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