<div dir="ltr">This patch is responsible for <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/4975" class="cremed">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/4975</a><div><br></div><div>Could you please fix or revert it?<br><div><br></div><div><div>[ RUN      ] MCJITCAPITest.custom_memory_manager</div><div>==30426==WARNING: MemorySanitizer: use-of-uninitialized-value</div><div>    #0 0x1866daf in processBasicBlock /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Target/X86/X86FixupLEAs.cpp:585:9</div><div>    #1 0x1866daf in (anonymous namespace)::FixupLEAPass::runOnMachineFunction(llvm::MachineFunction&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Target/X86/X86FixupLEAs.cpp:212</div><div>    #2 0x29558ee in llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/CodeGen/MachineFunctionPass.cpp:62:13</div><div>    #3 0xcd2510 in llvm::FPPassManager::runOnFunction(llvm::Function&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/IR/LegacyPassManager.cpp:1519:27</div><div>    #4 0xcd2c10 in llvm::FPPassManager::runOnModule(llvm::Module&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/IR/LegacyPassManager.cpp:1540:16</div><div>    #5 0xcd3fae in runOnModule /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/IR/LegacyPassManager.cpp:1596:27</div><div>    #6 0xcd3fae in llvm::legacy::PassManagerImpl::run(llvm::Module&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/IR/LegacyPassManager.cpp:1699</div><div>    #7 0xf5fb36 in llvm::MCJIT::emitObject(llvm::Module*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:165:6</div><div>    #8 0xf60547 in llvm::MCJIT::generateCodeForModule(llvm::Module*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:204:20</div><div>    #9 0xf62a73 in llvm::MCJIT::finalizeObject() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:259:5</div><div>    #10 0xe4a9ce in LLVMGetPointerToGlobal /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp:296:15</div><div>    #11 0x532faa in MCJITCAPITest_custom_memory_manager_Test::TestBody() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp:389:35</div><div>    #12 0x1d30ae1 in HandleExceptionsInMethodIfSupported<testing::Test, void> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2458:12</div><div>    #13 0x1d30ae1 in testing::Test::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2474</div><div>    #14 0x1d332e2 in testing::TestInfo::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2656:11</div><div>    #15 0x1d344df in testing::TestCase::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2774:28</div><div>    #16 0x1d51989 in testing::internal::UnitTestImpl::RunAllTests() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:4649:43</div><div>    #17 0x1d509a8 in HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2458:12</div><div>    #18 0x1d509a8 in testing::UnitTest::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:4257</div><div>    #19 0x1d17f47 in RUN_ALL_TESTS /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/include/gtest/gtest.h:2233:46</div><div>    #20 0x1d17f47 in main /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/UnitTestMain/TestMain.cpp:51</div><div>    #21 0x7eff7f30382f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)</div><div>    #22 0x4a3c08 in _start (/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm_build_msan/unittests/ExecutionEngine/MCJIT/MCJITTests+0x4a3c08)</div><div><br></div><div>SUMMARY: MemorySanitizer: use-of-uninitialized-value /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Target/X86/X86FixupLEAs.cpp:585:9 in processBasicBlock</div><div>Exiting</div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, May 16, 2017 at 9:15 AM Lama Saba via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: lsaba<br>
Date: Tue May 16 11:01:36 2017<br>
New Revision: 303183<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=303183&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=303183&view=rev</a><br>
Log:<br>
[X86] Replace slow LEA instructions in X86<br>
<br>
  According to Intel's Optimization Reference Manual for SNB+:<br>
  " For LEA instructions with three source operands and some specific situations, instruction latency has increased to 3 cycles, and must<br>
    dispatch via port 1:<br>
  - LEA that has all three source operands: base, index, and offset<br>
  - LEA that uses base and index registers where the base is EBP, RBP,or R13<br>
  - LEA that uses RIP relative addressing mode<br>
  - LEA that uses 16-bit addressing mode "<br>
  This patch currently handles the first 2 cases only.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D32277" rel="noreferrer" target="_blank">https://reviews.llvm.org/D32277</a><br>
<br>
<br>
Added:<br>
    llvm/trunk/test/CodeGen/X86/leaFixup32.mir<br>
    llvm/trunk/test/CodeGen/X86/leaFixup64.mir<br>
Modified:<br>
    llvm/trunk/lib/Target/X86/X86.td<br>
    llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp<br>
    llvm/trunk/lib/Target/X86/X86Subtarget.h<br>
    llvm/trunk/lib/Target/X86/X86TargetMachine.cpp<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.td?rev=303183&r1=303182&r2=303183&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.td?rev=303183&r1=303182&r2=303183&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86.td (original)<br>
+++ llvm/trunk/lib/Target/X86/X86.td Tue May 16 11:01:36 2017<br>
@@ -235,6 +235,8 @@ def FeatureLEAUsesAG : SubtargetFeature<<br>
                                    "LEA instruction needs inputs at AG stage">;<br>
 def FeatureSlowLEA : SubtargetFeature<"slow-lea", "SlowLEA", "true",<br>
                                    "LEA instruction with certain arguments is slow">;<br>
+def FeatureSlow3OpsLEA : SubtargetFeature<"slow-3ops-lea", "Slow3OpsLEA", "true",<br>
+                                   "LEA instruction with 3 ops or certain registers is slow">;<br>
 def FeatureSlowIncDec : SubtargetFeature<"slow-incdec", "SlowIncDec", "true",<br>
                                    "INC and DEC instructions are slower than ADD and SUB">;<br>
 def FeatureSoftFloat<br>
@@ -480,6 +482,7 @@ def SNBFeatures : ProcessorFeatures<[],<br>
   FeatureXSAVE,<br>
   FeatureXSAVEOPT,<br>
   FeatureLAHFSAHF,<br>
+  FeatureSlow3OpsLEA,<br>
   FeatureFastScalarFSQRT,<br>
   FeatureFastSHLDRotate<br>
 ]>;<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp?rev=303183&r1=303182&r2=303183&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp?rev=303183&r1=303182&r2=303183&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp Tue May 16 11:01:36 2017<br>
@@ -27,20 +27,26 @@<br>
 #include "llvm/Target/TargetInstrInfo.h"<br>
 using namespace llvm;<br>
