[Bug tree-optimization/123236] `(signed)((unsigned long long)signed_var >> CST)` can be simplified to `signed_var >> CST`
cvs-commit at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Thu Aug 13 14:58:53 GMT 2026
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 <sayle@gcc.gnu.org>:
https://gcc.gnu.org/g:67ec3f5215298dd7f3177ed16c10c84392db8bb6
commit r17-3260-g67ec3f5215298dd7f3177ed16c10c84392db8bb6
Author: Roger Sayle <roger@nextmovesoftware.com>
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 <roger@nextmovesoftware.com>
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)).
More information about the Gcc-bugs
mailing list