diff --git a/llvm/lib/Target/X86/X86FixupLEAs.cpp b/llvm/lib/Target/X86/X86FixupLEAs.cpp index b01145809ac6de..5c1ac8dd96715a 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 c929df8acfc1fb..d1de6793f0f718 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 2bab3c10e78e31..fe5c414a56f954 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 c85cc08f886b35..9a4cb55e52bd92 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 f834a9e2ed5f74..778e1f8fa4420f 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