[gcc r17-2413] PR middle-end/123236: Simplify (int)((long long)x >> 4)

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

commit r17-2413-ge46d96d20bbfa786d30c9371631da00939845f05
Author: Roger Sayle <[email protected]>
Date:   Wed Jul 15 12:26:16 2026 +0100

    PR middle-end/123236: Simplify (int)((long long)x >> 4)
    
    This patch addresses a code quality regression on x86_64 related to
    PR 123236.  That original PR (and the related PR 101266) concern tree
    level optimizations, where this problem should also be fixed, but it
    also reveals a regression in the RTL optimizers.
    
    A motivating test case (on x86_64) is:
    
    int bar(int a) {
      long long t = a;
      return t >> 4;
    }
    
    Currently -O2 generates a 64-bit shift:
    bar:    movslq  %edi, %rax
            sarq    $4, %rax
            ret
    
    with this patch we now generate a 32-bit shift:
    bar:    movl    %edi, %eax
            sarl    $4, %eax
            ret
    
    The underlying cause of the RTL-level regression is that some
    RTL expressions that were previously expressed as {ZERO,SIGN}_EXTEND
    are now sometimes represented as the equivalent {ZERO,SIGN}_EXTRACT,
    and that not all simplifications of TRUNCATE({ZERO,SIGN}_EXTEND) are
    implemented for TRUNCATE({ZERO,SIGN}_EXTRACT).
    
    Thanks to Segher, simplify_rtx does handle some truncations of extracts,
    see https://gcc.gnu.org/pipermail/gcc-patches/2016-November/463629.html
    but unfortunately this code (and subsequent tweaks) doesn't quite match
    the cases that appear here.
    
    2026-07-15  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.

Diff:
---
 gcc/simplify-rtx.cc                        | 14 +++++++-------
 gcc/testsuite/gcc.target/i386/pr123236-1.c | 10 ++++++++++
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 92a2a6e954a8..882a11c5760d 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 000000000000..67e872f9b2d7
--- /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" } } */
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.