Richard Biener wrote: > This probably caused bootstrap on s390x-linux to fail as in PR63952 > (last checked with rev. 217714).
It seems we have both a back-end bug and a middle-end bug here. First of all, this code in optabs.c:prepare_cmp_insn is quite strange: if (GET_MODE_CLASS (mode) == MODE_CC) { gcc_assert (can_compare_p (comparison, CCmode, ccp_jump)); *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y); return; } Note that can_compare_p checks whether the back-end accepts a test RTX created via: test = gen_rtx_fmt_ee (code, mode, const0_rtx, const0_rtx); All back-end cbranchcc4 patterns however verify that the first operand of the comparison is the flags register, so a const0_rtx will never match. It doesn't seem useful to call can_compare_p with CCmode at all. The patch below changes prepare_cmp_insn do do an explicit insn_operand_matches test using the actual operands, just like is also done for non-CCmode comparisons. However, even so this is still rejected by the s390 back end. This is because the s390 cbranchcc4 pattern is really quite wrong; it is restricted to accepting only EQ/NE comparisons when it could simply accept any valid comparison (i.e. where s390_comparison is true). In addition, it has a TARGET_HARD_FLOAT check for no reason I can see, and it has custom expander code that is in all cases a no-op and results in exactly the pattern in the insn to be emitted anyway. Fixed by the patch below as well. Tested on s390x-ibm-linux (with and without --with-arch=z196). OK for mainline? Bye, Ulrich ChangeLog: PR rtl-optimization/63952 * optabs.c (prepare_cmp_insn): Do not call can_compare_p for CCmode. * config/s390/s390.md ("cbranchcc4"): Accept any s390_comparison. Remove incorrect TARGET_HARD_FLOAT check and no-op expander code. Index: gcc/optabs.c =================================================================== *** gcc/optabs.c (revision 217784) --- gcc/optabs.c (working copy) *************** prepare_cmp_insn (rtx x, rtx y, enum rtx *** 4167,4174 **** if (GET_MODE_CLASS (mode) == MODE_CC) { ! gcc_assert (can_compare_p (comparison, CCmode, ccp_jump)); ! *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y); return; } --- 4167,4177 ---- if (GET_MODE_CLASS (mode) == MODE_CC) { ! enum insn_code icode = optab_handler (cbranch_optab, CCmode); ! test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y); ! gcc_assert (icode != CODE_FOR_nothing ! && insn_operand_matches (icode, 0, test)); ! *ptest = test; return; } Index: gcc/config/s390/s390.md =================================================================== *** gcc/config/s390/s390.md (revision 217784) --- gcc/config/s390/s390.md (working copy) *************** *** 8142,8157 **** (define_expand "cbranchcc4" [(set (pc) ! (if_then_else (match_operator 0 "s390_eqne_operator" [(match_operand 1 "cc_reg_operand" "") ! (match_operand 2 "const0_operand" "")]) (label_ref (match_operand 3 "" "")) (pc)))] ! "TARGET_HARD_FLOAT" ! "s390_emit_jump (operands[3], ! s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2])); ! DONE;") ! ;; --- 8142,8154 ---- (define_expand "cbranchcc4" [(set (pc) ! (if_then_else (match_operator 0 "s390_comparison" [(match_operand 1 "cc_reg_operand" "") ! (match_operand 2 "const_int_operand" "")]) (label_ref (match_operand 3 "" "")) (pc)))] ! "" ! "") ;; -- Dr. Ulrich Weigand GNU/Linux compilers and toolchain ulrich.weig...@de.ibm.com