<br>
-#define DEBUG_TYPE "x86-fixup-LEAs"<br>
+namespace llvm {<br>
+void initializeFixupLEAPassPass(PassRegistry &);<br>
+}<br>
+<br>
+#define FIXUPLEA_DESC "X86 LEA Fixup"<br>
+#define FIXUPLEA_NAME "x86-fixup-LEAs"<br>
+<br>
+#define DEBUG_TYPE FIXUPLEA_NAME<br>
<br>
 STATISTIC(NumLEAs, "Number of LEA instructions created");<br>
<br>
 namespace {<br>
 class FixupLEAPass : public MachineFunctionPass {<br>
   enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };<br>
-  static char ID;<br>
+<br>
   /// \brief Loop over all of the instructions in the basic block<br>
   /// replacing applicable instructions with LEA instructions,<br>
   /// where appropriate.<br>
   bool processBasicBlock(MachineFunction &MF, MachineFunction::iterator MFI);<br>
<br>
-  StringRef getPassName() const override { return "X86 LEA Fixup"; }<br>
<br>
   /// \brief Given a machine register, look for the instruction<br>
   /// which writes it in the current basic block. If found,<br>
@@ -62,6 +68,22 @@ class FixupLEAPass : public MachineFunct<br>
   void processInstructionForSLM(MachineBasicBlock::iterator &I,<br>
                                 MachineFunction::iterator MFI);<br>
<br>
+<br>
+  /// \brief Given a LEA instruction which is unprofitable<br>
+  /// on SNB+ try to replace it with other instructions.<br>
+  /// According to Intel's Optimization Reference Manual:<br>
+  /// " For LEA instructions with three source operands and some specific<br>
+  ///   situations, instruction latency has increased to 3 cycles, and must<br>
+  ///   dispatch via port 1:<br>
+  /// - LEA that has all three source operands: base, index, and offset<br>
+  /// - LEA that uses base and index registers where the base is EBP, RBP,<br>
+  ///   or R13<br>
+  /// - LEA that uses RIP relative addressing mode<br>
+  /// - LEA that uses 16-bit addressing mode "<br>
+  /// This function currently handles the first 2 cases only.<br>
+  MachineInstr *processInstrForSlow3OpLEA(MachineInstr &MI,<br>
+                                          MachineFunction::iterator MFI);<br>
+<br>
   /// \brief Look for LEAs that add 1 to reg or subtract 1 from reg<br>
   /// and convert them to INC or DEC respectively.<br>
   bool fixupIncDec(MachineBasicBlock::iterator &I,<br>
@@ -85,7 +107,13 @@ class FixupLEAPass : public MachineFunct<br>
                                    MachineBasicBlock::iterator &MBBI) const;<br>
<br>
 public:<br>
-  FixupLEAPass() : MachineFunctionPass(ID) {}<br>
+  static char ID;<br>
+<br>
+  StringRef getPassName() const override { return FIXUPLEA_DESC; }<br>
+<br>
+  FixupLEAPass() : MachineFunctionPass(ID) {<br>
+    initializeFixupLEAPassPass(*PassRegistry::getPassRegistry());<br>
+  }<br>
<br>
   /// \brief Loop over all of the basic blocks,<br>
   /// replacing instructions by equivalent LEA instructions<br>
@@ -104,9 +132,12 @@ private:<br>
   bool OptIncDec;<br>
   bool OptLEA;<br>
 };<br>
-char FixupLEAPass::ID = 0;<br>
 }<br>
