<div dir="ltr">Reverted in r319591.</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 1, 2017 at 12:50 PM, Matt Morehouse <span dir="ltr"><<a href="mailto:mascasa@google.com" target="_blank">mascasa@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">If you don't have a fix yet, could you please revert?  Bot has been broken for several hours now.</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 1, 2017 at 9:24 AM, Jatin Bhateja <span dir="ltr"><<a href="mailto:jatin.bhateja@gmail.com" target="_blank">jatin.bhateja@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I noticed this and looking for its resolution.<div><br></div><div>Thanks,</div><div>Jatin</div></div><div class="m_-1772450639109081393HOEnZb"><div class="m_-1772450639109081393h5"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 1, 2017 at 10:25 PM, Matt Morehouse <span dir="ltr"><<a href="mailto:mascasa@google.com" target="_blank">mascasa@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Jatin,<div><br></div><div>The gep.ll test is failing under ASan and breaking the <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/10802" target="_blank">x86_64-linux-fast bot</a>.  Please take a look.</div><div><br></div><div><pre style="font-family:"Courier New",courier,monotype,monospace;color:rgb(0,0,0);font-size:medium"><span class="m_-1772450639109081393m_-8915255994032389653m_3344820007742969176gmail-stdout">******************** TEST 'LLVM :: CodeGen/X86/GlobalISel/gep.ll' FAILED ********************
Script:
--
/b/sanitizer-x86_64-linux-fast<wbr>/build/llvm_build_asan/bin/llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm/test/CodeGen/X86/G<wbr>lobalISel/gep.ll -o - | /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm_build_asan/bin/Fil<wbr>eCheck /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm/test/CodeGen/X86/G<wbr>lobalISel/gep.ll --check-prefix=ALL --check-prefix=X64_GISEL
/b/sanitizer-x86_64-linux-fast<wbr>/build/llvm_build_asan/bin/llc -mtriple=x86_64-linux-gnu              -verify-machineinstrs < /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm/test/CodeGen/X86/G<wbr>lobalISel/gep.ll -o - | /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm_build_asan/bin/Fil<wbr>eCheck /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm/test/CodeGen/X86/G<wbr>lobalISel/gep.ll --check-prefix=ALL --check-prefix=X64
--
Exit Code: 2

Command Output (stderr):
--
==============================<wbr>==============================<wbr>=====
==64410==ERROR: AddressSanitizer: use-after-poison on address 0x621000024e98 at pc 0x0000036f9139 bp 0x7fffb1b5d940 sp 0x7fffb1b5d938
READ of size 8 at 0x621000024e98 thread T0
    #0 0x36f9138 in getParent /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm/include/llvm/CodeG<wbr>en/MachineInstr.h:140:43
    #1 0x36f9138 in llvm::MachineInstr::getRegInfo<wbr>() /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm/lib/CodeGen/Machin<wbr>eInstr.cpp:128
    #2 0x2bc42de in llvm::DenseMapInfo<(anonymous namespace)::MemOpKey>::getHash<wbr>Value((anonymous namespace)::MemOpKey const&) /b/sanitizer-x86_64-linux-fast<wbr>/build/llvm/lib/Target/X86/X86<wbr>OptimizeLEAs.cpp:184:36</span></pre></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 1, 2017 at 6:07 AM, Jatin Bhateja via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: jbhateja<br>
Date: Fri Dec  1 06:07:38 2017<br>
New Revision: 319543<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=319543&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=319543&view=rev</a><br>
Log:<br>
[X86] Improvement in CodeGen instruction selection for LEAs.<br>
<br>
Summary:<br>
1/  Operand folding during complex pattern matching for LEAs has been extended, such that it promotes Scale to<br>
     accommodate similar operand appearing in the DAG  e.g.<br>
                 T1 = A + B<br>
                 T2 = T1 + 10<br>
                 T3 = T2 + A<br>
    For above DAG rooted at T3, X86AddressMode will now look like<br>
                Base = B , Index = A , Scale = 2 , Disp = 10<br>
<br>
2/  During OptimizeLEAPass down the pipeline factorization is now performed over LEAs so that if there is an opportunity<br>
     then complex LEAs (having 3 operands) could be factored out  e.g.<br>
                 leal 1(%rax,%rcx,1), %rdx<br>
                 leal 1(%rax,%rcx,2), %rcx<br>
     will be factored as following<br>
                 leal 1(%rax,%rcx,1), %rdx<br>
                 leal (%rdx,%rcx)   , %edx<br>
