Zhenqiang Chen wrote:

> Function noce_emit_store_flag tries to generate instruction to store flag by
> emit_store_flag for general_operand. For s390, CCU is a general _operand,
> but can not match cstorecc4, then it tries to generate a register move
> instruction from CCU to CCZ1, which will trigger an ICE.

OK, I think I see the problem now.  emit_store_flag calls emit_cstore, which
calls prepare_operand, which does:

  if (!insn_operand_matches (icode, opnum, x))
    {
      if (reload_completed)
        return NULL_RTX;
      x = copy_to_mode_reg (insn_data[(int) icode].operand[opnum].mode, x);
    }

The insn_operand_matches call will indeed fail since x has CCUmode, but
the operand only accepts CCZ1mode for this insn.

However, it is a bug to use copy_to_mode_reg with a mode different
from the mode of the RTX to be loaded (unless that RTX is a constant
of VOIDmode); copy_to_mode_reg will simply abort in that case.

Usually, this doesn't happen since prepare_operand is called on insns that
were already selected according to the operand mode.  However, this is
weakened for MODE_CC modes in emit_store_flag:

     machine_mode optab_mode = mclass == MODE_CC ? CCmode : compare_mode;
     icode = optab_handler (cstore_optab, optab_mode);

So the assumption seems to be that a cstorecc4 insn must accept *any*
MODE_CC mode, or else prepare_operand will abort.  I don't think this
requirement is really useful; on s390 there are good reasons to only
accept certain MODE_CC modes and ask the middle-end to fall back to
the generic implemention for others.

Thus I'd propose to add a mode check to prepare_operand and simply fail
instead of aborting if the mode doesn't match what the insn expects.
The appended patch does this; it fixes the ICEs when adding your patch.

Tested on s390x-ibm-linux.

Richard, does this look reasonable to you?

Bye,
Ulrich

ChangeLog:

        * optabs.c (prepare_operand): Gracefully fail if the mode of X
        does not match the operand mode expected by the insn pattern.

Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c        (revision 217416)
--- gcc/optabs.c        (working copy)
*************** prepare_operand (enum insn_code icode, r
*** 4308,4316 ****
  
    if (!insn_operand_matches (icode, opnum, x))
      {
        if (reload_completed)
        return NULL_RTX;
!       x = copy_to_mode_reg (insn_data[(int) icode].operand[opnum].mode, x);
      }
  
    return x;
--- 4308,4319 ----
  
    if (!insn_operand_matches (icode, opnum, x))
      {
+       machine_mode op_mode = insn_data[(int) icode].operand[opnum].mode;
        if (reload_completed)
        return NULL_RTX;
!       if (GET_MODE (x) != op_mode && GET_MODE (x) != VOIDmode)
!       return NULL_RTX;
!       x = copy_to_mode_reg (op_mode, x);
      }
  
    return x;



-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  ulrich.weig...@de.ibm.com

Reply via email to