<br>
+char FixupLEAPass::ID = 0;<br>
+<br>
+INITIALIZE_PASS(FixupLEAPass, FIXUPLEA_NAME, FIXUPLEA_DESC, false, false)<br>
+<br>
 MachineInstr *<br>
 FixupLEAPass::postRAConvertToLEA(MachineFunction::iterator &MFI,<br>
                                  MachineBasicBlock::iterator &MBBI) const {<br>
@@ -168,7 +199,7 @@ bool FixupLEAPass::runOnMachineFunction(<br>
   MF = &Func;<br>
   const X86Subtarget &ST = Func.getSubtarget<X86Subtarget>();<br>
   OptIncDec = !ST.slowIncDec() || Func.getFunction()->optForMinSize();<br>
-  OptLEA = ST.LEAusesAG() || ST.slowLEA();<br>
+  OptLEA = ST.LEAusesAG() || ST.slowLEA() || ST.slow3OpsLEA();<br>
<br>
   if (!OptLEA && !OptIncDec)<br>
     return false;<br>
@@ -242,9 +273,64 @@ FixupLEAPass::searchBackwards(MachineOpe<br>
   return MachineBasicBlock::iterator();<br>
 }<br>
<br>
-static inline bool isLEA(const int opcode) {<br>
-  return opcode == X86::LEA16r || opcode == X86::LEA32r ||<br>
-         opcode == X86::LEA64r || opcode == X86::LEA64_32r;<br>
+static inline bool isLEA(const int Opcode) {<br>
+  return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||<br>
+         Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;<br>
+}<br>
+<br>
+static inline bool isInefficientLEAReg(unsigned int Reg) {<br>
+  return Reg == X86::EBP || Reg == X86::RBP || Reg == X86::R13;<br>
+}<br>
+<br>
+static inline bool isRegOperand(const MachineOperand &Op) {<br>
+  return Op.isReg() && Op.getReg() != X86::NoRegister;<br>
+}<br>
+/// hasIneffecientLEARegs - LEA that uses base and index registers<br>
+/// where the base is EBP, RBP, or R13<br>
+static inline bool hasInefficientLEABaseReg(const MachineOperand &Base,<br>
+                                            const MachineOperand &Index) {<br>
+  return Base.isReg() && isInefficientLEAReg(Base.getReg()) &&<br>
+         isRegOperand(Index);<br>
+}<br>
+<br>
+static inline bool hasLEAOffset(const MachineOperand &Offset) {<br>
+  return (Offset.isImm() && Offset.getImm() != 0) || Offset.isGlobal();<br>
+}<br>
+<br>
+// LEA instruction that has all three operands: offset, base and index<br>
+static inline bool isThreeOperandsLEA(const MachineOperand &Base,<br>
+                                      const MachineOperand &Index,<br>
+                                      const MachineOperand &Offset) {<br>
+  return isRegOperand(Base) && isRegOperand(Index) && hasLEAOffset(Offset);<br>
+}<br>
+<br>
+static inline int getADDrrFromLEA(int LEAOpcode) {<br>
+  switch (LEAOpcode) {<br>
+  default:<br>
+    llvm_unreachable("Unexpected LEA instruction");<br>
+  case X86::LEA16r:<br>
+    return X86::ADD16rr;<br>
+  case X86::LEA32r:<br>
+    return X86::ADD32rr;<br>
+  case X86::LEA64_32r:<br>
+  case X86::LEA64r:<br>
+    return X86::ADD64rr;<br>
+  }<br>
+}<br>
+<br>
+static inline int getADDriFromLEA(int LEAOpcode, const MachineOperand &Offset) {<br>
+  bool IsInt8 = Offset.isImm() && isInt<8>(Offset.getImm());<br>
+  switch (LEAOpcode) {<br>
+  default:<br>
+    llvm_unreachable("Unexpected LEA instruction");<br>
+  case X86::LEA16r:<br>
+    return IsInt8 ? X86::ADD16ri8 : X86::ADD16ri;<br>
+  case X86::LEA32r:<br>
+  case X86::LEA64_32r:<br>
+    return IsInt8 ? X86::ADD32ri8 : X86::ADD32ri;<br>
+  case X86::LEA64r:<br>
+    return IsInt8 ? X86::ADD64ri8 : X86::ADD64ri32;<br>
+  }<br>
 }<br>
<br>
 /// isLEASimpleIncOrDec - Does this LEA have one these forms:<br>
@@ -337,8 +423,8 @@ void FixupLEAPass::seekLEAFixup(MachineO<br>
 void FixupLEAPass::processInstructionForSLM(MachineBasicBlock::iterator &I,<br>
                                             MachineFunction::iterator MFI) {<br>
   MachineInstr &MI = *I;<br>
-  const int opcode = MI.getOpcode();<br>
-  if (!isLEA(opcode))<br>
+  const int Opcode = MI.getOpcode();<br>
+  if (!isLEA(Opcode))<br>
     return;<br>
   if (MI.getOperand(5).getReg() != 0 || !MI.getOperand(4).isImm() ||<br>
       !TII->isSafeToClobberEFLAGS(*MFI, I))<br>
@@ -350,53 +436,142 @@ void FixupLEAPass::processInstructionFor<br>
     return;<br>
   if (MI.getOperand(2).getImm() > 1)<br>
     return;<br>
-  int addrr_opcode, addri_opcode;<br>
-  switch (opcode) {<br>
-  default:<br>
-    llvm_unreachable("Unexpected LEA instruction");<br>
-  case X86::LEA16r:<br>
-    addrr_opcode = X86::ADD16rr;<br>
-    addri_opcode = X86::ADD16ri;<br>
-    break;<br>
-  case X86::LEA32r:<br>
-    addrr_opcode = X86::ADD32rr;<br>
-    addri_opcode = X86::ADD32ri;<br>
-    break;<br>
-  case X86::LEA64_32r:<br>
-  case X86::LEA64r:<br>
-    addrr_opcode = X86::ADD64rr;<br>
-    addri_opcode = X86::ADD64ri32;<br>
-    break;<br>
-  }<br>
   DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););<br>
   DEBUG(dbgs() << "FixLEA: Replaced by: ";);<br>
   MachineInstr *NewMI = nullptr;<br>
-  const MachineOperand &Dst = MI.getOperand(0);<br>
   // Make ADD instruction for two registers writing to LEA's destination<br>
   if (SrcR1 != 0 && SrcR2 != 0) {<br>
-    const MachineOperand &Src1 = MI.getOperand(SrcR1 == DstR ? 1 : 3);<br>
-    const MachineOperand &Src2 = MI.getOperand(SrcR1 == DstR ? 3 : 1);<br>
-    NewMI = BuildMI(*MF, MI.getDebugLoc(), TII->get(addrr_opcode))<br>
-                .add(Dst)<br>
-                .add(Src1)<br>
-                .add(Src2);<br>
-    MFI->insert(I, NewMI);<br>
+    const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(Opcode));<br>
+    const MachineOperand &Src = MI.getOperand(SrcR1 == DstR ? 3 : 1);<br>
+    NewMI =<br>
+        BuildMI(*MFI, I, MI.getDebugLoc(), ADDrr, DstR).addReg(DstR).add(Src);<br>
     DEBUG(NewMI->dump(););<br>
   }<br>
   // Make ADD instruction for immediate<br>
   if (MI.getOperand(4).getImm() != 0) {<br>
+    const MCInstrDesc &ADDri =<br>
+        TII->get(getADDriFromLEA(Opcode, MI.getOperand(4)));<br>
     const MachineOperand &SrcR = MI.getOperand(SrcR1 == DstR ? 1 : 3);<br>
-    NewMI = BuildMI(*MF, MI.getDebugLoc(), TII->get(addri_opcode))<br>
-                .add(Dst)<br>
+    NewMI = BuildMI(*MFI, I, MI.getDebugLoc(), ADDri, DstR)<br>
                 .add(SrcR)<br>
                 .addImm(MI.getOperand(4).getImm());<br>
-    MFI->insert(I, NewMI);<br>
     DEBUG(NewMI->dump(););<br>
   }<br>
   if (NewMI) {<br>
     MFI->erase(I);<br>
-    I = static_cast<MachineBasicBlock::iterator>(NewMI);<br>
+    I = NewMI;<br>
+  }<br>
+}<br>
+<br>
+MachineInstr *<br>
+FixupLEAPass::processInstrForSlow3OpLEA(MachineInstr &MI,<br>
+                                        MachineFunction::iterator MFI) {<br>
+<br>
+  const int LEAOpcode = MI.getOpcode();<br>
+  if (!isLEA(LEAOpcode))<br>
+    return nullptr;<br>
+<br>
+  const MachineOperand &Dst = MI.getOperand(0);<br>
+  const MachineOperand &Base = MI.getOperand(1);<br>
+  const MachineOperand &Scale = MI.getOperand(2);<br>
+  const MachineOperand &Index = MI.getOperand(3);<br>
+  const MachineOperand &Offset = MI.getOperand(4);<br>
+  const MachineOperand &Segment = MI.getOperand(5);<br>
+<br>
+  if (!(isThreeOperandsLEA(Base, Index, Offset) ||<br>
+        hasInefficientLEABaseReg(Base, Index)) ||<br>
+      !TII->isSafeToClobberEFLAGS(*MFI, MI) ||<br>
+      Segment.getReg() != X86::NoRegister)<br>
+    return nullptr;<br>
+<br>
+  unsigned int DstR = Dst.getReg();<br>
+  unsigned int BaseR = Base.getReg();<br>
+  unsigned int IndexR = Index.getReg();<br>
+  unsigned SSDstR =<br>
+      (LEAOpcode == X86::LEA64_32r) ? getX86SubSuperRegister(DstR, 64) : DstR;<br>
+  bool IsScale1 = Scale.getImm() == 1;<br>
+  bool IsInefficientBase = isInefficientLEAReg(BaseR);<br>
+  bool IsInefficientIndex = isInefficientLEAReg(IndexR);<br>
+<br>
+  // Skip these cases since it takes more than 2 instructions<br>
+  // to replace the LEA instruction.<br>
+  if (IsInefficientBase && SSDstR == BaseR && !IsScale1)<br>
+    return nullptr;<br>
+  if (LEAOpcode == X86::LEA64_32r && IsInefficientBase &&<br>
+      (IsInefficientIndex || !IsScale1))<br>
+    return nullptr;<br>
+<br>
+  const DebugLoc DL = MI.getDebugLoc();<br>
+  const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(LEAOpcode));<br>
+  const MCInstrDesc &ADDri = TII->get(getADDriFromLEA(LEAOpcode, Offset));<br>
+<br>
+  DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MI.dump(););<br>
+  DEBUG(dbgs() << "FixLEA: Replaced by: ";);<br>
+<br>
+  // First try to replace LEA with one or two (for the 3-op LEA case)<br>
+  // add instructions:<br>
+  // 1.lea (%base,%index,1), %base => add %index,%base<br>
+  // 2.lea (%base,%index,1), %index => add %base,%index<br>
+  if (IsScale1 && (DstR == BaseR || DstR == IndexR)) {<br>
+    const MachineOperand &Src = DstR == BaseR ? Index : Base;<br>
+    MachineInstr *NewMI =<br>
+        BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Src);<br>
+    DEBUG(NewMI->dump(););<br>
+    // Create ADD instruction for the Offset in case of 3-Ops LEA.<br>
+    if (hasLEAOffset(Offset)) {<br>
+      NewMI = BuildMI(*MFI, MI, DL, ADDri, DstR).addReg(DstR).add(Offset);<br>
+      DEBUG(NewMI->dump(););<br>
+    }<br>
+    return NewMI;<br>
   }<br>
