https://gcc.gnu.org/g:0ff1ea6a6a2ec7dc57c962920e790d94cd286f39

commit r16-6019-g0ff1ea6a6a2ec7dc57c962920e790d94cd286f39
Author: Alexandre Oliva <[email protected]>
Date:   Wed Dec 10 20:56:17 2025 -0300

    x86: improve lea peepholes
    
    gcc.target/i386/lea-3.c fails on ia32 with PIE enabled by default.
    There are two reasons for that:
    
    - setting up the PIC register requires one addl instruction, and the
      testcase wants none
    
    - the expected lea-combining peephole doesn't get applied for two
      reasons:
    
    -- the second insn of the pair that could be turned into a single lea
       doesn't clobber CC, but the existing peephole2 requires an add with
       such a clobber
    
    -- the first and second insns set different regs, and the existing
       peephole2 requires them to be the same
    
    Add extra peephole2s for when the second insn doesn't clobber CC, and
    for when the first set reg is different, but it dies at the second
    insn.
    
    Adjust lea-3.c to run with -fno-PIE, and add lea-4.c with -fPIE.
    
    The last of the newly-added peephole2s, that enables lea-4.c to pass,
    also hits during an i686-linux-gnu bootstrap (without PIE enabled),
    while building shared libraries for the target.  I haven't been able
    to exercise the other 2, but I haven't tried very hard, and I see no
    why they couldn't possibly hit, so I left them in.
    
    
    for  gcc/ChangeLog
    
            * config/i386/i386.md (lea peephole2): Add 3 new variants.
    
    for  gcc/testsuite/ChangeLog
    
            * gcc.target/i386/lea-3.c: Add -fno-PIE.
            * gcc.target/i386/lea-4.c: New, with -fPIE.

Diff:
---
 gcc/config/i386/i386.md               | 42 +++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/lea-3.c |  2 +-
 gcc/testsuite/gcc.target/i386/lea-4.c | 16 +++++++++++++
 3 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index df7135f84d47..b5d838934251 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -6452,6 +6452,48 @@
   [(set (match_dup 0) (plus:SWI48 (plus:SWI48 (match_dup 0)
                                              (match_dup 1))
                                  (match_dup 2)))])
+
+(define_peephole2
+  [(parallel [(set (match_operand:SWI48 0 "register_operand")
+                  (plus:SWI48 (match_dup 0)
+                              (match_operand 1 "register_operand")))
+             (clobber (reg:CC FLAGS_REG))])
+   (set (match_dup 0)
+       (plus:SWI48 (match_dup 0)
+                   (match_operand 2 "x86_64_immediate_operand")))]
+  "!TARGET_AVOID_LEA_FOR_ADDR || optimize_function_for_size_p (cfun)"
+  [(set (match_dup 0) (plus:SWI48 (plus:SWI48 (match_dup 0)
+                                             (match_dup 1))
+                                 (match_dup 2)))])
+
+(define_peephole2
+  [(parallel [(set (match_operand:SWI48 0 "register_operand")
+                  (plus:SWI48 (match_dup 0)
+                              (match_operand 1 "register_operand")))
+             (clobber (reg:CC FLAGS_REG))])
+   (parallel [(set (match_operand:SWI48 3 "register_operand")
+                  (plus:SWI48 (match_dup 0)
+                              (match_operand 2 "x86_64_immediate_operand")))
+             (clobber (reg:CC FLAGS_REG))])]
+  "(!TARGET_AVOID_LEA_FOR_ADDR || optimize_function_for_size_p (cfun))
+   && peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 3) (plus:SWI48 (plus:SWI48 (match_dup 0)
+                                             (match_dup 1))
+                                 (match_dup 2)))])
+
+(define_peephole2
+  [(parallel [(set (match_operand:SWI48 0 "register_operand")
+                  (plus:SWI48 (match_dup 0)
+                              (match_operand 1 "register_operand")))
+             (clobber (reg:CC FLAGS_REG))])
+   (set (match_operand:SWI48 3 "register_operand")
+       (plus:SWI48 (match_dup 0)
+                   (match_operand 2 "x86_64_immediate_operand")))]
+  "(!TARGET_AVOID_LEA_FOR_ADDR || optimize_function_for_size_p (cfun))
+   && peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 3) (plus:SWI48 (plus:SWI48 (match_dup 0)
+                                             (match_dup 1))
+                                 (match_dup 2)))])
 
 ;; Add instructions
 
diff --git a/gcc/testsuite/gcc.target/i386/lea-3.c 
b/gcc/testsuite/gcc.target/i386/lea-3.c
index 84e66b00fc25..ce50531f9354 100644
--- a/gcc/testsuite/gcc.target/i386/lea-3.c
+++ b/gcc/testsuite/gcc.target/i386/lea-3.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fno-PIE" } */
 
 int m;
 
diff --git a/gcc/testsuite/gcc.target/i386/lea-4.c 
b/gcc/testsuite/gcc.target/i386/lea-4.c
new file mode 100644
index 000000000000..7bb2cec6d853
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/lea-4.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIE" } */
+/* Same as lea-3.c, but with -fPIE.  On ia32, that requires setting up the PIC
+   register, which requires an addl instruction.  */
+
+int m;
+
+int foo(int y)
+{
+  return (m+y-1)/y;
+}
+
+/* { dg-final { scan-assembler "leal" } } */
+/* { dg-final { scan-assembler-not "addl" { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-not "subl" } } */

Reply via email to