[gcc r17-3260] PR rtl-optimization/126315: Failure of gcc.target/arm/pr42879.c on armv7-a.

Roger Sayle via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:67ec3f5215298dd7f3177ed16c10c84392db8bb6

commit r17-3260-g67ec3f5215298dd7f3177ed16c10c84392db8bb6
Author: Roger Sayle <[email protected]>
Date:   Thu Aug 13 16:55:40 2026 +0200

    PR rtl-optimization/126315: Failure of gcc.target/arm/pr42879.c on armv7-a.
    
    My recent patch related to PR tree-optimization/123236
    triggers the testsuite failure of gcc.target/arm/pr42879.c
    which is a missed optimization on ARM with -mthumb where we
    now fail to emit the (shorter) lsls instruction.
    
    I believe this change simply exposes an underlying problem/wart
    in combine related to WORD_REGISTER_OPERATIONS, that has been
    present in the compiler for decades.
    
    My opinion is that on WORD_REGISTER_OPERATIONS targets, this
    transformation in combine can result in some very dubious RTL
    (containing a paradoxical SUBREG of an AND binary operator).
    As a result, thumb.md (reasonably) fails to match:
    
    Trying 11 -> 12:
       11: r102:SI=r98:QI#0&0x1
          REG_DEAD r98:QI
       12: cc:CC=cmp(r102:SI,0)
          REG_DEAD r102:SI
    Failed to match this instruction:
    (set (reg:CC 80 cc)
        (compare:CC (subreg:SI (and:QI (reg:QI 98 [ *p_6(D) ])
                    (const_int 1 [0x1])) 0)
            (const_int 0 [0])))
    
    One approach might be for WORD_REGISTER_OPERATIONS targets to
    match this poorly defined pseudo-canonical RTL.  Should the
    compare assume the paradoxical SUBREG is zero extended, sign
    extended or junk?  Clearly the results of the comparison do
    depend upon the high bits.
    
    Fortunately, simply disabling the offending transformation fixes
    this issue, with combine proposing very reasonable RTL, which is
    already matched by ARM's thumb.md:
    
    Trying 11 -> 12:
       11: r102:SI=r98:QI#0&0x1
          REG_DEAD r98:QI
       12: cc:CC=cmp(r102:SI,0)
          REG_DEAD r102:SI
    Successfully matched this instruction:
    (set (reg:CC_NZ 80 cc)
        (compare:CC_NZ (zero_extract:SI (subreg:SI (reg:QI 98 [ *p_6(D) ]) 0)
                (const_int 1 [0x1])
                (const_int 0 [0]))
            (const_int 0 [0])))
    Successfully matched this instruction:
    (set (pc)
        (if_then_else (ne (reg:CC_NZ 80 cc)
                (const_int 0 [0]))
            (label_ref 18)
            (pc)))
    allowing combination of insns 11 and 12
    original costs 4 + 4 = 24
    replacement cost 20
    deferring deletion of insn with uid = 11.
    modifying other_insn    13: pc={(cc:CC_NZ!=0)?L18:pc}
          REG_DEAD cc:CC
          REG_BR_PROB 548896825
    deferring rescan insn with uid = 13.
    modifying insn i3    12: cc:CC_NZ=cmp(zero_extract(r98:QI#0,0x1,0),0)
          REG_DEAD r98:QI
    deferring rescan insn with uid = 12.
    
    2026-08-13  Roger Sayle  <[email protected]>
    
    gcc/ChangeLog
            PR rtl-optimization/126315
            * combine.cc (simplify_comparison) <case AND>: Delete
            transformation that changed (AND (SUBREG x) C) into the
            non-canonical (SUBREG (AND x C)).

Diff:
---
 gcc/combine.cc | 44 --------------------------------------------
 1 file changed, 44 deletions(-)

diff --git a/gcc/combine.cc b/gcc/combine.cc
index 6ee3c1a07cdf..743026317ce4 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -12872,50 +12872,6 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	      continue;
 	    }
 
-	  /* If this is (and:M1 (subreg:M1 X:M2 0) (const_int C1)) where C1
-	     fits in both M1 and M2 and the SUBREG is either paradoxical
-	     or represents the low part, permute the SUBREG and the AND
-	     and try again.  */
-	  if (GET_CODE (XEXP (op0, 0)) == SUBREG
-	      && CONST_INT_P (XEXP (op0, 1)))
-	    {
-	      unsigned HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1));
-	      /* Require an integral mode, to avoid creating something like
-		 (AND:SF ...).  */
-	      if ((is_a <scalar_int_mode>
-		   (GET_MODE (SUBREG_REG (XEXP (op0, 0))), &tmode))
-		  /* It is unsafe to commute the AND into the SUBREG if the
-		     SUBREG is paradoxical and WORD_REGISTER_OPERATIONS is
-		     not defined.  As originally written the upper bits
-		     have a defined value due to the AND operation.
-		     However, if we commute the AND inside the SUBREG then
-		     they no longer have defined values and the meaning of
-		     the code has been changed.
-		     Also C1 should not change value in the smaller mode,
-		     see PR67028 (a positive C1 can become negative in the
-		     smaller mode, so that the AND does no longer mask the
-		     upper bits).  */
-		  && ((WORD_REGISTER_OPERATIONS
-		       && mode_width > GET_MODE_PRECISION (tmode)
-		       && mode_width <= BITS_PER_WORD
-		       && trunc_int_for_mode (c1, tmode) == (HOST_WIDE_INT) c1)
-		      || (mode_width <= GET_MODE_PRECISION (tmode)
-			  && subreg_lowpart_p (XEXP (op0, 0))))
-		  && mode_width <= HOST_BITS_PER_WIDE_INT
-		  && HWI_COMPUTABLE_MODE_P (tmode)
-		  && (c1 & ~mask) == 0
-		  && (c1 & ~GET_MODE_MASK (tmode)) == 0
-		  && c1 != mask
-		  && c1 != GET_MODE_MASK (tmode))
-		{
-		  op0 = simplify_gen_binary (AND, tmode,
-					     SUBREG_REG (XEXP (op0, 0)),
-					     gen_int_mode (c1, tmode));
-		  op0 = gen_lowpart (mode, op0);
-		  continue;
-		}
-	    }
-
 	  /* Convert (ne (and (not X) 1) 0) to (eq (and X 1) 0).  */
 	  if (const_op == 0 && equality_comparison_p
 	      && XEXP (op0, 1) == const1_rtx
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.