+  // If the base is inefficient try switching the index and base operands,<br>
+  // otherwise just break the 3-Ops LEA inst into 2-Ops LEA + ADD instruction:<br>
+  // lea offset(%base,%index,scale),%dst =><br>
+  // lea (%base,%index,scale); add offset,%dst<br>
+  if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {<br>
+    MachineInstr *NewMI = BuildMI(*MFI, MI, DL, TII->get(LEAOpcode))<br>
+                              .add(Dst)<br>
+                              .add(IsInefficientBase ? Index : Base)<br>
+                              .add(Scale)<br>
+                              .add(IsInefficientBase ? Base : Index)<br>
+                              .addImm(0)<br>
+                              .add(Segment);<br>
+    DEBUG(NewMI->dump(););<br>
+    // Create ADD instruction for the Offset in case of 3-Ops LEA.<br>
+    if (hasLEAOffset(Offset)) {<br>
+      NewMI = BuildMI(*MFI, MI, DL, ADDri, DstR).addReg(DstR).add(Offset);<br>
+      DEBUG(NewMI->dump(););<br>
+    }<br>
+    return NewMI;<br>
+  }<br>
+  // Handle the rest of the cases with inefficient base register:<br>
+  assert(SSDstR != BaseR && "SSDstR == BaseR should be handled already!");<br>
+  assert(IsInefficientBase && "efficient base should be handled already!");<br>
+<br>
+  // lea (%base,%index,1), %dst => mov %base,%dst; add %index,%dst<br>
+  if (IsScale1 && !hasLEAOffset(Offset)) {<br>
+    TII->copyPhysReg(*MFI, MI, DL, DstR, BaseR, Base.isKill());<br>
+    DEBUG(MI.getPrevNode()->dump(););<br>
+<br>
+    MachineInstr *NewMI =<br>
+        BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Index);<br>
+    DEBUG(NewMI->dump(););<br>
+    return NewMI;<br>
+  }<br>
+  // lea offset(%base,%index,scale), %dst =><br>
+  // lea offset( ,%index,scale), %dst; add %base,%dst<br>
+  MachineInstr *NewMI = BuildMI(*MFI, MI, DL, TII->get(LEAOpcode))<br>
+                            .add(Dst)<br>
+                            .addReg(0)<br>
+                            .add(Scale)<br>
+                            .add(Index)<br>
+                            .add(Offset)<br>
+                            .add(Segment);<br>
+  DEBUG(NewMI->dump(););<br>
+<br>
+  NewMI = BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Base);<br>
+  DEBUG(NewMI->dump(););<br>
+  return NewMI;<br>
 }<br>
