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
[email protected]