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

Reply via email to