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?


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/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 92a2a6e954a..882a11c5760 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -727,12 +727,10 @@ simplify_context::simplify_truncation (machine_mode mode, 
rtx op,
        }
     }
 
-  /* Turn (truncate:M1 (*_extract:M2 (reg:M2) (len) (pos))) into
-     (*_extract:M1 (truncate:M1 (reg:M2)) (len) (pos')) if possible without
-     changing len.  */
+  /* Turn (truncate:M1 (*_extract:M2 (reg:M3) (len) (pos))) into
+     (*_extract:M1 (truncate:M1 (reg:M3)) (len) (pos')) if possible.  */
   if ((GET_CODE (op) == ZERO_EXTRACT || GET_CODE (op) == SIGN_EXTRACT)
-      && REG_P (XEXP (op, 0))
-      && GET_MODE (XEXP (op, 0)) == GET_MODE (op)
+      && precision <= GET_MODE_UNIT_PRECISION (GET_MODE (XEXP (op, 0)))
       && CONST_INT_P (XEXP (op, 1))
       && CONST_INT_P (XEXP (op, 2)))
     {
@@ -741,7 +739,8 @@ simplify_context::simplify_truncation (machine_mode mode, 
rtx op,
       unsigned HOST_WIDE_INT pos = UINTVAL (XEXP (op, 2));
       if (BITS_BIG_ENDIAN && pos >= op_precision - precision)
        {
-         op0 = simplify_gen_unary (TRUNCATE, mode, op0, GET_MODE (op0));
+         if (GET_MODE (op0) != mode)
+           op0 = simplify_gen_unary (TRUNCATE, mode, op0, GET_MODE (op0));
          if (op0)
            {
              pos -= op_precision - precision;
@@ -751,7 +750,8 @@ simplify_context::simplify_truncation (machine_mode mode, 
rtx op,
        }
       else if (!BITS_BIG_ENDIAN && precision >= len + pos)
        {
-         op0 = simplify_gen_unary (TRUNCATE, mode, op0, GET_MODE (op0));
+         if (GET_MODE (op0) != mode)
+           op0 = simplify_gen_unary (TRUNCATE, mode, op0, GET_MODE (op0));
          if (op0)
            return simplify_gen_ternary (GET_CODE (op), mode, mode, op0,
                                         XEXP (op, 1), XEXP (op, 2));
diff --git a/gcc/testsuite/gcc.target/i386/pr123236-1.c 
b/gcc/testsuite/gcc.target/i386/pr123236-1.c
new file mode 100644
index 00000000000..67e872f9b2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr123236-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+int foo(int a) {
+  long long t = a;
+  return t >> 4;
+}
+
+/* { dg-final { scan-assembler-not "movslq" } } */
+/* { dg-final { scan-assembler-not "sarq" } } */

Reply via email to