<br>
 bool FixupLEAPass::processBasicBlock(MachineFunction &MF,<br>
@@ -410,8 +585,16 @@ bool FixupLEAPass::processBasicBlock(Mac<br>
     if (OptLEA) {<br>
       if (MF.getSubtarget<X86Subtarget>().isSLM())<br>
         processInstructionForSLM(I, MFI);<br>
-      else<br>
-        processInstruction(I, MFI);<br>
+<br>
+      else {<br>
+        if (MF.getSubtarget<X86Subtarget>().slow3OpsLEA()) {<br>
+          if (auto *NewMI = processInstrForSlow3OpLEA(*I, MFI)) {<br>
+            MFI->erase(I);<br>
+            I = NewMI;<br>
+          }<br>
+        } else<br>
+          processInstruction(I, MFI);<br>
+      }<br>
     }<br>
   }<br>
   return false;<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86Subtarget.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.h?rev=303183&r1=303182&r2=303183&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.h?rev=303183&r1=303182&r2=303183&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86Subtarget.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86Subtarget.h Tue May 16 11:01:36 2017<br>
@@ -253,6 +253,11 @@ protected:<br>
   /// True if the LEA instruction with certain arguments is slow<br>
   bool SlowLEA;<br>
<br>
+  /// True if the LEA instruction has all three source operands: base, index,<br>
+  /// and offset or if the LEA instruction uses base and index registers where<br>
+  /// the base is EBP, RBP,or R13<br>
+  bool Slow3OpsLEA;<br>
+<br>
   /// True if INC and DEC instructions are slow when writing to flags<br>
   bool SlowIncDec;<br>
<br>
@@ -490,6 +495,7 @@ public:<br>
   bool callRegIndirect() const { return CallRegIndirect; }<br>
   bool LEAusesAG() const { return LEAUsesAG; }<br>
   bool slowLEA() const { return SlowLEA; }<br>
+  bool slow3OpsLEA() const { return Slow3OpsLEA; }<br>
   bool slowIncDec() const { return SlowIncDec; }<br>
   bool hasCDI() const { return HasCDI; }<br>
   bool hasPFI() const { return HasPFI; }<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=303183&r1=303182&r2=303183&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=303183&r1=303182&r2=303183&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Tue May 16 11:01:36 2017<br>
@@ -61,6 +61,7 @@ static cl::opt<bool> EnableMachineCombin<br>
 namespace llvm {<br>
<br>
 void initializeWinEHStatePassPass(PassRegistry &);<br>
+void initializeFixupLEAPassPass(PassRegistry &);<br>
 void initializeX86ExecutionDepsFixPass(PassRegistry &);<br>
<br>
 } // end namespace llvm<br>
@@ -75,6 +76,7 @@ extern "C" void LLVMInitializeX86Target(<br>
   initializeWinEHStatePassPass(PR);<br>
   initializeFixupBWInstPassPass(PR);<br>
   initializeEvexToVexInstPassPass(PR);<br>
+  initializeFixupLEAPassPass(PR);<br>
   initializeX86ExecutionDepsFixPass(PR);<br>
 }<br>
<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/leaFixup32.mir<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/leaFixup32.mir?rev=303183&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/leaFixup32.mir?rev=303183&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/leaFixup32.mir (added)<br>
+++ llvm/trunk/test/CodeGen/X86/leaFixup32.mir Tue May 16 11:01:36 2017<br>
@@ -0,0 +1,508 @@<br>
+# RUN: llc -run-pass x86-fixup-LEAs -mcpu=corei7-avx -o - %s | FileCheck %s<br>
+--- |<br>
+  ; ModuleID = 'test/CodeGen/X86/fixup-lea.ll'<br>
+  source_filename = "test/CodeGen/X86/fixup-lea.ll"<br>
+  target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"<br>
+  target triple = "i386"<br>
+  ;generated using: llc -stop-after x86-pad-short-functions fixup-lea.ll > leaFinxup32.mir<br>
+<br>
+  ;test2add_32: 3 operands LEA32r that can be replaced with 2 add instructions<br>
+  ; where ADD32ri8 is chosen<br>
+  define i32 @test2add_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test2add_ebp_32: 3 operands LEA32r that can be replaced with 2 add instructions<br>
+  ; where the base is rbp/r13/ebp register<br>
+  define i32 @test2add_ebp_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1add_ebp_32: 2 operands LEA32r where base register is ebp and can be replaced<br>
+  ; with an add instruction<br>
+  define i32 @test1add_ebp_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions<br>
+  define i32 @testleaadd_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_ebp_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions<br>
+  ; where the base is ebp register<br>
+  define i32 @testleaadd_ebp_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1lea_ebp_32: 2 operands LEA32r wher base register is rbp/r13/ebp and can be replaced<br>
+  ; with a lea instruction<br>
+  define i32 @test1lea_ebp_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test2addi32_32: 3 operands LEA32r that can be replaced with 2 add instructions where ADD32ri32<br>
+  ; is chosen<br>
+  define i32 @test2addi32_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1mov1add_ebp_32: 2 operands LEA32r that can be replaced with 1 add 1 mov instructions<br>
+  ; where the base is rbp/r13/ebp register<br>
+  define i32 @test1mov1add_ebp_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_ebp_index_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions<br>
+  ; where the base and the index are ebp register and there is offset<br>
+  define i32 @testleaadd_ebp_index_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_ebp_index2_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions<br>
+  ; where the base and the index are ebp register and there is scale<br>
+  define i32 @testleaadd_ebp_index2_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test_skip_opt_32: 3 operands LEA32r that can not be replaced with 2 instructions<br>
+  define i32 @test_skip_opt_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test_skip_eflags_32: LEA32r that cannot be replaced since its not safe to clobber eflags<br>
+  define i32 @test_skip_eflags_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+...<br>
+---<br>
+name:            test2add_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%eax' }<br>
+  - { reg: '%ebp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp<br>
+    ; CHECK: %eax = ADD32rr %eax, killed %ebp<br>
+    ; CHECK: %eax = ADD32ri8 %eax, -5<br>
+<br>
+    %eax = LEA32r killed %eax, 1, killed %ebp, -5, _<br>
+    RETQ %eax<br>
+<br>
+...<br>
+---<br>
+name:            test2add_ebp_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%eax' }<br>
+  - { reg: '%ebp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp<br>
+    ; CHECK: %ebp = ADD32rr %ebp, killed %eax<br>
+    ; CHECK: %ebp = ADD32ri8 %ebp, -5<br>
+<br>
+    %ebp = LEA32r killed %ebp, 1, killed %eax, -5, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            test1add_ebp_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%eax' }<br>
+  - { reg: '%ebp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp<br>
+    ; CHECK: %ebp = ADD32rr %ebp, killed %eax<br>
+<br>
+    %ebp = LEA32r killed %ebp, 1, killed %eax, 0, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%eax' }<br>
+  - { reg: '%ebp' }<br>
+  - { reg: '%ebx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp, %esi<br>
+    ; CHECK: %ebx = LEA32r killed %eax, 1, killed %ebp, 0<br>
+    ; CHECK: %ebx = ADD32ri8 %ebx, -5<br>
+<br>
+    %ebx = LEA32r killed %eax, 1, killed %ebp, -5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_ebp_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%eax' }<br>
+  - { reg: '%ebp' }<br>
+  - { reg: '%ebx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp<br>
+    ; CHECK: %ebx = LEA32r killed %eax, 1, killed %ebp, 0, _<br>
+    ; CHECK: %ebx = ADD32ri8  %ebx, -5<br>
+<br>
+    %ebx = LEA32r killed %ebp, 1, killed %eax, -5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            test1lea_ebp_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%eax' }<br>
+  - { reg: '%ebp' }<br>
+  - { reg: '%ebx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp<br>
+    ; CHECK: %ebx = LEA32r killed %eax, 1, killed %ebp, 0, _<br>
+<br>
+    %ebx = LEA32r killed %ebp, 1, killed %eax, 0, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            test2addi32_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%eax' }<br>
+  - { reg: '%ebp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp<br>
+    ; CHECK: %eax = ADD32rr %eax, killed %ebp<br>
+    ; CHECK: %eax = ADD32ri %eax, 129<br>
+<br>
+    %eax = LEA32r killed %eax, 1, killed %ebp, 129, _<br>
+    RETQ %eax<br>
+<br>
+...<br>
+---<br>
+name:            test1mov1add_ebp_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%eax' }<br>
+  - { reg: '%ebp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp, %ebx<br>
+    ; CHECK: %ebx = MOV32rr killed %ebp<br>
+    ; CHECK: %ebx = ADD32rr %ebx, killed %ebp<br>
+<br>
+    %ebx = LEA32r killed %ebp, 1, killed %ebp, 0, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_ebp_index_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%ebx' }<br>
+  - { reg: '%ebp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp, %ebx<br>
+    ; CHECK: %ebx = LEA32r _, 1, killed %ebp, 5, _<br>
+    ; CHECK: %ebx = ADD32rr %ebx, killed %ebp<br>
+<br>
+    %ebx = LEA32r killed %ebp, 1, killed %ebp, 5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_ebp_index2_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%ebx' }<br>
+  - { reg: '%ebp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp, %ebx<br>
+    ; CHECK: %ebx = LEA32r _, 4, killed %ebp, 5, _<br>
+    ; CHECK: %ebx = ADD32rr %ebx, killed %ebp<br>
+<br>
+    %ebx = LEA32r killed %ebp, 4, killed %ebp, 5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            test_skip_opt_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%ebx' }<br>
+  - { reg: '%ebp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp, %ebx<br>
+    ; CHECK: %ebp = LEA32r killed %ebp, 4, killed %ebp, 0, _<br>
+<br>
+    %ebp = LEA32r killed %ebp, 4, killed %ebp, 0, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            test_skip_eflags_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%ebp' }<br>
+  - { reg: '%eax' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp, %ebx<br>
+    ; CHECK: %ebx = LEA32r killed %eax, 4, killed %eax, 5, _<br>
+    ; CHECK: %ebp = LEA32r killed %ebx, 4, killed %ebx, 0, _<br>
+    ; CHECK: %ebp = ADD32ri8 %ebp, 5<br>
+<br>
+    CMP32rr   %eax, killed %ebx, implicit-def %eflags<br>
+    %ebx = LEA32r killed %eax, 4, killed %eax, 5, _<br>
+    JE_1 %bb.1, implicit %eflags<br>
+    RETQ %ebx<br>
+  bb.1:<br>
+    liveins: %eax, %ebp, %ebx<br>
+    %ebp = LEA32r killed %ebx, 4, killed %ebx, 5, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+<br>
+<br>
+<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/leaFixup64.mir<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/leaFixup64.mir?rev=303183&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/leaFixup64.mir?rev=303183&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/leaFixup64.mir (added)<br>
+++ llvm/trunk/test/CodeGen/X86/leaFixup64.mir Tue May 16 11:01:36 2017<br>
@@ -0,0 +1,1041 @@<br>
+# RUN: llc -run-pass x86-fixup-LEAs -mcpu=corei7-avx -o - %s | FileCheck %s<br>
+--- |<br>
+  ; ModuleID = 'lea-2.ll'<br>
+  source_filename = "lea-2.ll"<br>
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"<br>
+  ;generated using: llc -stop-after x86-pad-short-functions lea-2.ll > leaFinxup64.mir<br>
+<br>
+  ;testleaadd_64_32_1: 3 operands LEA64_32r cannot be replaced with 2 add instructions<br>
+  ; but can be replaced with 1 lea + 1 add<br>
+  define i32 @testleaadd_64_32_1() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_rbp_64_32_1: 3 operands LEA64_32r cannot be replaced with 2 add instructions<br>
+  ; where the base is rbp/r13/ebp register but it can be replaced with 1 lea + 1 add<br>
+  define i32 @testleaadd_rbp_64_32_1() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1lea_rbp_64_32_1: 2 operands LEA64_32r where base register is rbp/r13/ebp and can not<br>
+  ; be replaced with an add instruction but can be replaced with 1 lea instruction<br>
+  define i32 @test1lea_rbp_64_32_1() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test2add_64: 3 operands LEA64r that can be replaced with 2 add instructions<br>
+  define i32 @test2add_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test2add_rbp_64: 3 operands LEA64r that can be replaced with 2 add instructions<br>
+  ; where the base is rbp/r13/ebp register<br>
+  define i32 @test2add_rbp_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1add_rbp_64: 2 operands LEA64r where base register is rbp/r13/ebp and can be replaced<br>
+  ; with an add instruction<br>
+  define i32 @test1add_rbp_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_64_32: 3 operands LEA64_32r that can be replaced with 1 lea 1 add instructions<br>
+  define i32 @testleaadd_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_rbp_64_32: 3 operands LEA64_32r that can be replaced with 1 lea 1 add instructions<br>
+  ; where the base is rbp/r13/ebp register<br>
+  define i32 @testleaadd_rbp_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1lea_rbp_64_32: 2 operands LEA64_32r where base register is rbp/r13/ebp and can be replaced<br>
+  ; with a lea instruction<br>
+  define i32 @test1lea_rbp_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_64: 3 operands LEA64r that can be replaced with 1 lea 1 add instructions<br>
+  define i32 @testleaadd_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_rbp_64: 3 operands LEA64r that can be replaced with 1 lea 1 add instructions<br>
+  ; where the base is rbp/r13/ebp register<br>
+  define i32 @testleaadd_rbp_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1lea_rbp_64: 2 operands LEA64r wher base register is rbp/r13/ebp and can be replaced<br>
+  ; with a lea instruction<br>
+  define i32 @test1lea_rbp_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test8: dst = base & scale!=1, can't optimize<br>
+  define i32 @test8() {<br>
+      ret i32 0<br>
+  }<br>
+<br>
+  ;testleaaddi32_64_32: 3 operands LEA64_32r that can be replaced with 1 lea + 1 add instructions where<br>
+  ; ADD64ri32 is chosen<br>
+  define i32 @testleaaddi32_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1mov1add_rbp_64_32: 2 operands LEA64_32r cannot be replaced with 1 add 1 mov instructions<br>
+  ; where the base is rbp/r13/ebp register<br>
+  define i32 @test1mov1add_rbp_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_rbp_index_64_32: 3 operands LEA64_32r that cannot replaced with 1 lea 1 add instructions<br>
+  ; where the base and the index are ebp register and there is offset<br>
+  define i32 @testleaadd_rbp_index_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_rbp_index2_64_32: 3 operands LEA64_32r that cannot replaced with 1 lea 1 add instructions<br>
+  ; where the base and the index are ebp register and there is scale<br>
+  define i32 @testleaadd_rbp_index2_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test2addi32_64: 3 operands LEA64r that can be replaced with 2 add instructions where ADD64ri32<br>
+  ; is chosen<br>
+  define i32 @test2addi32_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test1mov1add_rbp_64: 2 operands LEA64r that can be replaced with 1 add 1 mov instructions<br>
+  ; where the base is rbp/r13/ebp register<br>
+  define i32 @test1mov1add_rbp_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_rbp_index_64: 3 operands LEA64r that can be replaced with 1 lea 1 add instructions<br>
+  ; where the base and the index are ebp register and there is offset<br>
+  define i32 @testleaadd_rbp_index_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;testleaadd_rbp_index2_64: 3 operands LEA64r that can be replaced with 1 lea 1 add instructions<br>
+  ; where the base and the index are ebp register and there is scale<br>
+  define i32 @testleaadd_rbp_index2_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test_skip_opt_64: 3 operands LEA64r that can not be replaced with 2 instructions<br>
+  define i32 @test_skip_opt_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test_skip_eflags_64: LEA64r that cannot be replaced since its not safe to clobber eflags<br>
+  define i32 @test_skip_eflags_64() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test_skip_opt_64_32: 3 operands LEA64_32r that can not be replaced with 2 instructions<br>
+  define i32 @test_skip_opt_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+  ;test_skip_eflags_64_32: LEA64_32r that cannot be replaced since its not safe to clobber eflags<br>
+  define i32 @test_skip_eflags_64_32() {<br>
+    ret i32 0<br>
+  }<br>
+<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_64_32_1<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %eax = LEA64_32r killed %rax, 1, killed %rbp, 0<br>
+    ; CHECK: %eax = ADD32ri8 %eax, -5<br>
+<br>
+    %eax = LEA64_32r killed %rax, 1, killed %rbp, -5, _<br>
+    RETQ %eax<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_rbp_64_32_1<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %ebp = LEA64_32r killed %rax, 1,  killed %rbp, 0<br>
+    ; CHECK: %ebp = ADD32ri8 %ebp, -5<br>
+<br>
+    %ebp = LEA64_32r killed %rbp, 1, killed %rax, -5, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            test1lea_rbp_64_32_1<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %ebp = LEA64_32r killed %rax, 1, killed %rbp, 0<br>
+<br>
+    %ebp = LEA64_32r killed %rbp, 1, killed %rax, 0, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            test2add_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %rax = ADD64rr %rax, killed %rbp<br>
+    ; CHECK: %rax = ADD64ri8 %rax, -5<br>
+<br>
+    %rax = LEA64r killed %rax, 1, killed %rbp, -5, _<br>
+    RETQ %eax<br>
+<br>
+...<br>
+---<br>
+name:            test2add_rbp_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %rbp = ADD64rr %rbp, killed %rax<br>
+    ; CHECK: %rbp = ADD64ri8 %rbp, -5<br>
+<br>
+    %rbp = LEA64r killed %rbp, 1, killed %rax, -5, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            test1add_rbp_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %rbp = ADD64rr %rbp, killed %rax<br>
+<br>
+    %rbp = LEA64r killed %rbp, 1, killed %rax, 0, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+  - { reg: '%rbx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %ebx = LEA64_32r killed %rax, 1, killed %rbp, 0, _<br>
+    ; CHECK: %ebx = ADD32ri8 %ebx, -5<br>
+<br>
+    %ebx = LEA64_32r killed %rax, 1, killed %rbp, -5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_rbp_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+  - { reg: '%rbx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %ebx = LEA64_32r killed %rax, 1, killed %rbp, 0, _<br>
+    ; CHECK: %ebx = ADD32ri8 %ebx, -5<br>
+<br>
+    %ebx = LEA64_32r killed %rbp, 1, killed %rax, -5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            test1lea_rbp_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+  - { reg: '%rbx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %ebx = LEA64_32r killed %rax, 1, killed %rbp, 0, _<br>
+<br>
+    %ebx = LEA64_32r killed %rbp, 1, killed %rax, 0, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+  - { reg: '%rbx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %rbx = LEA64r killed %rax, 1, killed %rbp, 0, _<br>
+    ; CHECK: %rbx = ADD64ri8 %rbx, -5<br>
+<br>
+    %rbx = LEA64r killed %rax, 1, killed %rbp, -5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_rbp_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+  - { reg: '%rbx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %rbx = LEA64r killed %rax, 1, killed %rbp, 0, _<br>
+    ; CHECK: %rbx = ADD64ri8 %rbx, -5<br>
+<br>
+    %rbx = LEA64r killed %rbp, 1, killed %rax, -5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            test1lea_rbp_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+  - { reg: '%rbx' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %rbx = LEA64r killed %rax, 1, killed %rbp, 0, _<br>
+<br>
+    %rbx = LEA64r killed %rbp, 1, killed %rax, 0, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            test8<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rdi' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rdi, %rbp<br>
+    ; CHECK:  %r12 = LEA64r _, 2, killed %r13, 5, _<br>
+    ; CHECK:  %r12 = ADD64rr %r12, killed %rbp<br>
+    %rbp = KILL %rbp, implicit-def %rbp<br>
+    %r13 = KILL %rdi, implicit-def %r13<br>
+    %r12 = LEA64r killed %rbp, 2, killed %r13, 5, _<br>
+    RETQ %r12<br>
+<br>
+...<br>
+---<br>
+name:            testleaaddi32_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %eax = LEA64_32r killed %rax, 1, killed %rbp, 0<br>
+    ; CHECK: %eax = ADD32ri %eax, 129<br>
+<br>
+    %eax = LEA64_32r killed %rax, 1, killed %rbp, 129, _<br>
+    RETQ %eax<br>
+<br>
+...<br>
+---<br>
+name:            test1mov1add_rbp_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %ebx = LEA64_32r killed %rbp, 1, killed %rbp, 0, _<br>
+<br>
+    %ebx = LEA64_32r killed %rbp, 1, killed %rbp, 0, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_rbp_index_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rbx' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %ebx = LEA64_32r killed %rbp, 1, killed %rbp, 5, _<br>
+<br>
+    %ebx = LEA64_32r killed %rbp, 1, killed %rbp, 5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_rbp_index2_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rbx' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %eax, %ebp, %ebx<br>
+    ; CHECK: %ebx = LEA64_32r killed %rbp, 4, killed %rbp, 5, _<br>
+<br>
+    %ebx = LEA64_32r killed %rbp, 4, killed %rbp, 5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            test2addi32_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp<br>
+    ; CHECK: %rax = ADD64rr %rax, killed %rbp<br>
+    ; CHECK: %rax = ADD64ri32 %rax, 129<br>
+<br>
+    %rax = LEA64r killed %rax, 1, killed %rbp, 129, _<br>
+    RETQ %eax<br>
+<br>
+...<br>
+---<br>
+name:            test1mov1add_rbp_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rax' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %rbx = MOV64rr killed %rbp<br>
+    ; CHECK: %rbx = ADD64rr %rbx, killed %rbp<br>
+<br>
+    %rbx = LEA64r killed %rbp, 1, killed %rbp, 0, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_rbp_index_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rbx' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %rbx = LEA64r _, 1, killed %rbp, 5, _<br>
+    ; CHECK: %rbx = ADD64rr %rbx, killed %rbp<br>
+<br>
+    %rbx = LEA64r killed %rbp, 1, killed %rbp, 5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            testleaadd_rbp_index2_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rbx' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %rbx = LEA64r _, 4, killed %rbp, 5, _<br>
+    ; CHECK: %rbx = ADD64rr %rbx, killed %rbp<br>
+<br>
+    %rbx = LEA64r killed %rbp, 4, killed %rbp, 5, _<br>
+    RETQ %ebx<br>
+<br>
+...<br>
+---<br>
+name:            test_skip_opt_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rbx' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %rbp = LEA64r killed %rbp, 4, killed %rbp, 0, _<br>
+<br>
+    %rbp = LEA64r killed %rbp, 4, killed %rbp, 0, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            test_skip_eflags_64<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rbp' }<br>
+  - { reg: '%rax' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %rbx = LEA64r killed %rax, 4, killed %rax, 5, _<br>
+    ; CHECK: %rbp = LEA64r killed %rbx, 4, killed %rbx, 0, _<br>
+    ; CHECK: %rbp = ADD64ri8 %rbp, 5<br>
+<br>
+    CMP64rr   %rax, killed %rbx, implicit-def %eflags<br>
+    %rbx = LEA64r killed %rax, 4, killed %rax, 5, _<br>
+    JE_1 %bb.1, implicit %eflags<br>
+    RETQ %ebx<br>
+  bb.1:<br>
+    liveins: %rax, %rbp, %rbx<br>
+    %rbp = LEA64r killed %rbx, 4, killed %rbx, 5, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            test_skip_opt_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rbx' }<br>
+  - { reg: '%rbp' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %ebp = LEA64_32r killed %rbp, 4, killed %rbp, 0, _<br>
+<br>
+    %ebp = LEA64_32r killed %rbp, 4, killed %rbp, 0, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+---<br>
+name:            test_skip_eflags_64_32<br>
+alignment:       4<br>
+exposesReturnsTwice: false<br>
+legalized:       false<br>
+regBankSelected: false<br>
+selected:        false<br>
+tracksRegLiveness: true<br>
+liveins:<br>
+  - { reg: '%rbp' }<br>
+  - { reg: '%rax' }<br>
+frameInfo:<br>
+  isFrameAddressTaken: false<br>
+  isReturnAddressTaken: false<br>
+  hasStackMap:     false<br>
+  hasPatchPoint:   false<br>
+  stackSize:       0<br>
+  offsetAdjustment: 0<br>
+  maxAlignment:    0<br>
+  adjustsStack:    false<br>
+  hasCalls:        false<br>
+  maxCallFrameSize: 0<br>
+  hasOpaqueSPAdjustment: false<br>
+  hasVAStart:      false<br>
+  hasMustTailInVarArgFunc: false<br>
+body:             |<br>
+  bb.0 (%ir-block.0):<br>
+    liveins: %rax, %rbp, %rbx<br>
+    ; CHECK: %ebx = LEA64_32r killed %rax, 4, killed %rax, 5, _<br>
+    ; CHECK: %ebp = LEA64_32r killed %rbx, 4, killed %rbx, 0, _<br>
+    ; CHECK: %ebp = ADD32ri8 %ebp, 5<br>
+<br>
+    CMP64rr   %rax, killed %rbx, implicit-def %eflags<br>
+    %ebx = LEA64_32r killed %rax, 4, killed %rax, 5, _<br>
+    JE_1 %bb.1, implicit %eflags<br>
+    RETQ %ebx<br>
+  bb.1:<br>
+    liveins: %rax, %rbp, %rbx<br>
+    %ebp = LEA64_32r killed %rbx, 4, killed %rbx, 5, _<br>
+    RETQ %ebp<br>
+<br>
+...<br>
+<br>
+<br>
+<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>