https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123236
--- Comment #3 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Roger Sayle <[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)).
