[llvm] a2f4534 - Transform slow LEA_B_I_D/LEA_SLOWBASE_I -> LEA_IS_D/LEA_IS iff base == index

Noah Goldstein via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 31 23:26:39 PST 2023


Author: Noah Goldstein
Date: 2023-02-01T01:26:06-06:00
New Revision: a2f45348d4ea93434d166ab9c6f73a28dba18595

URL: https://github.com/llvm/llvm-project/commit/a2f45348d4ea93434d166ab9c6f73a28dba18595
DIFF: https://github.com/llvm/llvm-project/commit/a2f45348d4ea93434d166ab9c6f73a28dba18595.diff

LOG: Transform slow LEA_B_I_D/LEA_SLOWBASE_I -> LEA_IS_D/LEA_IS iff base == index

The two 3c LEA cases:
    lea D(base, index,1)      -> lea D(,index,2)
    lea D(r13/rbp, index)     -> lea D(,r13/rbp,2) // D maybe zero

Current take 2 instructions to transform. We can do a bit better by
using LEA w.o a base if base == index and scale == 1.

Reviewed By: pengfei

Differential Revision: https://reviews.llvm.org/D141980

Added: 
    

Modified: 
    llvm/lib/Target/X86/X86FixupLEAs.cpp
    llvm/test/CodeGen/X86/leaFixup32.mir
    llvm/test/CodeGen/X86/leaFixup64.mir
    llvm/test/CodeGen/X86/select-1-or-neg1.ll
    llvm/test/DebugInfo/MIR/InstrRef/x86-lea-fixup-2.mir

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86FixupLEAs.cpp b/llvm/lib/Target/X86/X86FixupLEAs.cpp
index b01145809ac6d..5c1ac8dd96715 100644
--- a/llvm/lib/Target/X86/X86FixupLEAs.cpp
+++ b/llvm/lib/Target/X86/X86FixupLEAs.cpp
@@ -786,12 +786,34 @@ void FixupLEAPass::processInstrForSlow3OpLEA(MachineBasicBlock::iterator &I,
   LLVM_DEBUG(dbgs() << "FixLEA: Replaced by: ";);
 
   MachineInstr *NewMI = nullptr;
+  bool BaseOrIndexIsDst = DestReg == BaseReg || DestReg == IndexReg;
+  // First try and remove the base while sticking with LEA iff base == index and
+  // scale == 1. We can handle:
+  //    1. lea D(%base,%index,1)   -> lea D(,%index,2)
+  //    2. lea D(%r13/%rbp,%index) -> lea D(,%index,2)
+  // Only do this if the LEA would otherwise be split into 2-instruction
+  // (either it has a an Offset or neither base nor index are dst)
+  if (IsScale1 && BaseReg == IndexReg &&
+      (hasLEAOffset(Offset) || (IsInefficientBase && !BaseOrIndexIsDst))) {
+    NewMI = BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(LEAOpcode))
+                .add(Dest)
+                .addReg(0)
+                .addImm(2)
+                .add(Index)
+                .add(Offset)
+                .add(Segment);
+    LLVM_DEBUG(NewMI->dump(););
+
+    MBB.getParent()->substituteDebugValuesForInst(*I, *NewMI, 1);
+    MBB.erase(I);
+    I = NewMI;
+    return;
+  } else if (IsScale1 && BaseOrIndexIsDst) {
+    // Try to replace LEA with one or two (for the 3-op LEA case)
+    // add instructions:
+    // 1.lea (%base,%index,1), %base => add %index,%base
+    // 2.lea (%base,%index,1), %index => add %base,%index
 
-  // First try to replace LEA with one or two (for the 3-op LEA case)
-  // add instructions:
-  // 1.lea (%base,%index,1), %base => add %index,%base
-  // 2.lea (%base,%index,1), %index => add %base,%index
-  if (IsScale1 && (DestReg == BaseReg || DestReg == IndexReg)) {
     unsigned NewOpc = getADDrrFromLEA(MI.getOpcode());
     if (DestReg != BaseReg)
       std::swap(BaseReg, IndexReg);

diff  --git a/llvm/test/CodeGen/X86/leaFixup32.mir b/llvm/test/CodeGen/X86/leaFixup32.mir
index c929df8acfc1f..d1de6793f0f71 100644
--- a/llvm/test/CodeGen/X86/leaFixup32.mir
+++ b/llvm/test/CodeGen/X86/leaFixup32.mir
@@ -48,15 +48,15 @@
     ret i32 0
   }
 
-  ;test1mov1add_ebp_32: 2 operands LEA32r that can be replaced with 1 add 1 mov instructions
+  ;test_leab_ebp_leais_32: 2 operands LEA32r that can be replaced with LEA_IS form
   ; where the base is rbp/r13/ebp register
-  define i32 @test1mov1add_ebp_32() {
+  define i32 @test_leab_ebp_leais_32() {
     ret i32 0
   }
 
-  ;testleaadd_ebp_index_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions
+  ;test_leabi_ebp_leais_32: 3 operands LEA32r that can be replaced with LEA_IS form
   ; where the base and the index are ebp register and there is offset
-  define i32 @testleaadd_ebp_index_32() {
+  define i32 @test_leabi_ebp_leais_32() {
     ret i32 0
   }
 
@@ -345,7 +345,7 @@ body:             |
 
 ...
 ---
-name:            test1mov1add_ebp_32
+name:            test_leab_ebp_leais_32
 alignment:       16
 exposesReturnsTwice: false
 legalized:       false
@@ -374,17 +374,16 @@ body:             |
   bb.0 (%ir-block.0):
     liveins: $eax, $ebp, $ebx
 
-    ; CHECK-LABEL: name: test1mov1add_ebp_32
+    ; CHECK-LABEL: name: test_leab_ebp_leais_32
     ; CHECK: liveins: $eax, $ebp, $ebx
-    ; CHECK: $ebx = MOV32rr $ebp
-    ; CHECK: $ebx = ADD32rr $ebx, $ebp, implicit-def $eflags
+    ; CHECK: $ebx = LEA32r $noreg, 2, $ebp, 0, $noreg
     ; CHECK: RET64 $ebx
     $ebx = LEA32r killed $ebp, 1, $ebp, 0, $noreg
     RET64 $ebx
 
 ...
 ---
-name:            testleaadd_ebp_index_32
+name:            test_leabi_ebp_leais_32
 alignment:       16
 exposesReturnsTwice: false
 legalized:       false
@@ -412,10 +411,9 @@ body:             |
   bb.0 (%ir-block.0):
     liveins: $eax, $ebp, $ebx
 
-    ; CHECK-LABEL: name: testleaadd_ebp_index_32
+    ; CHECK-LABEL: name: test_leabi_ebp_leais_32
     ; CHECK: liveins: $eax, $ebp, $ebx
-    ; CHECK: $ebx = LEA32r $noreg, 1, $ebp, 5, $noreg
-    ; CHECK: $ebx = ADD32rr $ebx, $ebp, implicit-def $eflags
+    ; CHECK: $ebx = LEA32r $noreg, 2, $ebp, 5, $noreg
     ; CHECK: RET64 $ebx
     $ebx = LEA32r $ebp, 1, $ebp, 5, $noreg
     RET64 $ebx

diff  --git a/llvm/test/CodeGen/X86/leaFixup64.mir b/llvm/test/CodeGen/X86/leaFixup64.mir
index 2bab3c10e78e3..fe5c414a56f95 100644
--- a/llvm/test/CodeGen/X86/leaFixup64.mir
+++ b/llvm/test/CodeGen/X86/leaFixup64.mir
@@ -86,15 +86,15 @@
     ret i32 0
   }
 
-  ;test1mov1add_rbp_64_32: 2 operands LEA64_32r cannot be replaced with 1 add 1 mov instructions
+  ;test_leab_rbp_leais_64_32: 2 operands LEA64_32r that can be replaced with LEA_IS form
   ; where the base is rbp/r13/ebp register
-  define i32 @test1mov1add_rbp_64_32() {
+  define i32 @test_leab_rbp_leais_64_32() {
     ret i32 0
   }
 
-  ;testleaadd_rbp_index_64_32: 3 operands LEA64_32r that cannot replaced with 1 lea 1 add instructions
+  ;test_leabi_rbp_leais_64_32: 3 operands LEA64_32r that can be replaced with LEA_IS form
   ; where the base and the index are ebp register and there is offset
-  define i32 @testleaadd_rbp_index_64_32() {
+  define i32 @test_leabi_rbp_leais_64_32() {
     ret i32 0
   }
 
@@ -110,15 +110,15 @@
     ret i32 0
   }
 
-  ;test1mov1add_rbp_64: 2 operands LEA64r that can be replaced with 1 add 1 mov instructions
+  ;test_leab_rbp_leais_64: 2 operands LEA64r that can be replaced with LEA_IS form
   ; where the base is rbp/r13/ebp register
-  define i32 @test1mov1add_rbp_64() {
+  define i32 @test_leab_rbp_leais_64() {
     ret i32 0
   }
 
-  ;testleaadd_rbp_index_64: 3 operands LEA64r that can be replaced with 1 lea 1 add instructions
+  ;test_leabi_rbp_leais_64: 3 operands LEA64r that can be replaced with LEA_IS form
   ; where the base and the index are ebp register and there is offset
-  define i32 @testleaadd_rbp_index_64() {
+  define i32 @test_leabi_rbp_leais_64() {
     ret i32 0
   }
 
@@ -692,7 +692,7 @@ body:             |
 
 ...
 ---
-name:            test1mov1add_rbp_64_32
+name:            test_leab_rbp_leais_64_32
 alignment:       16
 exposesReturnsTwice: false
 legalized:       false
@@ -720,16 +720,16 @@ body:             |
   bb.0 (%ir-block.0):
     liveins: $rax, $rbp, $rbx
 
-    ; CHECK-LABEL: name: test1mov1add_rbp_64_32
+    ; CHECK-LABEL: name: test_leab_rbp_leais_64_32
     ; CHECK: liveins: $rax, $rbp, $rbx
-    ; CHECK: $ebx = LEA64_32r killed $rbp, 1, killed $rbp, 0, $noreg
+    ; CHECK: $ebx = LEA64_32r $noreg, 2, killed $rbp, 0, $noreg
     ; CHECK: RET64 $ebx
     $ebx = LEA64_32r killed $rbp, 1, killed $rbp, 0, $noreg
     RET64 $ebx
 
 ...
 ---
-name:            testleaadd_rbp_index_64_32
+name:            test_leabi_rbp_leais_64_32
 alignment:       16
 exposesReturnsTwice: false
 legalized:       false
@@ -757,9 +757,9 @@ body:             |
   bb.0 (%ir-block.0):
     liveins: $rax, $rbp, $rbx
 
-    ; CHECK-LABEL: name: testleaadd_rbp_index_64_32
+    ; CHECK-LABEL: name: test_leabi_rbp_leais_64_32
     ; CHECK: liveins: $rax, $rbp, $rbx
-    ; CHECK: $ebx = LEA64_32r killed $rbp, 1, killed $rbp, 5, $noreg
+    ; CHECK: $ebx = LEA64_32r $noreg, 2, killed $rbp, 5, $noreg
     ; CHECK: RET64 $ebx
     $ebx = LEA64_32r killed $rbp, 1, killed $rbp, 5, $noreg
     RET64 $ebx
@@ -841,7 +841,7 @@ body:             |
 
 ...
 ---
-name:            test1mov1add_rbp_64
+name:            test_leab_rbp_leais_64
 alignment:       16
 exposesReturnsTwice: false
 legalized:       false
@@ -869,17 +869,16 @@ body:             |
   bb.0 (%ir-block.0):
     liveins: $rax, $rbp, $rbx
 
-    ; CHECK-LABEL: name: test1mov1add_rbp_64
+    ; CHECK-LABEL: name: test_leab_rbp_leais_64
     ; CHECK: liveins: $rax, $rbp, $rbx
-    ; CHECK: $rbx = MOV64rr $rbp
-    ; CHECK: $rbx = ADD64rr $rbx, $rbp, implicit-def $eflags
+    ; CHECK: $rbx = LEA64r $noreg, 2, $rbp, 0, $noreg
     ; CHECK: RET64 $ebx
     $rbx = LEA64r killed $rbp, 1, $rbp, 0, $noreg
     RET64 $ebx
 
 ...
 ---
-name:            testleaadd_rbp_index_64
+name:            test_leabi_rbp_leais_64
 alignment:       16
 exposesReturnsTwice: false
 legalized:       false
@@ -907,10 +906,9 @@ body:             |
   bb.0 (%ir-block.0):
     liveins: $rax, $rbp, $rbx
 
-    ; CHECK-LABEL: name: testleaadd_rbp_index_64
+    ; CHECK-LABEL: name: test_leabi_rbp_leais_64
     ; CHECK: liveins: $rax, $rbp, $rbx
-    ; CHECK: $rbx = LEA64r $noreg, 1, $rbp, 5, $noreg
-    ; CHECK: $rbx = ADD64rr $rbx, $rbp, implicit-def $eflags
+    ; CHECK: $rbx = LEA64r $noreg, 2, $rbp, 5, $noreg
     ; CHECK: RET64 $ebx
     $rbx = LEA64r $rbp, 1, $rbp, 5, $noreg
     RET64 $ebx

diff  --git a/llvm/test/CodeGen/X86/select-1-or-neg1.ll b/llvm/test/CodeGen/X86/select-1-or-neg1.ll
index c85cc08f886b3..9a4cb55e52bd9 100644
--- a/llvm/test/CodeGen/X86/select-1-or-neg1.ll
+++ b/llvm/test/CodeGen/X86/select-1-or-neg1.ll
@@ -19,8 +19,7 @@ define i32 @PR28968(i32 %x) {
 ; SLOWLEA3-NEXT:    xorl %eax, %eax
 ; SLOWLEA3-NEXT:    cmpl $1, %edi
 ; SLOWLEA3-NEXT:    sete %al
-; SLOWLEA3-NEXT:    addl %eax, %eax
-; SLOWLEA3-NEXT:    decl %eax
+; SLOWLEA3-NEXT:    leal -1(,%rax,2), %eax
 ; SLOWLEA3-NEXT:    retq
   %cmp = icmp eq i32 %x, 1
   %sel = select i1 %cmp, i32 1, i32 -1

diff  --git a/llvm/test/DebugInfo/MIR/InstrRef/x86-lea-fixup-2.mir b/llvm/test/DebugInfo/MIR/InstrRef/x86-lea-fixup-2.mir
index f834a9e2ed5f7..778e1f8fa4420 100644
--- a/llvm/test/DebugInfo/MIR/InstrRef/x86-lea-fixup-2.mir
+++ b/llvm/test/DebugInfo/MIR/InstrRef/x86-lea-fixup-2.mir
@@ -23,8 +23,8 @@ body:             |
 
 ...
 ---
-name:            test1mov1add_ebp_32
-# CHECK-LABEL: name: test1mov1add_ebp_32
+name:            testleais_ebp_32
+# CHECK-LABEL: name: testleais_ebp_32
 alignment:       16
 tracksRegLiveness: true
 debugInstrRef: true
@@ -38,14 +38,14 @@ body:             |
   bb.0:
     liveins: $eax, $ebp, $ebx
 
-    ; CHECK: $ebx = ADD32rr {{.*}} debug-instr-number 2
+    ; CHECK: $ebx = LEA32r $noreg, 2, $ebp, 0, $noreg, debug-instr-number 2
     $ebx = LEA32r killed $ebp, 1, $ebp, 0, $noreg, debug-instr-number 1
     RET64 $ebx
 
 ...
 ---
-name:            testleaadd_ebp_index_32
-# CHECK-LABEL: name: testleaadd_ebp_index_32
+name:            testleabid_ebp_leaisd_32
+# CHECK-LABEL: name: testleabid_ebp_leaisd_32
 alignment:       16
 tracksRegLiveness: true
 debugInstrRef: true
@@ -58,7 +58,7 @@ body:             |
   bb.0:
     liveins: $eax, $ebp, $ebx
 
-    ; CHECK: $ebx = ADD32rr {{.*}} debug-instr-number 2
+    ; CHECK: $ebx = LEA32r $noreg, 2, $ebp, 5, $noreg, debug-instr-number 2
     $ebx = LEA32r $ebp, 1, $ebp, 5, $noreg, debug-instr-number 1
     RET64 $ebx
 


        


More information about the llvm-commits mailing list