Hi Torbjorn,
I believe this size regression on ARM (thumb) is resolved by the attached patch.
This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check, both with and without --target_board=unix{-m32}
with no new failures. Ok for mainline?
Hopefully, Jeff can spin this on his farm to see whether this transformation
is still useful anywhere (and not just creating problems on ARM)?
2026-08-11 Roger Sayle <[email protected]>
gcc/ChangeLog
* combine.cc (simplify_comparison) <case AND>: Delete
transformation that changed (AND (SUBREG x) C) into the
non-canonical (SUBREG (AND (x C)).
Thanks in advance,
Cheers,
Roger
--
> -----Original Message-----
> From: Torbjorn SVENSSON <[email protected]>
> Sent: 10 August 2026 16:28
> To: Richard Biener <[email protected]>; Roger Sayle
> <[email protected]>; Richard Earnshaw (lists)
> <[email protected]>
> Cc: GCC Patches <[email protected]>; Jeffrey Law
> <[email protected]>; Richard Sandiford
> <[email protected]>
> Subject: Re: [PATCH v2] PR middle-end/123236: Simplify (int)((long long)x >>
> 4)
>
> Hi,
>
> This change introduces a (size) regression for arm-none-eabi:
>
>
> Testing arm/pr42879.c
> doing compile
> Executing on host: /build/r17-2833-g32657f29f91871/bin/arm-none-eabi-gcc
> /build/gcc_src/gcc/testsuite/gcc.target/arm/pr42879.c -mthumb -
> march=armv7-m -mcpu=cortex-m3 -mfloat-abi=soft -mfpu=auto -fdiagnostics-
> plain-output -mthumb -Os -ffat-lto-objects -fno-ident -S -o pr42879.s
> (timeout = 800)
> spawn -ignore SIGHUP /build/r17-2833-g32657f29f91871/bin/arm-none-eabi-gcc
> /build/gcc_src/gcc/testsuite/gcc.target/arm/pr42879.c -mthumb -march=armv7-
> m -mcpu=cortex-m3 -mfloat-abi=soft -mfpu=auto -fdiagnostics-plain-output -
> mthumb -Os -ffat-lto-objects -fno-ident -S -o pr42879.s pid is 180 -180 pid
> is -1
> output is status 0
>
> PASS: gcc.target/arm/pr42879.c (test for excess errors)
> FAIL: gcc.target/arm/pr42879.c scan-assembler lsls
>
>
>
> $ /build/r17-2412-g2fcbe075ec3b32/bin/arm-none-eabi-gcc
> /build/gcc_src/gcc/testsuite/gcc.target/arm/pr42879.c -mthumb -march=armv7-
> m -mcpu=cortex-m3 -mfloat-abi=soft -mfpu=auto -Os -fno-ident -S -o -
> .cpu cortex-m3
> .arch armv7-m
> .fpu softvfp
> .eabi_attribute 20, 1
> .eabi_attribute 21, 1
> .eabi_attribute 23, 3
> .eabi_attribute 24, 1
> .eabi_attribute 25, 1
> .eabi_attribute 26, 1
> .eabi_attribute 30, 4
> .eabi_attribute 34, 1
> .eabi_attribute 18, 4
> .file "pr42879.c"
> .text
> .align 1
> .global foo
> .syntax unified
> .thumb
> .thumb_func
> .type foo, %function
> foo:
> @ args = 0, pretend = 0, frame = 0
> @ frame_needed = 0, uses_anonymous_args = 0
> @ link register save eliminated.
> ldrb r3, [r0] @ zero_extendqisi2
> lsls r3, r3, #31
> bmi .L2
> b bar
> .L2:
> movs r0, #1
> bx lr
> .size foo, .-foo
>
>
> $ /build/r17-2413-ge46d96d20bbfa7/bin/arm-none-eabi-gcc
> /build/gcc_src/gcc/testsuite/gcc.target/arm/pr42879.c -mthumb -march=armv7-
> m -mcpu=cortex-m3 -mfloat-abi=soft -mfpu=auto -Os -fno-ident -S -o -
> .cpu cortex-m3
> .arch armv7-m
> .fpu softvfp
> .eabi_attribute 20, 1
> .eabi_attribute 21, 1
> .eabi_attribute 23, 3
> .eabi_attribute 24, 1
> .eabi_attribute 25, 1
> .eabi_attribute 26, 1
> .eabi_attribute 30, 4
> .eabi_attribute 34, 1
> .eabi_attribute 18, 4
> .file "pr42879.c"
> .text
> .align 1
> .global foo
> .syntax unified
> .thumb
> .thumb_func
> .type foo, %function
> foo:
> @ args = 0, pretend = 0, frame = 0
> @ frame_needed = 0, uses_anonymous_args = 0
> @ link register save eliminated.
> ldrb r3, [r0] @ zero_extendqisi2
> and r3, r3, #1
> cbnz r3, .L2
> b bar
> .L2:
> movs r0, #1
> bx lr
> .size foo, .-foo
>
>
>
> Kind regards,
> Torbjörn
>
> On 2026-07-14 11:07, Richard Biener wrote:
> > On Fri, Jul 10, 2026 at 7:44 PM Roger Sayle <[email protected]>
> wrote:
> >>
> >>
> >> Long story... Back in January I proposed the following patch:
> >> https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705292.html
> >> which contained two pieces, one in combine, the other in simplify-rtx.
> >> Both of which were initially approved by Jeff Law here
> >> https://gcc.gnu.org/pipermail/gcc-patches/2026-May/715595.html
> >> but then Richard Sandiford pointed out the combine piece might cause
> >> problems on RISC machines, and suggested improvements.
> >> https://gcc.gnu.org/pipermail/gcc-patches/2026-May/715668.html
> >>
> >> In addition to making Richard's recommended changes, I've also
> >> decided to split the patch into two, to enable bisection and isolate
> >> these transformations [in case Richard S's fears come to pass and the
> >> combine transformation needs to be reverted].
> >>
> >> This is the "safe" (or less controversial) half. Hopefully, folks
> >> are (still) happy for this bit to be committed?
> >> p.s. the second and third hunks are just micro-optimizations; we
> >> don't need to call simplify_gen_unary (TRUNCATE, ...) if the operand
> >> already has the correct mode. The significant change is that the
> >> modes don't need to match, and the operand need not be a register
> >> [combine can put anything in a SUBREG].
> >>
> >> This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
> >> and make -k check, both with and without --target_board=unix{-m32},
> >> with no new failures. Ok for mainline?
> >
> > OK.
> >
> > Thanks,
> > Richard.
> >
> >>
> >> 2026-07-10 Roger Sayle <[email protected]>
> >>
> >> gcc/ChangeLog
> >> PR rtl-optimization/123236
> >> * simplify-rtx.cc (simplify_context::simplify_truncation): Handle
> >> cases where a ZERO_EXTRACT or SIGN_EXTRACT has a different mode
> >> to (but at least as wide as) its first operand.
> >>
> >> gcc/testsuite/ChangeLog
> >> PR rtl-optimization/123236
> >> * gcc.target/i386/pr123236-1.c: New test case.
> >>
> >>
> >> Thank again,
> >> Roger
> >> --
> >>
diff --git a/gcc/combine.cc b/gcc/combine.cc
index 53ea168a44b..bb3d41bafd7 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -12869,50 +12869,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