<br>
3/ Aggressive operand folding for AM based selection for LEAs is sensitive to loops, thus avoiding creation of any complex LEAs within a loop.<br>
<br>
4/ Simplify LEA converts (lea (BASE,1,INDEX,0)  --> add (BASE, INDEX) which offers better through put.<br>
<br>
PR32755 will be taken care of by this pathc.<br>
<br>
Previous patch revisions : r313343 , r314886<br>
<br>
Reviewers: lsaba, RKSimon, craig.topper, qcolombet, jmolloy, jbhateja<br>
<br>
Reviewed By: lsaba, RKSimon, jbhateja<br>
<br>
Subscribers: jmolloy, spatel, igorb, llvm-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D35014" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3501<wbr>4</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/CodeGe<wbr>n/MachineInstr.h<br>
    llvm/trunk/include/llvm/CodeGe<wbr>n/SelectionDAG.h<br>
    llvm/trunk/lib/CodeGen/Selecti<wbr>onDAG/SelectionDAGISel.cpp<br>
    llvm/trunk/lib/Target/X86/X86I<wbr>SelDAGToDAG.cpp<br>
    llvm/trunk/lib/Target/X86/X86O<wbr>ptimizeLEAs.cpp<br>
    llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/callingconv.ll<br>
    llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/gep.ll<br>
    llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/memop-scalar.ll<br>
    llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse1.ll<br>
    llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse2.ll<br>
    llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse3.ll<br>
    llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse4.ll<br>
    llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i16.ll<br>
    llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i32.ll<br>
    llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i64.ll<br>
    llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-result.ll<br>
    llvm/trunk/test/CodeGen/X86/um<wbr>ul-with-overflow.ll<br>
    llvm/trunk/test/Transforms/Loo<wbr>pStrengthReduce/X86/ivchain-X8<wbr>6.ll<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGe<wbr>n/MachineInstr.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineInstr.h?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>CodeGen/MachineInstr.h?rev=319<wbr>543&r1=319542&r2=319543&view=d<wbr>iff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/CodeGe<wbr>n/MachineInstr.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGe<wbr>n/MachineInstr.h Fri Dec  1 06:07:38 2017<br>
@@ -1320,12 +1320,13 @@ public:<br>
   /// Add all implicit def and use operands to this instruction.<br>
   void addImplicitDefUseOperands(Mach<wbr>ineFunction &MF);<br>
<br>
-private:<br>
   /// If this instruction is embedded into a MachineFunction, return the<br>
   /// MachineRegisterInfo object for the current function, otherwise<br>
   /// return null.<br>
   MachineRegisterInfo *getRegInfo();<br>
<br>
+private:<br>
+<br>
   /// Unlink all of the register operands in this instruction from their<br>
   /// respective use lists.  This requires that the operands already be on their<br>
   /// use lists.<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGe<wbr>n/SelectionDAG.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>CodeGen/SelectionDAG.h?rev=319<wbr>543&r1=319542&r2=319543&view=d<wbr>iff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/CodeGe<wbr>n/SelectionDAG.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGe<wbr>n/SelectionDAG.h Fri Dec  1 06:07:38 2017<br>
@@ -300,6 +300,9 @@ public:<br>
   /// type legalization.<br>
   bool NewNodesMustHaveLegalTypes = false;<br>
<br>
+  /// Set to true for DAG of BasicBlock contained inside a loop.<br>
+  bool IsDAGPartOfLoop = false;<br>
+<br>
 private:<br>
   /// DAGUpdateListener is a friend so it can manipulate the listener stack.<br>
   friend struct DAGUpdateListener;<br>
<br>
Modified: llvm/trunk/lib/CodeGen/Selecti<wbr>onDAG/SelectionDAGISel.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/CodeGen/S<wbr>electionDAG/SelectionDAGISel.c<wbr>pp?rev=319543&r1=319542&r2=319<wbr>543&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/CodeGen/Selecti<wbr>onDAG/SelectionDAGISel.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/Selecti<wbr>onDAG/SelectionDAGISel.cpp Fri Dec  1 06:07:38 2017<br>
@@ -27,6 +27,7 @@<br>
 #include "llvm/Analysis/AliasAnalysis.h<wbr>"<br>
 #include "llvm/Analysis/BranchProbabili<wbr>tyInfo.h"<br>
 #include "llvm/Analysis/CFG.h"<br>
+#include "llvm/Analysis/LoopInfo.h"<br>
 #include "llvm/Analysis/OptimizationRem<wbr>arkEmitter.h"<br>
 #include "llvm/Analysis/TargetLibraryIn<wbr>fo.h"<br>
 #include "llvm/CodeGen/FastISel.h"<br>
@@ -325,6 +326,8 @@ void SelectionDAGISel::getAnalysisU<wbr>sage(<br>
   if (OptLevel != CodeGenOpt::None)<br>
     AU.addRequired<AAResultsWrapp<wbr>erPass>();<br>
   AU.addRequired<GCModuleInfo>(<wbr>);<br>
+  if (OptLevel != CodeGenOpt::None)<br>
+    AU.addRequired<LoopInfoWrapper<wbr>Pass>();<br>
   AU.addRequired<StackProtector<wbr>>();<br>
   AU.addPreserved<StackProtecto<wbr>r>();<br>
   AU.addPreserved<GCModuleInfo><wbr>();<br>
@@ -1415,6 +1418,7 @@ void SelectionDAGISel::SelectAllBas<wbr>icBlo<br>
<br>
   // Iterate over all basic blocks in the function.<br>
   for (const BasicBlock *LLVMBB : RPOT) {<br>
+    CurDAG->IsDAGPartOfLoop = false;<br>
     if (OptLevel != CodeGenOpt::None) {<br>
       bool AllPredsVisited = true;<br>
       for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB);<br>
@@ -1592,6 +1596,13 @@ void SelectionDAGISel::SelectAllBas<wbr>icBlo<br>
                                    FunctionBasedInstrumentation);<br>
     }<br>
<br>
+    if (OptLevel != CodeGenOpt::None) {<br>
+      auto &LIWP = getAnalysis<LoopInfoWrapperPas<wbr>s>();<br>
+      LoopInfo &LI = LIWP.getLoopInfo();<br>
+      if (LI.getLoopFor(LLVMBB))<br>
+        CurDAG->IsDAGPartOfLoop = true;<br>
+    }<br>
+<br>
     if (Begin != BI)<br>
       ++NumDAGBlocks;<br>
     else<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86I<wbr>SelDAGToDAG.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/X86ISelDAGToDAG.cpp?rev=3195<wbr>43&r1=319542&r2=319543&view=di<wbr>ff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/X86I<wbr>SelDAGToDAG.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86I<wbr>SelDAGToDAG.cpp Fri Dec  1 06:07:38 2017<br>
@@ -88,6 +88,11 @@ namespace {<br>
              IndexReg.getNode() != nullptr || Base_Reg.getNode() != nullptr;<br>
     }<br>
<br>
+    bool hasComplexAddressingMode() const {<br>
+      return Disp && IndexReg.getNode() != nullptr &&<br>
+             Base_Reg.getNode() != nullptr;<br>
+    }<br>
+<br>
     /// Return true if this addressing mode is already RIP-relative.<br>
     bool isRIPRelative() const {<br>
       if (BaseType != RegBase) return false;<br>
@@ -97,6 +102,10 @@ namespace {<br>
       return false;<br>
     }<br>
<br>
+    bool isLegalScale() const {<br>
+      return (Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8);<br>
+    }<br>
+<br>
     void setBaseReg(SDValue Reg) {<br>
       BaseType = RegBase;<br>
       Base_Reg = Reg;<br>
@@ -162,10 +171,13 @@ namespace {<br>
     /// If true, selector should try to optimize for minimum code size.<br>
     bool OptForMinSize;<br>
<br>
+    /// If true, selector should try to aggresively fold operands into AM.<br>
+    bool OptForAggressingFolding;<br>
+<br>
   public:<br>
     explicit X86DAGToDAGISel(X86TargetMachi<wbr>ne &tm, CodeGenOpt::Level OptLevel)<br>
         : SelectionDAGISel(tm, OptLevel), OptForSize(false),<br>
-          OptForMinSize(false) {}<br>
+          OptForMinSize(false), OptForAggressingFolding(false) {}<br>
<br>
     StringRef getPassName() const override {<br>
       return "X86 DAG->DAG Instruction Selection";<br>
@@ -184,6 +196,12 @@ namespace {<br>
<br>
     void PreprocessISelDAG() override;<br>
<br>
+    void setAggressiveOperandFolding(bo<wbr>ol val) {<br>
+      OptForAggressingFolding = val;<br>
+    }<br>
+<br>
+    bool getAggressiveOperandFolding() { return OptForAggressingFolding; }<br>
+<br>
 // Include the pieces autogenerated from the target description.<br>
 #include "X86GenDAGISel.inc"<br>
<br>
@@ -198,6 +216,7 @@ namespace {<br>
     bool matchAdd(SDValue N, X86ISelAddressMode &AM, unsigned Depth);<br>
     bool matchAddressRecursively(SDValu<wbr>e N, X86ISelAddressMode &AM,<br>
                                  unsigned Depth);<br>
+    bool matchAddressLEA(SDValue N, X86ISelAddressMode &AM);<br>
     bool matchAddressBase(SDValue N, X86ISelAddressMode &AM);<br>
     bool selectAddr(SDNode *Parent, SDValue N, SDValue &Base,<br>
                     SDValue &Scale, SDValue &Index, SDValue &Disp,<br>
@@ -447,6 +466,20 @@ namespace {<br>
<br>
     bool isMaskZeroExtended(SDNode *N) const;<br>
   };<br>
+<br>
+  class X86AggressiveOperandFolding {<br>
+  public:<br>
+    explicit X86AggressiveOperandFolding(X8<wbr>6DAGToDAGISel &ISel, bool val)<br>
+        : Selector(&ISel) {<br>
+      Selector->setAggressiveOperand<wbr>Folding(val);<br>
+    }<br>
+    ~X86AggressiveOperandFolding() {<br>
+      Selector->setAggressiveOperand<wbr>Folding(false);<br>
+    }<br>
+<br>
+  private:<br>
+    X86DAGToDAGISel *Selector;<br>
+  };<br>
 }<br>
<br>
<br>
@@ -1194,7 +1227,7 @@ static bool foldMaskAndShiftToScale(Sele<br>
   AM.IndexReg = NewSRL;<br>
   return false;<br>
 }<br>
-<br>
+<br>
 bool X86DAGToDAGISel::matchAddressR<wbr>ecursively(SDValue N, X86ISelAddressMode &AM,<br>
                                               unsigned Depth) {<br>
   SDLoc dl(N);<br>
@@ -1202,8 +1235,14 @@ bool X86DAGToDAGISel::matchAddressR<wbr>ecurs<br>
       dbgs() << "MatchAddress: ";<br>
       AM.dump();<br>
     });<br>
-  // Limit recursion.<br>
-  if (Depth > 5)<br>
+<br>
+  // Limit recursion. For aggressive operand folding recurse<br>
+  // till depth 8 which is the maximum legal scale value.<br>
+  auto getMaxOperandFoldingDepth = [&] () -> unsigned int {<br>
+      return getAggressiveOperandFolding() ? 8 : 5;<br>
+  };<br>
+<br>
+  if (Depth > getMaxOperandFoldingDepth())<br>
     return matchAddressBase(N, AM);<br>
<br>
   // If this is already a %rip relative address, we can only merge immediates<br>
@@ -1494,6 +1533,20 @@ bool X86DAGToDAGISel::matchAddressB<wbr>ase(S<br>
       return false;<br>
     }<br>
<br>
+    if (OptLevel != CodeGenOpt::None && getAggressiveOperandFolding() &&<br>
+        AM.BaseType == X86ISelAddressMode::RegBase) {<br>
+      if (AM.Base_Reg == N) {<br>
+        SDValue Base_Reg = AM.Base_Reg;<br>
+        AM.Base_Reg = AM.IndexReg;<br>
+        AM.IndexReg = Base_Reg;<br>
+        AM.Scale++;<br>
+        return false;<br>
+      } else if (AM.IndexReg == N) {<br>
+        AM.Scale++;<br>
+        return false;<br>
+      }<br>
+    }<br>
+<br>
     // Otherwise, we cannot select it.<br>
     return true;<br>
   }<br>
@@ -1729,7 +1782,7 @@ bool X86DAGToDAGISel::selectLEA64_3<wbr>2Addr<br>
                                          SDValue &Disp, SDValue &Segment) {<br>
   // Save the debug loc before calling selectLEAAddr, in case it invalidates N.<br>
   SDLoc DL(N);<br>
-<br>
+<br>
   if (!selectLEAAddr(N, Base, Scale, Index, Disp, Segment))<br>
     return false;<br>
<br>
@@ -1764,6 +1817,29 @@ bool X86DAGToDAGISel::selectLEA64_3<wbr>2Addr<br>
   return true;<br>
 }<br>
<br>
+bool X86DAGToDAGISel::matchAddressL<wbr>EA(SDValue N, X86ISelAddressMode &AM) {<br>
+  // Avoid enabling aggressive operand folding when node N is a part of loop.<br>
+  X86AggressiveOperandFolding Enable(*this, !CurDAG->IsDAGPartOfLoop);<br>
+<br>
+  bool matchRes = matchAddress(N, AM);<br>
+<br>
+  // Check for legality of scale when recursion unwinds back to the top.<br>
+  if (!matchRes) {<br>
+    if (!AM.isLegalScale())<br>
+      return true;<br>
+<br>
+    // Avoid creating costly complex LEAs having scale less than 2<br>
+    // within loop.<br>
+    if(CurDAG->IsDAGPartOfLoop && Subtarget->slow3OpsLEA() &&<br>
+        AM.Scale <= 2 && AM.hasComplexAddressingMode() &&<br>
+         (!AM.hasSymbolicDisplacement(<wbr>) && N.getOpcode() < ISD::BUILTIN_OP_END))<br>
+     return true;<br>
+  }<br>
+<br>
+  return matchRes;<br>
+}<br>
+<br>
+<br>
 /// Calls SelectAddr and determines if the maximal addressing<br>
 /// mode it matches can be cost effectively emitted as an LEA instruction.<br>
 bool X86DAGToDAGISel::selectLEAAddr<wbr>(SDValue N,<br>
@@ -1781,7 +1857,7 @@ bool X86DAGToDAGISel::selectLEAAddr<wbr>(SDVa<br>
   SDValue Copy = AM.Segment;<br>
   SDValue T = CurDAG->getRegister(0, MVT::i32);<br>
   AM.Segment = T;<br>
-  if (matchAddress(N, AM))<br>
+  if (matchAddressLEA(N, AM))<br>
     return false;<br>
   assert (T == AM.Segment);<br>
   AM.Segment = Copy;<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86O<wbr>ptimizeLEAs.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86OptimizeLEAs.cpp?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Target/X8<wbr>6/X86OptimizeLEAs.cpp?rev=3195<wbr>43&r1=319542&r2=319543&view=di<wbr>ff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Target/X86/X86O<wbr>ptimizeLEAs.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86O<wbr>ptimizeLEAs.cpp Fri Dec  1 06:07:38 2017<br>
@@ -27,6 +27,7 @@<br>
 #include "llvm/ADT/SmallVector.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
 #include "llvm/CodeGen/MachineBasicBloc<wbr>k.h"<br>
+#include "llvm/CodeGen/MachineDominator<wbr>s.h"<br>
 #include "llvm/CodeGen/MachineFunction.<wbr>h"<br>
 #include "llvm/CodeGen/MachineFunctionP<wbr>ass.h"<br>
 #include "llvm/CodeGen/MachineInstr.h"<br>
@@ -58,6 +59,7 @@ static cl::opt<bool><br>
                      cl::init(false));<br>
<br>
 STATISTIC(NumSubstLEAs, "Number of LEA instruction substitutions");<br>
+STATISTIC(NumFactoredLEAs, "Number of LEAs factorized");<br>
 STATISTIC(NumRedundantLEAs, "Number of redundant LEA instructions removed");<br>
<br>
 /// \brief Returns true if two machine operands are identical and they are not<br>
@@ -65,6 +67,10 @@ STATISTIC(NumRedundantLEAs, "Number of r<br>
 static inline bool isIdenticalOp(const MachineOperand &MO1,<br>
                                  const MachineOperand &MO2);<br>
<br>
+/// \brief Returns true if two machine instructions have identical operands.<br>
+static bool isIdenticalMI(MachineRegisterI<wbr>nfo *MRI, const MachineOperand &MO1,<br>
+                          const MachineOperand &MO2);<br>
+<br>
 /// \brief Returns true if two address displacement operands are of the same<br>
 /// type and use the same symbol/index/address regardless of the offset.<br>
 static bool isSimilarDispOp(const MachineOperand &MO1,<br>
@@ -73,6 +79,9 @@ static bool isSimilarDispOp(const Machin<br>
 /// \brief Returns true if the instruction is LEA.<br>
 static inline bool isLEA(const MachineInstr &MI);<br>
<br>
+/// \brief Returns true if Definition of Operand is a copylike instruction.<br>
+static bool isDefCopyLike(MachineRegisterI<wbr>nfo *MRI, const MachineOperand &Opr);<br>
+<br>
 namespace {<br>
<br>
 /// A key based on instruction's memory operands.<br>
@@ -80,15 +89,35 @@ class MemOpKey {<br>
 public:<br>
   MemOpKey(const MachineOperand *Base, const MachineOperand *Scale,<br>
            const MachineOperand *Index, const MachineOperand *Segment,<br>
-           const MachineOperand *Disp)<br>
-      : Disp(Disp) {<br>
+           const MachineOperand *Disp, bool DispCheck = false)<br>
+      : Disp(Disp), DeepCheck(DispCheck) {<br>
     Operands[0] = Base;<br>
     Operands[1] = Scale;<br>
     Operands[2] = Index;<br>
     Operands[3] = Segment;<br>
   }<br>
<br>
+  /// Checks operands of MemOpKey are identical, if Base or Index<br>
+  /// operand definitions are of kind SUBREG_TO_REG then compare<br>
+  /// operands of defining MI.<br>
+  bool performDeepCheck(const MemOpKey &Other) const {<br>
+    MachineInstr *MI = const_cast<MachineInstr *>(Operands[0]->getParent());<br>
+    MachineRegisterInfo *MRI = MI->getRegInfo();<br>
+<br>
+    for (int i = 0; i < 4; i++) {<br>
+      bool CopyLike = isDefCopyLike(MRI, *Operands[i]);<br>
+      if (CopyLike && !isIdenticalMI(MRI, *Operands[i], *Other.Operands[i]))<br>
+        return false;<br>
+      else if (!CopyLike && !isIdenticalOp(*Operands[i], *Other.Operands[i]))<br>
+        return false;<br>
+    }<br>
+    return isIdenticalOp(*Disp, *Other.Disp);<br>
+  }<br>
+<br>
   bool operator==(const MemOpKey &Other) const {<br>
+    if (DeepCheck)<br>
+      return performDeepCheck(Other);<br>
+<br>
     // Addresses' bases, scales, indices and segments must be identical.<br>
     for (int i = 0; i < 4; ++i)<br>
       if (!isIdenticalOp(*Operands[i], *Other.Operands[i]))<br>
@@ -106,6 +135,12 @@ public:<br>
<br>
   // Address' displacement operand.<br>
   const MachineOperand *Disp;<br>
+<br>
+  // If true checks Address' base, index, segment and<br>
+  // displacement are identical, in additions if base/index<br>
+  // are defined by copylike instruction then futher<br>
+  // compare the operands of the defining instruction.<br>
+  bool DeepCheck;<br>
 };<br>
<br>
 } // end anonymous namespace<br>
@@ -131,12 +166,34 @@ template <> struct DenseMapInfo<MemOpKey<br>
   static unsigned getHashValue(const MemOpKey &Val) {<br>
     // Checking any field of MemOpKey is enough to determine if the key is<br>
     // empty or tombstone.<br>
+    hash_code Hash(0);<br>
     assert(Val.Disp != PtrInfo::getEmptyKey() && "Cannot hash the empty key");<br>
     assert(Val.Disp != PtrInfo::getTombstoneKey() &&<br>
            "Cannot hash the tombstone key");<br>
<br>
-    hash_code Hash = hash_combine(*Val.Operands[0], *Val.Operands[1],<br>
-                                  *Val.Operands[2], *Val.Operands[3]);<br>
+    auto getMIHash = [](MachineInstr *MI) -> hash_code {<br>
+      hash_code h(0);<br>
+      for (unsigned i = 1, e = MI->getNumOperands(); i < e; i++)<br>
+        h = hash_combine(h, MI->getOperand(i));<br>
+      return h;<br>
+    };<br>
+<br>
+    const MachineOperand &Base = *Val.Operands[0];<br>
+    const MachineOperand &Index = *Val.Operands[2];<br>
+    MachineInstr *MI = const_cast<MachineInstr *>(Base.getParent());<br>
+    MachineRegisterInfo *MRI = MI->getRegInfo();<br>
+<br>
+    if (isDefCopyLike(MRI, Base))<br>
+      Hash = getMIHash(MRI->getVRegDef(Base<wbr>.getReg()));<br>
+    else<br>
+      Hash = hash_combine(Hash, Base);<br>
+<br>
+    if (isDefCopyLike(MRI, Index))<br>
+      Hash = getMIHash(MRI->getVRegDef(Inde<wbr>x.getReg()));<br>
+    else<br>
+      Hash = hash_combine(Hash, Index);<br>
+<br>
+    Hash = hash_combine(Hash, *Val.Operands[1], *Val.Operands[3]);<br>
<br>
     // If the address displacement is an immediate, it should not affect the<br>
     // hash so that memory operands which differ only be immediate displacement<br>
@@ -196,6 +253,16 @@ static inline MemOpKey getMemOpKey(const<br>
                   &MI.getOperand(N + X86::AddrDisp));<br>
 }<br>
<br>
+static inline MemOpKey getMemOpCSEKey(const MachineInstr &MI, unsigned N) {<br>
+  static MachineOperand DummyScale = MachineOperand::CreateImm(1);<br>
+  assert((isLEA(MI) || MI.mayLoadOrStore()) &&<br>
+         "The instruction must be a LEA, a load or a store");<br>
+  return MemOpKey(&MI.getOperand(N + X86::AddrBaseReg), &DummyScale,<br>
+                  &MI.getOperand(N + X86::AddrIndexReg),<br>
+                  &MI.getOperand(N + X86::AddrSegmentReg),<br>
+                  &MI.getOperand(N + X86::AddrDisp), true);<br>
+}<br>
+<br>
 static inline bool isIdenticalOp(const MachineOperand &MO1,<br>
                                  const MachineOperand &MO2) {<br>
   return MO1.isIdenticalTo(MO2) &&<br>
@@ -203,6 +270,27 @@ static inline bool isIdenticalOp(const M<br>
           !TargetRegisterInfo::isPhysic<wbr>alRegister(MO1.getReg()));<br>
 }<br>
<br>
+static bool isIdenticalMI(MachineRegisterI<wbr>nfo *MRI, const MachineOperand &MO1,<br>
+                          const MachineOperand &MO2) {<br>
+  MachineInstr *MI1 = nullptr;<br>
+  MachineInstr *MI2 = nullptr;<br>
+  if (!MO1.isReg() || !MO2.isReg())<br>
+    return false;<br>
+<br>
+  MI1 = MRI->getVRegDef(MO1.getReg());<br>
+  MI2 = MRI->getVRegDef(MO2.getReg());<br>
+  if (!MI1 || !MI2)<br>
+    return false;<br>
+  if (MI1->getOpcode() != MI2->getOpcode())<br>
+    return false;<br>
+  if (MI1->getNumOperands() != MI2->getNumOperands())<br>
+    return false;<br>
+  for (unsigned i = 1, e = MI1->getNumOperands(); i < e; ++i)<br>
+    if (!isIdenticalOp(MI1->getOperan<wbr>d(i), MI2->getOperand(i)))<br>
+      return false;<br>
+  return true;<br>
+}<br>
+<br>
 #ifndef NDEBUG<br>
 static bool isValidDispOp(const MachineOperand &MO) {<br>
   return MO.isImm() || MO.isCPI() || MO.isJTI() || MO.isSymbol() ||<br>
@@ -234,8 +322,150 @@ static inline bool isLEA(const MachineIn<br>
          Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;<br>
 }<br>
<br>
+static bool isDefCopyLike(MachineRegisterI<wbr>nfo *MRI, const MachineOperand &Opr) {<br>
+  bool isInstrErased = !(Opr.isReg() && Opr.getParent()->getParent());<br>
+  if (!Opr.isReg() || isInstrErased ||<br>
+      TargetRegisterInfo::isPhysical<wbr>Register(Opr.getReg()))<br>
+    return false;<br>
+  MachineInstr *MI = MRI->getVRegDef(Opr.getReg());<br>
+  return MI && MI->isCopyLike();<br>
+}<br>
+<br>
 namespace {<br>
<br>
+/// This class captures the functions and attributes<br>
+/// needed to factorize LEA within and across basic<br>
+/// blocks.LEA instruction with same BASE,OFFSET and<br>
+/// INDEX are the candidates for factorization.<br>
+class FactorizeLEAOpt {<br>
+public:<br>
+  using LEAListT = std::list<MachineInstr *>;<br>
+  using LEAMapT = DenseMap<MemOpKey, LEAListT>;<br>
+  using ValueT = DenseMap<MemOpKey, unsigned>;<br>
+  using ScopeEntryT = std::pair<MachineBasicBlock *, ValueT>;<br>
+  using ScopeStackT = std::vector<ScopeEntryT>;<br>
+<br>
+  FactorizeLEAOpt() = default;<br>
+  FactorizeLEAOpt(const FactorizeLEAOpt &) = delete;<br>
+  FactorizeLEAOpt &operator=(const FactorizeLEAOpt &) = delete;<br>
+<br>
+  void performCleanup() {<br>
+    for (auto LEA : removedLEAs)<br>
+      LEA->eraseFromParent();<br>
+    LEAs.clear();<br>
+    Stack.clear();<br>
+    removedLEAs.clear();<br>
+  }<br>
+<br>
+  LEAMapT &getLEAMap() { return LEAs; }<br>
+  ScopeEntryT *getTopScope() { return &Stack.back(); }<br>
+<br>
+  void addForLazyRemoval(MachineInstr *Instr) { removedLEAs.insert(Instr); }<br>
+<br>
+  bool checkIfScheduledForRemoval(Mac<wbr>hineInstr *Instr) {<br>
+    return removedLEAs.find(Instr) != removedLEAs.end();<br>
+  }<br>
+<br>
+  /// Push the ScopeEntry for the BasicBlock over Stack.<br>
+  /// Also traverses over list of instruction and update<br>
+  /// LEAs Map and ScopeEntry for each LEA instruction<br>
+  /// found using insertLEA().<br>
+  void collectDataForBasicBlock(Machi<wbr>neBasicBlock *MBB);<br>
+<br>
+  /// Stores the size of MachineInstr list corrosponding<br>
+  /// to key K from LEAs MAP into the ScopeEntry of<br>
+  /// the basic block, then insert the LEA at the beginning<br>
+  /// of the list.<br>
+  void insertLEA(MachineInstr *MI);<br>
+<br>
+  /// Pops out ScopeEntry of top most BasicBlock from the stack<br>
+  /// and remove the LEA instructions contained in the scope<br>
+  /// from the LEAs Map.<br>
+  void removeDataForBasicBlock();<br>
+<br>
+  /// If LEA contains Physical Registers then its not a candidate<br>
+  /// for factorizations since physical registers may violate SSA<br>
+  /// semantics of MI.<br>
+  bool containsPhyReg(MachineInstr *MI, unsigned RecLevel);<br>
+<br>
+private:<br>
+  ScopeStackT Stack;<br>
+  LEAMapT LEAs;<br>
+  std::set<MachineInstr *> removedLEAs;<br>
+};<br>
+<br>
+void FactorizeLEAOpt::collectDataFo<wbr>rBasicBlock(MachineBasicBlock *MBB) {<br>
+  ValueT EmptyMap;<br>
+  ScopeEntryT SE = std::make_pair(MBB, EmptyMap);<br>
+  Stack.push_back(SE);<br>
+  for (auto &MI : *MBB) {<br>
+    if (isLEA(MI))<br>
+      insertLEA(&MI);<br>
+  }<br>
+}<br>
+<br>
+void FactorizeLEAOpt::removeDataFor<wbr>BasicBlock() {<br>
+  ScopeEntryT &SE = Stack.back();<br>
+  for (auto MapEntry : SE.second) {<br>
+    LEAMapT::iterator Itr = LEAs.find(MapEntry.first);<br>
+    assert((Itr != LEAs.end()) &&<br>
+           "LEAs map must have a node corresponding to ScopeEntry's Key.");<br>
+<br>
+    while (((*Itr).second.size() > MapEntry.second))<br>
+      (*Itr).second.pop_front();<br>
+    // If list goes empty remove entry from LEAs Map.<br>
+    if ((*Itr).second.empty())<br>
+      LEAs.erase(Itr);<br>
+  }<br>
+  Stack.pop_back();<br>
+}<br>
+<br>
+bool FactorizeLEAOpt::containsPhyRe<wbr>g(MachineInstr *MI, unsigned RecLevel) {<br>
+  if (!MI || !RecLevel)<br>
+    return false;<br>
+<br>
+  MachineRegisterInfo *MRI = MI->getRegInfo();<br>
+  for (auto Operand : MI->operands()) {<br>
+    if (!Operand.isReg())<br>
+      continue;<br>
+    if (TargetRegisterInfo::isPhysica<wbr>lRegister(Operand.getReg()))<br>
+      return true;<br>
+    MachineInstr *OperDefMI = MRI->getVRegDef(Operand.getReg<wbr>());<br>
+    if (OperDefMI && (MI != OperDefMI) && OperDefMI->isCopyLike() &&<br>
+        containsPhyReg(OperDefMI, RecLevel - 1))<br>
+      return true;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+void FactorizeLEAOpt::insertLEA(Mac<wbr>hineInstr *MI) {<br>
+  unsigned lsize;<br>
+  if (containsPhyReg(MI, 2))<br>
+    return;<br>
+<br>
+  // Factorization is beneficial only for complex LEAs.<br>
+  MachineOperand &Base = MI->getOperand(1);<br>
+  MachineOperand &Index = MI->getOperand(3);<br>
+  MachineOperand &Offset = MI->getOperand(4);<br>
+  if ((Offset.isImm() && !Offset.getImm()) ||<br>
+      (!Base.isReg() || !Base.getReg()) || (!Index.isReg() || !Index.getReg()))<br>
+    return;<br>
+<br>
+  MemOpKey Key = getMemOpCSEKey(*MI, 1);<br>
+  ScopeEntryT *TopScope = getTopScope();<br>
+<br>
+  LEAMapT::iterator Itr = LEAs.find(Key);<br>
+  if (Itr == LEAs.end()) {<br>
+    lsize = 0;<br>
+    LEAs[Key].push_front(MI);<br>
+  } else {<br>
+    lsize = (*Itr).second.size();<br>
+    (*Itr).second.push_front(MI);<br>
+  }<br>
+  if (TopScope->second.find(Key) == TopScope->second.end())<br>
+    TopScope->second[Key] = lsize;<br>
+}<br>
+<br>
 class OptimizeLEAPass : public MachineFunctionPass {<br>
 public:<br>
   OptimizeLEAPass() : MachineFunctionPass(ID) {}<br>
@@ -247,6 +477,12 @@ public:<br>
   /// been calculated by LEA. Also, remove redundant LEAs.<br>
   bool runOnMachineFunction(MachineFu<wbr>nction &MF) override;<br>
<br>
+  void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
+    AU.setPreservesCFG();<br>
+    MachineFunctionPass::getAnalys<wbr>isUsage(AU);<br>
+    AU.addRequired<MachineDominato<wbr>rTree>();<br>
+  }<br>
+<br>
 private:<br>
   using MemOpMap = DenseMap<MemOpKey, SmallVector<MachineInstr *, 16>>;<br>
<br>
@@ -292,8 +528,24 @@ private:<br>
   /// \brief Removes LEAs which calculate similar addresses.<br>
   bool removeRedundantLEAs(MemOpMap &LEAs);<br>
<br>
+  /// \brief Visit over basic blocks, collect LEAs in a scoped<br>
+  ///  hash map (FactorizeLEAOpt::LEAs) and try to factor them out.<br>
+  bool FactorizeLEAsAllBasicBlocks(Ma<wbr>chineFunction &MF);<br>
+<br>
+  bool FactorizeLEAsBasicBlock(Machin<wbr>eDomTreeNode *DN);<br>
+<br>
+  /// \brief Factor out LEAs which share Base,Index,Offset and Segment.<br>
+  bool processBasicBlock(const MachineBasicBlock &MBB);<br>
+<br>
+  /// \brief Try to replace LEA with a lower strength instruction<br>
+  /// to improves latency and throughput.<br>
+  bool strengthReduceLEAs(MemOpMap &LEAs, const MachineBasicBlock &MBB);<br>
+<br>
   DenseMap<const MachineInstr *, unsigned> InstrPos;<br>
<br>
+  FactorizeLEAOpt FactorOpt;<br>
+<br>
+  MachineDominatorTree *DT;<br>
   MachineRegisterInfo *MRI;<br>
   const X86InstrInfo *TII;<br>
   const X86RegisterInfo *TRI;<br>
@@ -489,7 +741,9 @@ void OptimizeLEAPass::findLEAs(cons<wbr>t Mac<br>
 bool OptimizeLEAPass::removeRedunda<wbr>ntAddrCalc(MemOpMap &LEAs) {<br>
   bool Changed = false;<br>
<br>
-  assert(!LEAs.empty());<br>
+  if (LEAs.empty())<br>
+    return Changed;<br>
+<br>
   MachineBasicBlock *MBB = (*LEAs.begin()->second.begin()<wbr>)->getParent();<br>
<br>
   // Process all instructions in basic block.<br>
@@ -659,6 +913,10 @@ bool OptimizeLEAPass::removeRedunda<wbr>ntLEA<br>
         // Erase removed LEA from the list.<br>
         I2 = List.erase(I2);<br>
<br>
+        // If List becomes empty remove it from LEAs map.<br>
+        if (List.empty())<br>
+          LEAs.erase(E.first);<br>
+<br>
         Changed = true;<br>
       }<br>
       ++I1;<br>
@@ -668,6 +926,217 @@ bool OptimizeLEAPass::removeRedunda<wbr>ntLEA<br>
   return Changed;<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>
+bool OptimizeLEAPass::strengthReduc<wbr>eLEAs(MemOpMap &LEAs,<br>
+                                         const MachineBasicBlock &BB) {<br>
+  bool Changed = false;<br>
+<br>
+  // Loop over all entries in the table.<br>
+  for (auto &E : LEAs) {<br>
+    auto &List = E.second;<br>
+<br>
+    // Loop over all LEA pairs.<br>
+    auto I1 = List.begin();<br>
+    while (I1 != List.end()) {<br>
+      MachineInstrBuilder NewMI;<br>
+      MachineInstr &First = **I1;<br>
+      MachineOperand &Res = First.getOperand(0);<br>
+      MachineOperand &Base = First.getOperand(1);<br>
+      MachineOperand &Scale = First.getOperand(2);<br>
+      MachineOperand &Index = First.getOperand(3);<br>
+      MachineOperand &Offset = First.getOperand(4);<br>
+<br>
+      const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(First<wbr>.getOpcode()));<br>
+      const DebugLoc DL = First.getDebugLoc();<br>
+<br>
+      if (!Base.isReg() || !Index.isReg() || !Index.getReg()) {<br>
+        I1++;<br>
+        continue;<br>
+      }<br>
+<br>
+      if (TargetRegisterInfo::isPhysica<wbr>lRegister(Res.getReg()) ||<br>
+          TargetRegisterInfo::isPhysical<wbr>Register(Base.getReg()) ||<br>
+          TargetRegisterInfo::isPhysical<wbr>Register(Index.getReg())) {<br>
+        I1++;<br>
+        continue;<br>
+      }<br>
+<br>
+      // Check for register class compatibility between Result and<br>
+      // Index operands.<br>
+      const TargetRegisterClass *ResRC = MRI->getRegClass(Res.getReg())<wbr>;<br>
+      const TargetRegisterClass *IndexRC = MRI->getRegClass(Index.getReg(<wbr>));<br>
+      if (TRI->getRegSizeInBits(*ResRC) != TRI->getRegSizeInBits(*IndexRC<wbr>)) {<br>
+        I1++;<br>
+        continue;<br>
+      }<br>
+<br>
+      MachineBasicBlock &MBB = *(const_cast<MachineBasicBlock *>(&BB));<br>
+      // R = B + I<br>
+      if (Scale.isImm() && Scale.getImm() == 1 && Offset.isImm() &&<br>
+          !Offset.getImm()) {<br>
+        NewMI = BuildMI(MBB, &First, DL, ADDrr)<br>
+                    .addDef(Res.getReg())<br>
+                    .addUse(Base.getReg())<br>
+                    .addUse(Index.getReg());<br>
+        Changed = NewMI.getInstr() != nullptr;<br>
+        First.eraseFromParent();<br>
+        I1 = List.erase(I1);<br>
+<br>
+        // If List becomes empty remove it from LEAs map.<br>
+        if (List.empty())<br>
+          LEAs.erase(E.first);<br>
+      } else<br>
+        I1++;<br>
+    }<br>
+  }<br>
+  return Changed;<br>
+}<br>
+<br>
+bool OptimizeLEAPass::processBasicB<wbr>lock(const MachineBasicBlock &MBB) {<br>
+  bool cseDone = false;<br>
+<br>
+  // Legal scale value (1,2,4 & 8) vector.<br>
+  auto LegalScale = [](int scale) {<br>
+    return scale == 1 || scale == 2 || scale == 4 || scale == 8;<br>
+  };<br>
+<br>
+  auto CompareFn = [](const MachineInstr *Arg1,<br>
+                      const MachineInstr *Arg2) -> bool {<br>
+    return Arg1->getOperand(2).getImm() >= Arg2->getOperand(2).getImm();<br>
+  };<br>
+<br>
+  // Loop over all entries in the table.<br>
+  for (auto &E : FactorOpt.getLEAMap()) {<br>
+    auto &List = E.second;<br>
+    if (List.size() > 1)<br>
+      List.sort(CompareFn);<br>
+<br>
+    // Loop over all LEA pairs.<br>
+    for (auto Iter1 = List.begin(); Iter1 != List.end(); Iter1++) {<br>
+      for (auto Iter2 = std::next(Iter1); Iter2 != List.end(); Iter2++) {<br>
+        MachineInstr &LI1 = **Iter1;<br>
+        MachineInstr &LI2 = **Iter2;<br>
+<br>
+        if (!DT->dominates(&LI2, &LI1))<br>
+          continue;<br>
+<br>
+        int Scale1 = LI1.getOperand(2).getImm();<br>
+        int Scale2 = LI2.getOperand(2).getImm();<br>
+        assert(LI2.getOperand(0).isReg<wbr>() && "Result is a VirtualReg");<br>
+        DebugLoc DL = LI1.getDebugLoc();<br>
+<br>
+        // Continue if instruction has already been factorized.<br>
+        if (FactorOpt.checkIfScheduledFor<wbr>Removal(&LI1))<br>
+          continue;<br>
+<br>
+        int Factor = Scale1 - Scale2;<br>
+        if (Factor > 0 && LegalScale(Factor)) {<br>
+          MachineOperand NewBase = LI2.getOperand(0);<br>
+          MachineOperand NewIndex = LI1.getOperand(3);<br>
+<br>
+          const TargetRegisterClass *LI2ResRC =<br>
+              MRI->getRegClass(LI2.getOperan<wbr>d(0).getReg());<br>
+          const TargetRegisterClass *LI1BaseRC =<br>
+              MRI->getRegClass(LI1.getOperan<wbr>d(1).getReg());<br>
+<br>
+          if (TRI->getRegSizeInBits(*LI1Bas<wbr>eRC) ><br>
+              TRI->getRegSizeInBits(*LI2ResR<wbr>C)) {<br>
+            MachineInstr *LI1IndexDef =<br>
+                MRI->getVRegDef(LI1.getOperand<wbr>(3).getReg());<br>
+            if (LI1IndexDef->getOpcode() != TargetOpcode::SUBREG_TO_REG)<br>
+              continue;<br>
+            MachineOperand &SubReg = LI1IndexDef->getOperand(2);<br>
+            const TargetRegisterClass *SubRegRC =<br>
+                MRI->getRegClass(SubReg.getReg<wbr>());<br>
+            if (TRI->getRegSizeInBits(*SubReg<wbr>RC) !=<br>
+                TRI->getRegSizeInBits(*LI2ResR<wbr>C))<br>
+              continue;<br>
+            NewIndex = SubReg;<br>
+          }<br>
+<br>
+          DEBUG(dbgs() << "CSE LEAs: Candidate to replace: "; LI1.dump(););<br>
+          MachineInstrBuilder NewMI =<br>
+              BuildMI(*(const_cast<MachineBa<wbr>sicBlock *>(&MBB)), &LI1, DL,<br>
+                      TII->get(LI1.getOpcode()))<br>
+                  .addDef(LI1.getOperand(0).getR<wbr>eg()) // Dst   = Dst of LI1.<br>
+                  .addUse(NewBase.getReg())           // Base  = Dst to LI2.<br>
+                  .addImm(Factor)            // Scale = Diff b/w scales.<br>
+                  .addUse(NewIndex.getReg()) // Index = Index of LI1.<br>
+                  .addImm(0)                 // Disp  = 0<br>
+                  .addUse(<br>
+                      LI1.getOperand(5).getReg()); // Segment = Segmant of LI1.<br>
+<br>
+          cseDone = NewMI.getInstr() != nullptr;<br>
+<br>
+          /// To preserve the SSA nature we need to remove Def flag<br>
+          /// from old result.<br>
+          LI1.getOperand(0).setIsDef(fal<wbr>se);<br>
+<br>
+          /// Lazy removal shall ensure that replaced LEA remains<br>
+          /// till we finish processing all the basic block. This shall<br>
+          /// provide opportunity for further factorization based on<br>
+          /// the replaced LEA which will be legal since it has same<br>
+          /// destination as newly formed LEA.<br>
+          FactorOpt.addForLazyRemoval(&L<wbr>I1);<br>
+<br>
+          NumFactoredLEAs++;<br>
+          DEBUG(dbgs() << "CSE LEAs: Replaced by: "; NewMI->dump(););<br>
+        }<br>
+      }<br>
+    }<br>
+  }<br>
+  return cseDone;<br>
+}<br>
+<br>
+bool OptimizeLEAPass::FactorizeLEAs<wbr>BasicBlock(MachineDomTreeNode *DN) {<br>
+  bool Changed = false;<br>
+  using StackT = SmallVector<MachineDomTreeNode *, 16>;<br>
+  using VisitedNodeMapT = SmallSet<MachineDomTreeNode *, 16>;<br>
+<br>
+  StackT WorkList;<br>
+  VisitedNodeMapT DomNodeMap;<br>
+<br>
+  WorkList.push_back(DN);<br>
+  while (!WorkList.empty()) {<br>
+    MachineDomTreeNode *MDN = WorkList.back();<br>
+    FactorOpt.collectDataForBasicB<wbr>lock(MDN->getBlock());<br>
+    Changed |= processBasicBlock(*MDN->getBlo<wbr>ck());<br>
+<br>
+    if (DomNodeMap.find(MDN) == DomNodeMap.end()) {<br>
+      DomNodeMap.insert(MDN);<br>
+      for (auto Child : MDN->getChildren())<br>
+        WorkList.push_back(Child);<br>
+    }<br>
+<br>
+    MachineDomTreeNode *TDM = WorkList.back();<br>
+    if (MDN->getLevel() == TDM->getLevel()) {<br>
+      FactorOpt.removeDataForBasicBl<wbr>ock();<br>
+      DomNodeMap.erase(MDN);<br>
+      WorkList.pop_back();<br>
+    }<br>
+  }<br>
+  return Changed;<br>
+}<br>
+<br>
+bool OptimizeLEAPass::FactorizeLEAs<wbr>AllBasicBlocks(MachineFunction &MF) {<br>
+  bool Changed = FactorizeLEAsBasicBlock(DT->ge<wbr>tRootNode());<br>
+  FactorOpt.performCleanup();<br>
+  return Changed;<br>
+}<br>
+<br>
 bool OptimizeLEAPass::runOnMachineF<wbr>unction(MachineFunction &MF) {<br>
   bool Changed = false;<br>
<br>
@@ -677,6 +1146,10 @@ bool OptimizeLEAPass::runOnMachineF<wbr>uncti<br>
   MRI = &MF.getRegInfo();<br>
   TII = MF.getSubtarget<X86Subtarget>(<wbr>).getInstrInfo();<br>
   TRI = MF.getSubtarget<X86Subtarget>(<wbr>).getRegisterInfo();<br>
+  DT = &getAnalysis<MachineDominatorT<wbr>ree>();<br>
+<br>
+  // Attempt factorizing LEAs.<br>
+  Changed |= FactorizeLEAsAllBasicBlocks(MF<wbr>);<br>
<br>
   // Process all basic blocks.<br>
   for (auto &MBB : MF) {<br>
@@ -693,6 +1166,9 @@ bool OptimizeLEAPass::runOnMachineF<wbr>uncti<br>
     // Remove redundant LEA instructions.<br>
     Changed |= removeRedundantLEAs(LEAs);<br>
<br>
+    // Strength reduce LEA instructions.<br>
+    Changed |= strengthReduceLEAs(LEAs, MBB);<br>
+<br>
     // Remove redundant address calculations. Do it only for -Os/-Oz since only<br>
     // a code size gain is expected from this part of the pass.<br>
     if (MF.getFunction()->optForSize(<wbr>))<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/callingconv.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/callingconv.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/GlobalISel/callingconv.ll?<wbr>rev=319543&r1=319542&r2=319543<wbr>&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/callingconv.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/callingconv.ll Fri Dec  1 06:07:38 2017<br>
@@ -388,7 +388,7 @@ define void @test_variadic_call_2(i8** %<br>
 ; X32-NEXT:    movl 4(%ecx), %ecx<br>
 ; X32-NEXT:    movl %eax, (%esp)<br>
 ; X32-NEXT:    movl $4, %eax<br>
-; X32-NEXT:    leal (%esp,%eax), %eax<br>
+; X32-NEXT:    addl %esp, %eax<br>
 ; X32-NEXT:    movl %edx, 4(%esp)<br>
 ; X32-NEXT:    movl %ecx, 4(%eax)<br>
 ; X32-NEXT:    calll variadic_callee<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/gep.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/gep.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/GlobalISel/gep.ll?rev=3195<wbr>43&r1=319542&r2=319543&view=di<wbr>ff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/gep.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/gep.ll Fri Dec  1 06:07:38 2017<br>
@@ -5,10 +5,10 @@<br>
 define i32* @test_gep_i8(i32 *%arr, i8 %ind) {<br>
 ; X64_GISEL-LABEL: test_gep_i8:<br>
 ; X64_GISEL:       # BB#0:<br>
-; X64_GISEL-NEXT:    movq $4, %rax<br>
-; X64_GISEL-NEXT:    movsbq %sil, %rcx<br>
-; X64_GISEL-NEXT:    imulq %rax, %rcx<br>
-; X64_GISEL-NEXT:    leaq (%rdi,%rcx), %rax<br>
+; X64_GISEL-NEXT:    movq $4, %rcx<br>
+; X64_GISEL-NEXT:    movsbq %sil, %rax<br>
+; X64_GISEL-NEXT:    imulq %rcx, %rax<br>
+; X64_GISEL-NEXT:    addq %rdi, %rax<br>
 ; X64_GISEL-NEXT:    retq<br>
 ;<br>
 ; X64-LABEL: test_gep_i8:<br>
@@ -25,7 +25,7 @@ define i32* @test_gep_i8_const(i32 *%arr<br>
 ; X64_GISEL-LABEL: test_gep_i8_const:<br>
 ; X64_GISEL:       # BB#0:<br>
 ; X64_GISEL-NEXT:    movq $80, %rax<br>
-; X64_GISEL-NEXT:    leaq (%rdi,%rax), %rax<br>
+; X64_GISEL-NEXT:    addq %rdi, %rax<br>
 ; X64_GISEL-NEXT:    retq<br>
 ;<br>
 ; X64-LABEL: test_gep_i8_const:<br>
@@ -39,10 +39,10 @@ define i32* @test_gep_i8_const(i32 *%arr<br>
 define i32* @test_gep_i16(i32 *%arr, i16 %ind) {<br>
 ; X64_GISEL-LABEL: test_gep_i16:<br>
 ; X64_GISEL:       # BB#0:<br>
-; X64_GISEL-NEXT:    movq $4, %rax<br>
-; X64_GISEL-NEXT:    movswq %si, %rcx<br>
-; X64_GISEL-NEXT:    imulq %rax, %rcx<br>
-; X64_GISEL-NEXT:    leaq (%rdi,%rcx), %rax<br>
+; X64_GISEL-NEXT:    movq $4, %rcx<br>
+; X64_GISEL-NEXT:    movswq %si, %rax<br>
+; X64_GISEL-NEXT:    imulq %rcx, %rax<br>
+; X64_GISEL-NEXT:    addq %rdi, %rax<br>
 ; X64_GISEL-NEXT:    retq<br>
 ;<br>
 ; X64-LABEL: test_gep_i16:<br>
@@ -59,7 +59,7 @@ define i32* @test_gep_i16_const(i32 *%ar<br>
 ; X64_GISEL-LABEL: test_gep_i16_const:<br>
 ; X64_GISEL:       # BB#0:<br>
 ; X64_GISEL-NEXT:    movq $80, %rax<br>
-; X64_GISEL-NEXT:    leaq (%rdi,%rax), %rax<br>
+; X64_GISEL-NEXT:    addq %rdi, %rax<br>
 ; X64_GISEL-NEXT:    retq<br>
 ;<br>
 ; X64-LABEL: test_gep_i16_const:<br>
@@ -73,10 +73,10 @@ define i32* @test_gep_i16_const(i32 *%ar<br>
 define i32* @test_gep_i32(i32 *%arr, i32 %ind) {<br>
 ; X64_GISEL-LABEL: test_gep_i32:<br>
 ; X64_GISEL:       # BB#0:<br>
-; X64_GISEL-NEXT:    movq $4, %rax<br>
-; X64_GISEL-NEXT:    movslq %esi, %rcx<br>
-; X64_GISEL-NEXT:    imulq %rax, %rcx<br>
-; X64_GISEL-NEXT:    leaq (%rdi,%rcx), %rax<br>
+; X64_GISEL-NEXT:    movq $4, %rcx<br>
+; X64_GISEL-NEXT:    movslq %esi, %rax<br>
+; X64_GISEL-NEXT:    imulq %rcx, %rax<br>
+; X64_GISEL-NEXT:    addq %rdi, %rax<br>
 ; X64_GISEL-NEXT:    retq<br>
 ;<br>
 ; X64-LABEL: test_gep_i32:<br>
@@ -92,7 +92,7 @@ define i32* @test_gep_i32_const(i32 *%ar<br>
 ; X64_GISEL-LABEL: test_gep_i32_const:<br>
 ; X64_GISEL:       # BB#0:<br>
 ; X64_GISEL-NEXT:    movq $20, %rax<br>
-; X64_GISEL-NEXT:    leaq (%rdi,%rax), %rax<br>
+; X64_GISEL-NEXT:    addq %rdi, %rax<br>
 ; X64_GISEL-NEXT:    retq<br>
 ;<br>
 ; X64-LABEL: test_gep_i32_const:<br>
@@ -108,7 +108,7 @@ define i32* @test_gep_i64(i32 *%arr, i64<br>
 ; X64_GISEL:       # BB#0:<br>
 ; X64_GISEL-NEXT:    movq $4, %rax<br>
 ; X64_GISEL-NEXT:    imulq %rsi, %rax<br>
-; X64_GISEL-NEXT:    leaq (%rdi,%rax), %rax<br>
+; X64_GISEL-NEXT:    addq %rdi, %rax<br>
 ; X64_GISEL-NEXT:    retq<br>
 ;<br>
 ; X64-LABEL: test_gep_i64:<br>
@@ -123,7 +123,7 @@ define i32* @test_gep_i64_const(i32 *%ar<br>
 ; X64_GISEL-LABEL: test_gep_i64_const:<br>
 ; X64_GISEL:       # BB#0:<br>
 ; X64_GISEL-NEXT:    movq $20, %rax<br>
-; X64_GISEL-NEXT:    leaq (%rdi,%rax), %rax<br>
+; X64_GISEL-NEXT:    addq %rdi, %rax<br>
 ; X64_GISEL-NEXT:    retq<br>
 ;<br>
 ; X64-LABEL: test_gep_i64_const:<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/memop-scalar.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/memop-scalar.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/GlobalISel/memop-scalar.ll<wbr>?rev=319543&r1=319542&r2=31954<wbr>3&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/memop-scalar.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/Gl<wbr>obalISel/memop-scalar.ll Fri Dec  1 06:07:38 2017<br>
@@ -181,7 +181,7 @@ define i32 @test_gep_folding_largeGepInd<br>
 ; ALL-LABEL: test_gep_folding_largeGepIndex<wbr>:<br>
 ; ALL:       # BB#0:<br>
 ; ALL-NEXT:    movabsq $228719476720, %rax # imm = 0x3540BE3FF0<br>
-; ALL-NEXT:    leaq (%rdi,%rax), %rax<br>
+; ALL-NEXT:    addq %rdi, %rax<br>
 ; ALL-NEXT:    movl %esi, (%rax)<br>
 ; ALL-NEXT:    movl (%rax), %eax<br>
 ; ALL-NEXT:    retq<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse1.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt-cse1.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/lea-opt-cse1.ll?rev=319543<wbr>&r1=319542&r2=319543&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse1.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse1.ll Fri Dec  1 06:07:38 2017<br>
@@ -9,27 +9,21 @@ define void @test_func(%struct.SA* nocap<br>
 ; X64:       # BB#0: # %entry<br>
 ; X64-NEXT:    movl (%rdi), %eax<br>
 ; X64-NEXT:    movl 16(%rdi), %ecx<br>
-; X64-NEXT:    leal (%rax,%rcx), %edx<br>
 ; X64-NEXT:    leal 1(%rax,%rcx), %eax<br>
 ; X64-NEXT:    movl %eax, 12(%rdi)<br>
-; X64-NEXT:    leal 1(%rcx,%rdx), %eax<br>
+; X64-NEXT:    addq %ecx, %eax<br>
 ; X64-NEXT:    movl %eax, 16(%rdi)<br>
 ; X64-NEXT:    retq<br>
 ;<br>
 ; X86-LABEL: test_func:<br>
 ; X86:       # BB#0: # %entry<br>
-; X86-NEXT:    pushl %esi<br>
-; X86-NEXT:    .cfi_def_cfa_offset 8<br>
-; X86-NEXT:    .cfi_offset %esi, -8<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X86-NEXT:    movl (%eax), %ecx<br>
 ; X86-NEXT:    movl 16(%eax), %edx<br>
-; X86-NEXT:    leal 1(%ecx,%edx), %esi<br>
+; X86-NEXT:    leal 1(%ecx,%edx), %ecx<br>
+; X86-NEXT:    movl %ecx, 12(%eax)<br>
 ; X86-NEXT:    addl %edx, %ecx<br>
-; X86-NEXT:    movl %esi, 12(%eax)<br>
-; X86-NEXT:    leal 1(%edx,%ecx), %ecx<br>
 ; X86-NEXT:    movl %ecx, 16(%eax)<br>
-; X86-NEXT:    popl %esi<br>
 ; X86-NEXT:    retl<br>
  entry:<br>
    %h0 = getelementptr inbounds %struct.SA, %struct.SA* %ctx, i64 0, i32 0<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse2.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt-cse2.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/lea-opt-cse2.ll?rev=319543<wbr>&r1=319542&r2=319543&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse2.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse2.ll Fri Dec  1 06:07:38 2017<br>
@@ -1,6 +1,6 @@<br>
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.p<wbr>y<br>
-; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s -check-prefix=X64<br>
-; RUN: llc < %s -mtriple=i686-unknown   | FileCheck %s -check-prefix=X86<br>
+; RUN: llc < %s -mtriple=x86_64-unknown  -mattr=+slow-3ops-lea | FileCheck %s -check-prefix=X64<br>
+; RUN: llc < %s -mtriple=i686-unknown  -mattr=+slow-3ops-lea  | FileCheck %s -check-prefix=X86<br>
<br>
 %struct.SA = type { i32 , i32 , i32 , i32 , i32};<br>
<br>
@@ -10,43 +10,39 @@ define void @foo(%struct.SA* nocapture %<br>
 ; X64-NEXT:    .p2align 4, 0x90<br>
 ; X64-NEXT:  .LBB0_1: # %loop<br>
 ; X64-NEXT:    # =>This Inner Loop Header: Depth=1<br>
-; X64-NEXT:    movl (%rdi), %eax<br>
-; X64-NEXT:    movl 16(%rdi), %ecx<br>
-; X64-NEXT:    leal 1(%rax,%rcx), %edx<br>
-; X64-NEXT:    movl %edx, 12(%rdi)<br>
+; X64-NEXT:    movl 16(%rdi), %eax<br>
+; X64-NEXT:    movl (%rdi), %ecx<br>
+; X64-NEXT:    addl %eax, %ecx<br>
+; X64-NEXT:    incl %ecx<br>
+; X64-NEXT:    movl %ecx, 12(%rdi)<br>
 ; X64-NEXT:    decl %esi<br>
 ; X64-NEXT:    jne .LBB0_1<br>
 ; X64-NEXT:  # BB#2: # %exit<br>
-; X64-NEXT:    addl %ecx, %eax<br>
-; X64-NEXT:    leal 1(%rcx,%rax), %eax<br>
-; X64-NEXT:    movl %eax, 16(%rdi)<br>
+; X64-NEXT:    addl %eax, %ecx<br>
+; X64-NEXT:    movl %ecx, 16(%rdi)<br>
 ; X64-NEXT:    retq<br>
 ;<br>
 ; X86-LABEL: foo:<br>
 ; X86:       # BB#0: # %entry<br>
-; X86-NEXT:    pushl %edi<br>
-; X86-NEXT:    .cfi_def_cfa_offset 8<br>
 ; X86-NEXT:    pushl %esi<br>
-; X86-NEXT:    .cfi_def_cfa_offset 12<br>
-; X86-NEXT:    .cfi_offset %esi, -12<br>
-; X86-NEXT:    .cfi_offset %edi, -8<br>
+; X86-NEXT:    .cfi_def_cfa_offset 8<br>
+; X86-NEXT:    .cfi_offset %esi, -8<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X86-NEXT:    .p2align 4, 0x90<br>
 ; X86-NEXT:  .LBB0_1: # %loop<br>
 ; X86-NEXT:    # =>This Inner Loop Header: Depth=1<br>
-; X86-NEXT:    movl (%eax), %edx<br>
-; X86-NEXT:    movl 16(%eax), %esi<br>
-; X86-NEXT:    leal 1(%edx,%esi), %edi<br>
-; X86-NEXT:    movl %edi, 12(%eax)<br>
+; X86-NEXT:    movl 16(%eax), %edx<br>
+; X86-NEXT:    movl (%eax), %esi<br>
+; X86-NEXT:    addl %edx, %esi<br>
+; X86-NEXT:    incl %esi<br>
+; X86-NEXT:    movl %esi, 12(%eax)<br>
 ; X86-NEXT:    decl %ecx<br>
 ; X86-NEXT:    jne .LBB0_1<br>
 ; X86-NEXT:  # BB#2: # %exit<br>
-; X86-NEXT:    addl %esi, %edx<br>
-; X86-NEXT:    leal 1(%esi,%edx), %ecx<br>
-; X86-NEXT:    movl %ecx, 16(%eax)<br>
+; X86-NEXT:    addl %edx, %esi<br>
+; X86-NEXT:    movl %esi, 16(%eax)<br>
 ; X86-NEXT:    popl %esi<br>
-; X86-NEXT:    popl %edi<br>
 ; X86-NEXT:    retl<br>
  entry:<br>
    br label %loop<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse3.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt-cse3.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/lea-opt-cse3.ll?rev=319543<wbr>&r1=319542&r2=319543&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse3.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse3.ll Fri Dec  1 06:07:38 2017<br>
@@ -8,7 +8,7 @@ define i32 @foo(i32 %a, i32 %b) local_un<br>
 ; X64-NEXT:    # kill: %esi<def> %esi<kill> %rsi<def><br>
 ; X64-NEXT:    # kill: %edi<def> %edi<kill> %rdi<def><br>
 ; X64-NEXT:    leal 4(%rdi,%rsi,2), %ecx<br>
-; X64-NEXT:    leal 4(%rdi,%rsi,4), %eax<br>
+; X64-NEXT:    leal (%ecx,%esi,2), %eax<br>
 ; X64-NEXT:    imull %ecx, %eax<br>
 ; X64-NEXT:    retq<br>
 ;<br>
@@ -16,9 +16,9 @@ define i32 @foo(i32 %a, i32 %b) local_un<br>
 ; X86:       # BB#0: # %entry<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X86-NEXT:    leal 4(%ecx,%eax,2), %edx<br>
-; X86-NEXT:    leal 4(%ecx,%eax,4), %eax<br>
-; X86-NEXT:    imull %edx, %eax<br>
+; X86-NEXT:    leal 4(%ecx,%eax,2), %ecx<br>
+; X86-NEXT:    leal (%ecx,%eax,2), %eax<br>
+; X86-NEXT:    imull %ecx, %eax<br>
 ; X86-NEXT:    retl<br>
 entry:<br>
   %mul = shl i32 %b, 1<br>
@@ -36,7 +36,7 @@ define i32 @foo1(i32 %a, i32 %b) local_u<br>
 ; X64-NEXT:    # kill: %esi<def> %esi<kill> %rsi<def><br>
 ; X64-NEXT:    # kill: %edi<def> %edi<kill> %rdi<def><br>
 ; X64-NEXT:    leal 4(%rdi,%rsi,4), %ecx<br>
-; X64-NEXT:    leal 4(%rdi,%rsi,8), %eax<br>
+; X64-NEXT:    leal (%ecx,%esi,4), %eax<br>
 ; X64-NEXT:    imull %ecx, %eax<br>
 ; X64-NEXT:    retq<br>
 ;<br>
@@ -44,9 +44,9 @@ define i32 @foo1(i32 %a, i32 %b) local_u<br>
 ; X86:       # BB#0: # %entry<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X86-NEXT:    leal 4(%ecx,%eax,4), %edx<br>
-; X86-NEXT:    leal 4(%ecx,%eax,8), %eax<br>
-; X86-NEXT:    imull %edx, %eax<br>
+; X86-NEXT:    leal 4(%ecx,%eax,4), %ecx<br>
+; X86-NEXT:    leal (%ecx,%eax,4), %eax<br>
+; X86-NEXT:    imull %ecx, %eax<br>
 ; X86-NEXT:    retl<br>
 entry:<br>
   %mul = shl i32 %b, 2<br>
@@ -68,29 +68,23 @@ define i32 @foo1_mult_basic_blocks(i32 %<br>
 ; X64-NEXT:    cmpl $10, %ecx<br>
 ; X64-NEXT:    je .LBB2_2<br>
 ; X64-NEXT:  # BB#1: # %mid<br>
-; X64-NEXT:    leal 4(%rdi,%rsi,8), %eax<br>
-; X64-NEXT:    imull %eax, %ecx<br>
-; X64-NEXT:    movl %ecx, %eax<br>
+; X64-NEXT:    leal (%ecx,%esi,4), %eax<br>
+; X64-NEXT:    imull %ecx, %eax<br>
 ; X64-NEXT:  .LBB2_2: # %exit<br>
 ; X64-NEXT:    retq<br>
 ;<br>
 ; X86-LABEL: foo1_mult_basic_blocks:<br>
 ; X86:       # BB#0: # %entry<br>
-; X86-NEXT:    pushl %esi<br>
-; X86-NEXT:    .cfi_def_cfa_offset 8<br>
-; X86-NEXT:    .cfi_offset %esi, -8<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx<br>
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi<br>
-; X86-NEXT:    leal 4(%esi,%edx,4), %ecx<br>
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
+; X86-NEXT:    leal 4(%eax,%edx,4), %ecx<br>
 ; X86-NEXT:    xorl %eax, %eax<br>
 ; X86-NEXT:    cmpl $10, %ecx<br>
 ; X86-NEXT:    je .LBB2_2<br>
 ; X86-NEXT:  # BB#1: # %mid<br>
-; X86-NEXT:    leal 4(%esi,%edx,8), %eax<br>
-; X86-NEXT:    imull %eax, %ecx<br>
-; X86-NEXT:    movl %ecx, %eax<br>
+; X86-NEXT:    leal (%ecx,%edx,4), %eax<br>
+; X86-NEXT:    imull %ecx, %eax<br>
 ; X86-NEXT:  .LBB2_2: # %exit<br>
-; X86-NEXT:    popl %esi<br>
 ; X86-NEXT:    retl<br>
 entry:<br>
   %mul = shl i32 %b, 2<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse4.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt-cse4.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/lea-opt-cse4.ll?rev=319543<wbr>&r1=319542&r2=319543&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse4.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/le<wbr>a-opt-cse4.ll Fri Dec  1 06:07:38 2017<br>
@@ -1,41 +1,31 @@<br>
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.p<wbr>y<br>
-; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s -check-prefix=X64<br>
-; RUN: llc < %s -mtriple=i686-unknown   | FileCheck %s -check-prefix=X86<br>
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+slow-3ops-lea | FileCheck %s -check-prefix=X64<br>
+; RUN: llc < %s -mtriple=i686-unknown -mattr=+slow-3ops-lea | FileCheck %s -check-prefix=X86<br>
<br>
 %struct.SA = type { i32 , i32 , i32 , i32 , i32};<br>
<br>
 define void @foo(%struct.SA* nocapture %ctx, i32 %n) local_unnamed_addr #0 {<br>
 ; X64-LABEL: foo:<br>
 ; X64:       # BB#0: # %entry<br>
-; X64-NEXT:    movl 16(%rdi), %eax<br>
-; X64-NEXT:    movl (%rdi), %ecx<br>
-; X64-NEXT:    addl %eax, %ecx<br>
-; X64-NEXT:    addl %eax, %ecx<br>
-; X64-NEXT:    addl %eax, %ecx<br>
-; X64-NEXT:    leal (%rcx,%rax), %edx<br>
-; X64-NEXT:    leal 1(%rax,%rcx), %ecx<br>
-; X64-NEXT:    movl %ecx, 12(%rdi)<br>
-; X64-NEXT:    leal 1(%rax,%rdx), %eax<br>
+; X64-NEXT:    movl (%rdi), %eax<br>
+; X64-NEXT:    movl 16(%rdi), %ecx<br>
+; X64-NEXT:    leal (%rax,%rcx,4), %eax<br>
+; X64-NEXT:    addl $1, %eax<br>
+; X64-NEXT:    movl %eax, 12(%rdi)<br>
+; X64-NEXT:    addl %ecx, %eax<br>
 ; X64-NEXT:    movl %eax, 16(%rdi)<br>
 ; X64-NEXT:    retq<br>
 ;<br>
 ; X86-LABEL: foo:<br>
 ; X86:       # BB#0: # %entry<br>
-; X86-NEXT:    pushl %esi<br>
-; X86-NEXT:    .cfi_def_cfa_offset 8<br>
-; X86-NEXT:    .cfi_offset %esi, -8<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
-; X86-NEXT:    movl 16(%eax), %ecx<br>
-; X86-NEXT:    movl (%eax), %edx<br>
-; X86-NEXT:    addl %ecx, %edx<br>
-; X86-NEXT:    addl %ecx, %edx<br>
-; X86-NEXT:    addl %ecx, %edx<br>
-; X86-NEXT:    leal 1(%ecx,%edx), %esi<br>
-; X86-NEXT:    addl %ecx, %edx<br>
-; X86-NEXT:    movl %esi, 12(%eax)<br>
-; X86-NEXT:    leal 1(%ecx,%edx), %ecx<br>
+; X86-NEXT:    movl (%eax), %ecx<br>
+; X86-NEXT:    movl 16(%eax), %edx<br>
+; X86-NEXT:    leal (%ecx,%edx,4), %ecx<br>
+; X86-NEXT:    addl $1, %ecx<br>
+; X86-NEXT:    movl %ecx, 12(%eax)<br>
+; X86-NEXT:    addl %edx, %ecx<br>
 ; X86-NEXT:    movl %ecx, 16(%eax)<br>
-; X86-NEXT:    popl %esi<br>
 ; X86-NEXT:    retl<br>
  entry:<br>
    %h0 = getelementptr inbounds %struct.SA, %struct.SA* %ctx, i64 0, i32 0<br>
@@ -62,15 +52,15 @@ define void @foo_loop(%struct.SA* nocapt<br>
 ; X64-NEXT:    .p2align 4, 0x90<br>
 ; X64-NEXT:  .LBB1_1: # %loop<br>
 ; X64-NEXT:    # =>This Inner Loop Header: Depth=1<br>
-; X64-NEXT:    movl (%rdi), %ecx<br>
 ; X64-NEXT:    movl 16(%rdi), %eax<br>
-; X64-NEXT:    leal 1(%rcx,%rax), %edx<br>
-; X64-NEXT:    movl %edx, 12(%rdi)<br>
+; X64-NEXT:    movl (%rdi), %ecx<br>
+; X64-NEXT:    addl %eax, %ecx<br>
+; X64-NEXT:    incl %ecx<br>
+; X64-NEXT:    movl %ecx, 12(%rdi)<br>
 ; X64-NEXT:    decl %esi<br>
 ; X64-NEXT:    jne .LBB1_1<br>
 ; X64-NEXT:  # BB#2: # %exit<br>
 ; X64-NEXT:    addl %eax, %ecx<br>
-; X64-NEXT:    leal 1(%rax,%rcx), %ecx<br>
 ; X64-NEXT:    addl %eax, %ecx<br>
 ; X64-NEXT:    addl %eax, %ecx<br>
 ; X64-NEXT:    addl %eax, %ecx<br>
@@ -82,26 +72,23 @@ define void @foo_loop(%struct.SA* nocapt<br>
 ;<br>
 ; X86-LABEL: foo_loop:<br>
 ; X86:       # BB#0: # %entry<br>
-; X86-NEXT:    pushl %edi<br>
-; X86-NEXT:    .cfi_def_cfa_offset 8<br>
 ; X86-NEXT:    pushl %esi<br>
-; X86-NEXT:    .cfi_def_cfa_offset 12<br>
-; X86-NEXT:    .cfi_offset %esi, -12<br>
-; X86-NEXT:    .cfi_offset %edi, -8<br>
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx<br>
+; X86-NEXT:    .cfi_def_cfa_offset 8<br>
+; X86-NEXT:    .cfi_offset %esi, -8<br>
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X86-NEXT:    .p2align 4, 0x90<br>
 ; X86-NEXT:  .LBB1_1: # %loop<br>
 ; X86-NEXT:    # =>This Inner Loop Header: Depth=1<br>
-; X86-NEXT:    movl (%eax), %esi<br>
 ; X86-NEXT:    movl 16(%eax), %ecx<br>
-; X86-NEXT:    leal 1(%esi,%ecx), %edi<br>
-; X86-NEXT:    movl %edi, 12(%eax)<br>
-; X86-NEXT:    decl %edx<br>
+; X86-NEXT:    movl (%eax), %edx<br>
+; X86-NEXT:    addl %ecx, %edx<br>
+; X86-NEXT:    incl %edx<br>
+; X86-NEXT:    movl %edx, 12(%eax)<br>
+; X86-NEXT:    decl %esi<br>
 ; X86-NEXT:    jne .LBB1_1<br>
 ; X86-NEXT:  # BB#2: # %exit<br>
-; X86-NEXT:    addl %ecx, %esi<br>
-; X86-NEXT:    leal 1(%ecx,%esi), %edx<br>
+; X86-NEXT:    addl %ecx, %edx<br>
 ; X86-NEXT:    addl %ecx, %edx<br>
 ; X86-NEXT:    addl %ecx, %edx<br>
 ; X86-NEXT:    addl %ecx, %edx<br>
@@ -110,7 +97,6 @@ define void @foo_loop(%struct.SA* nocapt<br>
 ; X86-NEXT:    addl %ecx, %edx<br>
 ; X86-NEXT:    movl %edx, 16(%eax)<br>
 ; X86-NEXT:    popl %esi<br>
-; X86-NEXT:    popl %edi<br>
 ; X86-NEXT:    retl<br>
  entry:<br>
    br label %loop<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i16.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-i16.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/mul-constant-i16.ll?rev=31<wbr>9543&r1=319542&r2=319543&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i16.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i16.ll Fri Dec  1 06:07:38 2017<br>
@@ -558,11 +558,10 @@ define i16 @test_mul_by_28(i16 %x) {<br>
 define i16 @test_mul_by_29(i16 %x) {<br>
 ; X86-LABEL: test_mul_by_29:<br>
 ; X86:       # BB#0:<br>
-; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx<br>
-; X86-NEXT:    leal (%ecx,%ecx,8), %eax<br>
-; X86-NEXT:    leal (%eax,%eax,2), %eax<br>
-; X86-NEXT:    addl %ecx, %eax<br>
-; X86-NEXT:    addl %ecx, %eax<br>
+; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax<br>
+; X86-NEXT:    leal (%eax,%eax,8), %ecx<br>
+; X86-NEXT:    leal (%ecx,%ecx,2), %ecx<br>
+; X86-NEXT:    leal (%ecx,%eax,2), %eax<br>
 ; X86-NEXT:    # kill: %ax<def> %ax<kill> %eax<kill><br>
 ; X86-NEXT:    retl<br>
 ;<br>
@@ -571,8 +570,7 @@ define i16 @test_mul_by_29(i16 %x) {<br>
 ; X64-NEXT:    # kill: %edi<def> %edi<kill> %rdi<def><br>
 ; X64-NEXT:    leal (%rdi,%rdi,8), %eax<br>
 ; X64-NEXT:    leal (%rax,%rax,2), %eax<br>
-; X64-NEXT:    addl %edi, %eax<br>
-; X64-NEXT:    addl %edi, %eax<br>
+; X64-NEXT:    leal (%rax,%rdi,2), %eax<br>
 ; X64-NEXT:    # kill: %ax<def> %ax<kill> %eax<kill><br>
 ; X64-NEXT:    retq<br>
   %mul = mul nsw i16 %x, 29<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i32.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-i32.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/mul-constant-i32.ll?rev=31<wbr>9543&r1=319542&r2=319543&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i32.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i32.ll Fri Dec  1 06:07:38 2017<br>
@@ -1457,11 +1457,10 @@ define i32 @test_mul_by_28(i32 %x) {<br>
 define i32 @test_mul_by_29(i32 %x) {<br>
 ; X86-LABEL: test_mul_by_29:<br>
 ; X86:       # BB#0:<br>
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X86-NEXT:    leal (%ecx,%ecx,8), %eax<br>
-; X86-NEXT:    leal (%eax,%eax,2), %eax<br>
-; X86-NEXT:    addl %ecx, %eax<br>
-; X86-NEXT:    addl %ecx, %eax<br>
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
+; X86-NEXT:    leal (%eax,%eax,8), %ecx<br>
+; X86-NEXT:    leal (%ecx,%ecx,2), %ecx<br>
+; X86-NEXT:    leal (%ecx,%eax,2), %eax<br>
 ; X86-NEXT:    retl<br>
 ;<br>
 ; X64-HSW-LABEL: test_mul_by_29:<br>
@@ -1469,8 +1468,7 @@ define i32 @test_mul_by_29(i32 %x) {<br>
 ; X64-HSW-NEXT:    # kill: %edi<def> %edi<kill> %rdi<def><br>
 ; X64-HSW-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]<br>
 ; X64-HSW-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]<br>
-; X64-HSW-NEXT:    addl %edi, %eax # sched: [1:0.25]<br>
-; X64-HSW-NEXT:    addl %edi, %eax # sched: [1:0.25]<br>
+; X64-HSW-NEXT:    leal (%rax,%rdi,2), %eax # sched: [1:0.50]<br>
 ; X64-HSW-NEXT:    retq # sched: [2:1.00]<br>
 ;<br>
 ; X64-JAG-LABEL: test_mul_by_29:<br>
@@ -1478,8 +1476,7 @@ define i32 @test_mul_by_29(i32 %x) {<br>
 ; X64-JAG-NEXT:    # kill: %edi<def> %edi<kill> %rdi<def><br>
 ; X64-JAG-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]<br>
 ; X64-JAG-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]<br>
-; X64-JAG-NEXT:    addl %edi, %eax # sched: [1:0.50]<br>
-; X64-JAG-NEXT:    addl %edi, %eax # sched: [1:0.50]<br>
+; X64-JAG-NEXT:    leal (%rax,%rdi,2), %eax # sched: [1:0.50]<br>
 ; X64-JAG-NEXT:    retq # sched: [4:1.00]<br>
 ;<br>
 ; X86-NOOPT-LABEL: test_mul_by_29:<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i64.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-i64.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/mul-constant-i64.ll?rev=31<wbr>9543&r1=319542&r2=319543&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i64.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-i64.ll Fri Dec  1 06:07:38 2017<br>
@@ -1523,8 +1523,7 @@ define i64 @test_mul_by_29(i64 %x) {<br>
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X86-NEXT:    leal (%eax,%eax,8), %ecx<br>
 ; X86-NEXT:    leal (%ecx,%ecx,2), %ecx<br>
-; X86-NEXT:    addl %eax, %ecx<br>
-; X86-NEXT:    addl %eax, %ecx<br>
+; X86-NEXT:    leal (%ecx,%eax,2), %ecx<br>
 ; X86-NEXT:    movl $29, %eax<br>
 ; X86-NEXT:    mull {{[0-9]+}}(%esp)<br>
 ; X86-NEXT:    addl %ecx, %edx<br>
@@ -1534,16 +1533,14 @@ define i64 @test_mul_by_29(i64 %x) {<br>
 ; X64-HSW:       # BB#0:<br>
 ; X64-HSW-NEXT:    leaq (%rdi,%rdi,8), %rax # sched: [1:0.50]<br>
 ; X64-HSW-NEXT:    leaq (%rax,%rax,2), %rax # sched: [1:0.50]<br>
-; X64-HSW-NEXT:    addq %rdi, %rax # sched: [1:0.25]<br>
-; X64-HSW-NEXT:    addq %rdi, %rax # sched: [1:0.25]<br>
+; X64-HSW-NEXT:    leaq (%rax,%rdi,2), %rax # sched: [1:0.50]<br>
 ; X64-HSW-NEXT:    retq # sched: [2:1.00]<br>
 ;<br>
 ; X64-JAG-LABEL: test_mul_by_29:<br>
 ; X64-JAG:       # BB#0:<br>
 ; X64-JAG-NEXT:    leaq (%rdi,%rdi,8), %rax # sched: [1:0.50]<br>
 ; X64-JAG-NEXT:    leaq (%rax,%rax,2), %rax # sched: [1:0.50]<br>
-; X64-JAG-NEXT:    addq %rdi, %rax # sched: [1:0.50]<br>
-; X64-JAG-NEXT:    addq %rdi, %rax # sched: [1:0.50]<br>
+; X64-JAG-NEXT:    leaq (%rax,%rdi,2), %rax # sched: [1:0.50]<br>
 ; X64-JAG-NEXT:    retq # sched: [4:1.00]<br>
 ;<br>
 ; X86-NOOPT-LABEL: test_mul_by_29:<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-result.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-result.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/mul-constant-result.ll?rev<wbr>=319543&r1=319542&r2=319543&vi<wbr>ew=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-result.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/mu<wbr>l-constant-result.ll Fri Dec  1 06:07:38 2017<br>
@@ -164,8 +164,7 @@ define i32 @mult(i32, i32) local_unnamed<br>
 ; X86-NEXT:  .LBB0_35:<br>
 ; X86-NEXT:    leal (%eax,%eax,8), %ecx<br>
 ; X86-NEXT:    leal (%ecx,%ecx,2), %ecx<br>
-; X86-NEXT:    addl %eax, %ecx<br>
-; X86-NEXT:    addl %ecx, %eax<br>
+; X86-NEXT:    leal (%ecx,%eax,2), %eax<br>
 ; X86-NEXT:    popl %esi<br>
 ; X86-NEXT:    retl<br>
 ; X86-NEXT:  .LBB0_36:<br>
@@ -323,16 +322,17 @@ define i32 @mult(i32, i32) local_unnamed<br>
 ; X64-HSW-NEXT:  .LBB0_31:<br>
 ; X64-HSW-NEXT:    leal (%rax,%rax,8), %ecx<br>
 ; X64-HSW-NEXT:    leal (%rcx,%rcx,2), %ecx<br>
-; X64-HSW-NEXT:    jmp .LBB0_17<br>
-; X64-HSW-NEXT:  .LBB0_32:<br>
-; X64-HSW-NEXT:    leal (%rax,%rax,8), %ecx<br>
-; X64-HSW-NEXT:    leal (%rcx,%rcx,2), %ecx<br>
-; X64-HSW-NEXT:    addl %eax, %ecx<br>
 ; X64-HSW-NEXT:  .LBB0_17:<br>
 ; X64-HSW-NEXT:    addl %eax, %ecx<br>
 ; X64-HSW-NEXT:    movl %ecx, %eax<br>
 ; X64-HSW-NEXT:    # kill: %eax<def> %eax<kill> %rax<kill><br>
 ; X64-HSW-NEXT:    retq<br>
+; X64-HSW-NEXT:  .LBB0_32:<br>
+; X64-HSW-NEXT:    leal (%rax,%rax,8), %ecx<br>
+; X64-HSW-NEXT:    leal (%rcx,%rcx,2), %ecx<br>
+; X64-HSW-NEXT:    leal (%rcx,%rax,2), %eax<br>
+; X64-HSW-NEXT:    # kill: %eax<def> %eax<kill> %rax<kill><br>
+; X64-HSW-NEXT:    retq<br>
 ; X64-HSW-NEXT:  .LBB0_33:<br>
 ; X64-HSW-NEXT:    movl %eax, %ecx<br>
 ; X64-HSW-NEXT:    shll $5, %ecx<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/um<wbr>ul-with-overflow.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>X86/umul-with-overflow.ll?rev=<wbr>319543&r1=319542&r2=319543&vie<wbr>w=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/CodeGen/X86/um<wbr>ul-with-overflow.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/um<wbr>ul-with-overflow.ll Fri Dec  1 06:07:38 2017<br>
@@ -40,10 +40,10 @@ define i32 @test2(i32 %a, i32 %b) nounwi<br>
 ; X64-NEXT:    leal (%rdi,%rdi), %eax<br>
 ; X64-NEXT:    retq<br>
 entry:<br>
-       %tmp0 = add i32 %b, %a<br>
-       %tmp1 = call { i32, i1 } @llvm.umul.with.overflow.i32(i<wbr>32 %tmp0, i32 2)<br>
-       %tmp2 = extractvalue { i32, i1 } %tmp1, 0<br>
-       ret i32 %tmp2<br>
+        %tmp0 = add i32 %b, %a<br>
+        %tmp1 = call { i32, i1 } @llvm.umul.with.overflow.i32(i<wbr>32 %tmp0, i32 2)<br>
+        %tmp2 = extractvalue { i32, i1 } %tmp1, 0<br>
+        ret i32 %tmp2<br>
 }<br>
<br>
 define i32 @test3(i32 %a, i32 %b) nounwind readnone {<br>
@@ -64,8 +64,8 @@ define i32 @test3(i32 %a, i32 %b) nounwi<br>
 ; X64-NEXT:    mull %ecx<br>
 ; X64-NEXT:    retq<br>
 entry:<br>
-       %tmp0 = add i32 %b, %a<br>
-       %tmp1 = call { i32, i1 } @llvm.umul.with.overflow.i32(i<wbr>32 %tmp0, i32 4)<br>
-       %tmp2 = extractvalue { i32, i1 } %tmp1, 0<br>
-       ret i32 %tmp2<br>
+        %tmp0 = add i32 %b, %a<br>
+        %tmp1 = call { i32, i1 } @llvm.umul.with.overflow.i32(i<wbr>32 %tmp0, i32 4)<br>
+        %tmp2 = extractvalue { i32, i1 } %tmp1, 0<br>
+        ret i32 %tmp2<br>
 }<br>
<br>
Modified: llvm/trunk/test/Transforms/Loo<wbr>pStrengthReduce/X86/ivchain-X8<wbr>6.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/X86/ivchain-X86.ll?rev=319543&r1=319542&r2=319543&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Transfor<wbr>ms/LoopStrengthReduce/X86/ivch<wbr>ain-X86.ll?rev=319543&r1=31954<wbr>2&r2=319543&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/Loo<wbr>pStrengthReduce/X86/ivchain-X8<wbr>6.ll (original)<br>
+++ llvm/trunk/test/Transforms/Loo<wbr>pStrengthReduce/X86/ivchain-X8<wbr>6.ll Fri Dec  1 06:07:38 2017<br>
@@ -13,14 +13,14 @@<br>
 ; X64-NEXT: .p2align<br>
 ; X64: %loop<br>
 ; no complex address modes<br>
-; X64-NOT: (%{{[^)]+}},%{{[^)]+}},<br>
+; X64-NOT: [1-9]+(%{{[^)]+}},%{{[^)]+}},<br>
 ;<br>
 ; X32: @simple<br>
 ; no expensive address computation in the preheader<br>
 ; X32-NOT: imul<br>
 ; X32: %loop<br>
 ; no complex address modes<br>
-; X32-NOT: (%{{[^)]+}},%{{[^)]+}},<br>
+; X32-NOT: [1-9]+(%{{[^)]+}},%{{[^)]+}},<br>
 define i32 @simple(i32* %a, i32* %b, i32 %x) nounwind {<br>
 entry:<br>
   br label %loop<br>
@@ -103,7 +103,7 @@ exit:<br>
 ; X32-NOT: mov{{.*}}(%esp){{$}}<br>
 ; X32: %for.body{{$}}<br>
 ; no complex address modes<br>
-; X32-NOT: (%{{[^)]+}},%{{[^)]+}},<br>
+; X32-NOT: [1-9]+(%{{[^)]+}},%{{[^)]+}},<br>
 ; no reloads<br>
 ; X32-NOT: (%esp)<br>
 define void @extrastride(i8* nocapture %main, i32 %main_stride, i32* nocapture %res, i32 %x, i32 %y, i32 %z) nounwind {<br>
<br>
<br>
______________________________<wbr>_________________<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/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>