<div dir="ltr">Thanks Hans and Elad for repoting.<div><br></div><div>I was on the fix, build over my standalone machine takes a little longer.</div><div><br></div><div>Shall reintroduce patch with fixes.</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Sep 16, 2017 at 12:12 AM, Hans Wennborg <span dir="ltr"><<a href="mailto:hans@chromium.org" target="_blank">hans@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The same assert fires in Chromium. I've filed<br>
<a href="https://bugs.llvm.org/show_bug.cgi?id=34629" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_<wbr>bug.cgi?id=34629</a> and reverted in r313376.<br>
<div class="HOEnZb"><div class="h5"><br>
On Fri, Sep 15, 2017 at 4:27 AM, Cohen, Elad2 via llvm-commits<br>
<<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br>
> HI Jatin,<br>
><br>
> It looks like the commit broke some of the build bots:<br>
> <a href="http://lab.llvm.org:8011/builders/clang-cmake-x86_64-sde-avx512-linux/builds/884" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/<wbr>builders/clang-cmake-x86_64-<wbr>sde-avx512-linux/builds/884</a><br>
> <a href="http://lab.llvm.org:8011/builders/clang-cmake-x86_64-avx2-linux/builds/649" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/<wbr>builders/clang-cmake-x86_64-<wbr>avx2-linux/builds/649</a><br>
><br>
>         FAIL: MultiSource/Applications/JM/<wbr>ldecod/ldecod.compile_time<br>
><br>
> Could you have a look?<br>
><br>
> <a href="http://lab.llvm.org:8011/builders/clang-cmake-x86_64-avx2-linux/builds/649/steps/test-suite/logs/test.log" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/<wbr>builders/clang-cmake-x86_64-<wbr>avx2-linux/builds/649/steps/<wbr>test-suite/logs/test.log</a> :<br>
> clang-6.0: /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/llvm/lib/<wbr>CodeGen/MachineRegisterInfo.<wbr>cpp:366: llvm::MachineInstr* llvm::MachineRegisterInfo::<wbr>getVRegDef(unsigned int) const: Assertion `(I.atEnd() || std::next(I) == def_instr_end()) && "getVRegDef assumes a single definition or no definition"' failed.<br>
> ...<br>
> Stack dump:<br>
> 0.      Program arguments: /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/stage1.<wbr>install/bin/clang-6.0 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -disable-free -main-file-name erc_do_p.c -mrelocation-model static -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu broadwell -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -coverage-notes-file /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/test/<wbr>sandbox/build/MultiSource/<wbr>Applications/JM/ldecod/Output/<wbr>erc_do_p.llvm.gcno -resource-dir /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/stage1.<wbr>install/lib/clang/6.0.0 -D __USE_LARGEFILE64 -D _FILE_OFFSET_BITS=64 -I /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/test/<wbr>sandbox/build/MultiSource/<wbr>Applications/JM/ldecod -I /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/test/test-<wbr>suite/MultiSource/<wbr>Applications/JM/ldecod -I /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/test/test-<wbr>suite/include -I ../../../../include -D _GNU_SOURCE -D __STDC_LIMIT_MACROS -D NDEBUG -internal-isystem /usr/local/include -internal-isystem /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/stage1.<wbr>install/lib/clang/6.0.0/<wbr>include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -fdebug-compilation-dir /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/test/<wbr>sandbox/build/MultiSource/<wbr>Applications/JM/ldecod -ferror-limit 19 -fmessage-length 0 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -o Output/erc_do_p.llvm.o -x c /home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/test/test-<wbr>suite/MultiSource/<wbr>Applications/JM/ldecod/erc_do_<wbr>p.c<br>
> 1.      <eof> parser at end of file<br>
> 2.      Code generation<br>
> 3.      Running pass 'Function Pass Manager' on module '/home/ssglocal/clang-cmake-<wbr>x86_64-avx2-linux/clang-cmake-<wbr>x86_64-avx2-linux/test/test-<wbr>suite/MultiSource/<wbr>Applications/JM/ldecod/erc_do_<wbr>p.c'.<br>
> 4.      Running pass 'X86 LEA Optimize' on function '@edgeDistortion'<br>
> clang-6.0: error: unable to execute command: Aborted (core dumped)<br>
> clang-6.0: error: clang frontend command failed due to signal (use -v to see invocation)<br>
> clang version 6.0.0 (trunk 313343)<br>
><br>
><br>
><br>
> -----Original Message-----<br>
> From: llvm-commits [mailto:<a href="mailto:llvm-commits-bounces@lists.llvm.org">llvm-commits-bounces@<wbr>lists.llvm.org</a>] On Behalf Of Jatin Bhateja via llvm-commits<br>
> Sent: Friday, September 15, 2017 08:30<br>
> To: <a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
> Subject: [llvm] r313343 - [X86] PR32755 : Improvement in CodeGen instruction selection for LEAs.<br>
><br>
> Author: jbhateja<br>
> Date: Thu Sep 14 22:29:51 2017<br>
> New Revision: 313343<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=313343&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=313343&view=rev</a><br>
> Log:<br>
> [X86] PR32755 : Improvement in CodeGen instruction selection for LEAs.<br>
><br>
> Summary:<br>
>    1/  Operand folding during complex pattern matching for LEAs has been<br>
>        extended, such that it promotes Scale to accommodate similar operand<br>
>        appearing in the DAG.<br>
>        e.g.<br>
>           T1 = A + B<br>
>           T2 = T1 + 10<br>
>           T3 = T2 + A<br>
>        For above DAG rooted at T3, X86AddressMode will no 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<br>
>        so that if there is an opportunity then complex LEAs (having 3 operands)<br>
>        could be factored out.<br>
>        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,<br>
>       thus avoiding creation of any complex LEAs within a loop.<br>
><br>
> Reviewers: lsaba, RKSimon, craig.topper, qcolombet<br>
><br>
> Reviewed By: lsaba<br>
><br>
> Subscribers: spatel, igorb, llvm-commits<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D35014" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D35014</a><br>
><br>
> Modified:<br>
>     llvm/trunk/include/llvm/<wbr>CodeGen/MachineInstr.h<br>
>     llvm/trunk/include/llvm/<wbr>CodeGen/SelectionDAG.h<br>
>     llvm/trunk/lib/CodeGen/<wbr>SelectionDAG/SelectionDAGISel.<wbr>cpp<br>
>     llvm/trunk/lib/Target/X86/<wbr>X86ISelDAGToDAG.cpp<br>
>     llvm/trunk/lib/Target/X86/<wbr>X86OptimizeLEAs.cpp<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/callingconv.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/gep.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/memop-scalar.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse1.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse2.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse3.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse4.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i16.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i32.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i64.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-result.ll<br>
>     llvm/trunk/test/CodeGen/X86/<wbr>umul-with-overflow.ll<br>
>     llvm/trunk/test/Transforms/<wbr>LoopStrengthReduce/X86/<wbr>ivchain-X86.ll<br>
><br>
> Modified: llvm/trunk/include/llvm/<wbr>CodeGen/MachineInstr.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineInstr.h?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/CodeGen/MachineInstr.h?<wbr>rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/include/llvm/<wbr>CodeGen/MachineInstr.h (original)<br>
> +++ llvm/trunk/include/llvm/<wbr>CodeGen/MachineInstr.h Thu Sep 14 22:29:51 2017<br>
> @@ -1289,12 +1289,13 @@ public:<br>
>    /// Add all implicit def and use operands to this instruction.<br>
>    void addImplicitDefUseOperands(<wbr>MachineFunction &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/<wbr>CodeGen/SelectionDAG.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/CodeGen/SelectionDAG.h?<wbr>rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/include/llvm/<wbr>CodeGen/SelectionDAG.h (original)<br>
> +++ llvm/trunk/include/llvm/<wbr>CodeGen/SelectionDAG.h Thu Sep 14 22:29:51 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/<wbr>SelectionDAG/SelectionDAGISel.<wbr>cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>CodeGen/SelectionDAG/<wbr>SelectionDAGISel.cpp?rev=<wbr>313343&r1=313342&r2=313343&<wbr>view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/lib/CodeGen/<wbr>SelectionDAG/SelectionDAGISel.<wbr>cpp (original)<br>
> +++ llvm/trunk/lib/CodeGen/<wbr>SelectionDAG/SelectionDAGISel.<wbr>cpp Thu Sep 14 22:29:51 2017<br>
> @@ -26,6 +26,7 @@<br>
>  #include "llvm/Analysis/AliasAnalysis.<wbr>h"<br>
>  #include "llvm/Analysis/<wbr>BranchProbabilityInfo.h"<br>
>  #include "llvm/Analysis/CFG.h"<br>
> +#include "llvm/Analysis/LoopInfo.h"<br>
>  #include "llvm/Analysis/<wbr>OptimizationDiagnosticInfo.h"<br>
>  #include "llvm/Analysis/<wbr>TargetLibraryInfo.h"<br>
>  #include "llvm/CodeGen/FastISel.h"<br>
> @@ -325,6 +326,8 @@ void SelectionDAGISel::<wbr>getAnalysisUsage(<br>
>    if (OptLevel != CodeGenOpt::None)<br>
>      AU.addRequired<<wbr>AAResultsWrapperPass>();<br>
>    AU.addRequired<GCModuleInfo>()<wbr>;<br>
> +  if (OptLevel != CodeGenOpt::None)<br>
> +    AU.addRequired<<wbr>LoopInfoWrapperPass>();<br>
>    AU.addRequired<StackProtector><wbr>();<br>
>    AU.addPreserved<<wbr>StackProtector>();<br>
>    AU.addPreserved<GCModuleInfo>(<wbr>);<br>
> @@ -1419,6 +1422,7 @@ void SelectionDAGISel::<wbr>SelectAllBasicBlo<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>
> @@ -1596,6 +1600,13 @@ void SelectionDAGISel::<wbr>SelectAllBasicBlo<br>
>                                     FunctionBasedInstrumentation);<br>
>      }<br>
><br>
> +    if (OptLevel != CodeGenOpt::None) {<br>
> +      auto &LIWP = getAnalysis<<wbr>LoopInfoWrapperPass>();<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/<wbr>X86ISelDAGToDAG.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/Target/<wbr>X86/X86ISelDAGToDAG.cpp?rev=<wbr>313343&r1=313342&r2=313343&<wbr>view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/lib/Target/X86/<wbr>X86ISelDAGToDAG.cpp (original)<br>
> +++ llvm/trunk/lib/Target/X86/<wbr>X86ISelDAGToDAG.cpp Thu Sep 14 22:29:51 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() {<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(<wbr>X86TargetMachine &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(<wbr>bool val = false) {<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>
> @@ -197,6 +215,7 @@ namespace {<br>
>      bool matchAdd(SDValue N, X86ISelAddressMode &AM, unsigned Depth);<br>
>      bool matchAddressRecursively(<wbr>SDValue 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>
> @@ -425,6 +444,20 @@ namespace {<br>
><br>
>      bool matchBEXTRFromAnd(SDNode *Node);<br>
>    };<br>
> +<br>
> +  class X86AggressiveOperandFolding {<br>
> +  public:<br>
> +    explicit X86AggressiveOperandFolding(<wbr>X86DAGToDAGISel &ISel, bool val)<br>
> +        : Selector(&ISel) {<br>
> +      Selector-><wbr>setAggressiveOperandFolding(<wbr>val);<br>
> +    }<br>
> +    ~X86AggressiveOperandFolding() {<br>
> +      Selector-><wbr>setAggressiveOperandFolding(<wbr>false);<br>
> +    }<br>
> +<br>
> +  private:<br>
> +    X86DAGToDAGISel *Selector;<br>
> +  };<br>
>  }<br>
><br>
><br>
> @@ -1138,7 +1171,7 @@ static bool foldMaskAndShiftToScale(Sele<br>
>    AM.IndexReg = NewSRL;<br>
>    return false;<br>
>  }<br>
> -<br>
> +<br>
>  bool X86DAGToDAGISel::<wbr>matchAddressRecursively(<wbr>SDValue N, X86ISelAddressMode &AM,<br>
>                                                unsigned Depth) {<br>
>    SDLoc dl(N);<br>
> @@ -1146,8 +1179,11 @@ bool X86DAGToDAGISel::<wbr>matchAddressRecurs<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>
> +  unsigned MaxDepth = getAggressiveOperandFolding() ? 8 : 5;<br>
> +  if (Depth > MaxDepth)<br>
>      return matchAddressBase(N, AM);<br>
><br>
>    // If this is already a %rip relative address, we can only merge immediates<br>
> @@ -1438,6 +1474,20 @@ bool X86DAGToDAGISel::<wbr>matchAddressBase(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>
> @@ -1668,7 +1718,7 @@ bool X86DAGToDAGISel::selectLEA64_<wbr>32Addr<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>
> @@ -1703,6 +1753,29 @@ bool X86DAGToDAGISel::selectLEA64_<wbr>32Addr<br>
>    return true;<br>
>  }<br>
><br>
> +bool X86DAGToDAGISel::<wbr>matchAddressLEA(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() && 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::<wbr>selectLEAAddr(SDValue N,<br>
> @@ -1720,7 +1793,7 @@ bool X86DAGToDAGISel::<wbr>selectLEAAddr(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/<wbr>X86OptimizeLEAs.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86OptimizeLEAs.cpp?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/Target/<wbr>X86/X86OptimizeLEAs.cpp?rev=<wbr>313343&r1=313342&r2=313343&<wbr>view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/lib/Target/X86/<wbr>X86OptimizeLEAs.cpp (original)<br>
> +++ llvm/trunk/lib/Target/X86/<wbr>X86OptimizeLEAs.cpp Thu Sep 14 22:29:51 2017<br>
> @@ -22,6 +22,7 @@<br>
>  #include "X86Subtarget.h"<br>
>  #include "llvm/ADT/Statistic.h"<br>
>  #include "llvm/CodeGen/LiveVariables.h"<br>
> +#include "llvm/CodeGen/<wbr>MachineDominators.h"<br>
>  #include "llvm/CodeGen/<wbr>MachineFunctionPass.h"<br>
>  #include "llvm/CodeGen/<wbr>MachineInstrBuilder.h"<br>
>  #include "llvm/CodeGen/MachineOperand.<wbr>h"<br>
> @@ -44,6 +45,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>
> @@ -51,6 +53,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(<wbr>MachineRegisterInfo *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>
> @@ -59,21 +65,44 @@ 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(<wbr>MachineRegisterInfo *MRI, const MachineOperand &Opr);<br>
> +<br>
>  namespace {<br>
>  /// A key based on instruction's memory operands.<br>
>  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>
> @@ -91,6 +120,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>
>  } // end anonymous namespace<br>
><br>
> @@ -114,12 +149,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(<wbr>Base.getReg()));<br>
> +    else<br>
> +      Hash = hash_combine(Hash, Base);<br>
> +<br>
> +    if (isDefCopyLike(MRI, Index))<br>
> +      Hash = getMIHash(MRI->getVRegDef(<wbr>Index.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>
> @@ -178,6 +235,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>
> @@ -185,6 +252,27 @@ static inline bool isIdenticalOp(const M<br>
>            !TargetRegisterInfo::<wbr>isPhysicalRegister(MO1.getReg(<wbr>)));<br>
>  }<br>
><br>
> +static bool isIdenticalMI(<wbr>MachineRegisterInfo *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-><wbr>getOperand(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>
> @@ -216,7 +304,140 @@ static inline bool isLEA(const MachineIn<br>
>           Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;<br>
>  }<br>
><br>
> +static bool isDefCopyLike(<wbr>MachineRegisterInfo *MRI, const MachineOperand &Opr) {<br>
> +  if (!Opr.isReg() || TargetRegisterInfo::<wbr>isPhysicalRegister(Opr.getReg(<wbr>)))<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(<wbr>MachineInstr *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 pushScope(MachineBasicBlock *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 popScope();<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::pushScope(<wbr>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::popScope() {<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::<wbr>containsPhyReg(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::<wbr>isPhysicalRegister(Operand.<wbr>getReg()))<br>
> +      return true;<br>
> +    MachineInstr *OperDefMI = MRI->getVRegDef(Operand.<wbr>getReg());<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(<wbr>MachineInstr *MI) {<br>
> +  unsigned lsize;<br>
> +  if (containsPhyReg(MI, 2))<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>
> @@ -228,6 +449,12 @@ public:<br>
>    /// been calculated by LEA. Also, remove redundant LEAs.<br>
>    bool runOnMachineFunction(<wbr>MachineFunction &MF) override;<br>
><br>
> +  void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
> +    AU.setPreservesCFG();<br>
> +    MachineFunctionPass::<wbr>getAnalysisUsage(AU);<br>
> +    AU.addRequired<<wbr>MachineDominatorTree>();<br>
> +  }<br>
> +<br>
>  private:<br>
>    typedef DenseMap<MemOpKey, SmallVector<MachineInstr *, 16>> MemOpMap;<br>
><br>
> @@ -273,8 +500,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(<wbr>MachineFunction &MF);<br>
> +<br>
> +  bool FactorizeLEAsBasicBlock(<wbr>MachineDomTreeNode *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>
> @@ -647,6 +890,152 @@ bool OptimizeLEAPass::<wbr>removeRedundantLEA<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::<wbr>strengthReduceLEAs(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>
> +    for (auto I1 = List.begin(); I1 != List.end(); I1++) {<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(<wbr>First.getOpcode()));<br>
> +      const DebugLoc DL = First.getDebugLoc();<br>
> +<br>
> +      if (!Base.isReg() || !Index.isReg())<br>
> +        continue;<br>
> +      if (TargetRegisterInfo::<wbr>isPhysicalRegister(Res.getReg(<wbr>)) ||<br>
> +          TargetRegisterInfo::<wbr>isPhysicalRegister(Base.<wbr>getReg()) ||<br>
> +          TargetRegisterInfo::<wbr>isPhysicalRegister(Index.<wbr>getReg()))<br>
> +        continue;<br>
> +<br>
> +      MachineBasicBlock &MBB = *(const_cast<MachineBasicBlock *>(&BB));<br>
> +      if (Scale.isImm() && Scale.getImm() == 1) {<br>
> +        // R = B + I<br>
> +        if (Offset.isImm() && !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>
> +        }<br>
> +      }<br>
> +    }<br>
> +  }<br>
> +  return Changed;<br>
> +}<br>
> +<br>
> +bool OptimizeLEAPass::<wbr>processBasicBlock(const MachineBasicBlock &MBB) {<br>
> +  bool cseDone = false;<br>
> +<br>
> +  // Legal scale value (1,2,4 & 8) vector.<br>
> +  int LegalScale[9] = {0, 1, 1, 0, 1, 0, 0, 0, 1};<br>
> +<br>
> +  auto CompareFn = [](const MachineInstr *Arg1,<br>
> +                      const MachineInstr *Arg2) -> bool {<br>
> +    if (Arg1->getOperand(2).getImm() < Arg2->getOperand(2).getImm())<br>
> +      return false;<br>
> +    return true;<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).<wbr>isReg() && "Result is a VirtualReg");<br>
> +        DebugLoc DL = LI1.getDebugLoc();<br>
> +<br>
> +        if (FactorOpt.<wbr>checkIfScheduledForRemoval(&<wbr>LI1))<br>
> +          continue;<br>
> +<br>
> +        int Factor = Scale1 - Scale2;<br>
> +        if (Factor > 0 && LegalScale[Factor]) {<br>
> +          DEBUG(dbgs() << "CSE LEAs: Candidate to replace: "; LI1.dump(););<br>
> +          MachineInstrBuilder NewMI =<br>
> +              BuildMI(*(const_cast<<wbr>MachineBasicBlock *>(&MBB)), &LI1, DL,<br>
> +                      TII->get(LI1.getOpcode()))<br>
> +                  .addDef(LI1.getOperand(0).<wbr>getReg()) // Dst   = Dst of LI1.<br>
> +                  .addUse(LI2.getOperand(0).<wbr>getReg()) // Base  = Dst of LI2.<br>
> +                  .addImm(Factor) // Scale = Diff b/w scales.<br>
> +                  .addUse(LI1.getOperand(3).<wbr>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>
> +          /// 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(&<wbr>LI1);<br>
> +<br>
> +          NumFactoredLEAs++;<br>
> +          DEBUG(dbgs() << "CSE LEAs: Replaced by: "; NewMI->dump(););<br>
> +        }<br>
> +      }<br>
> +    }<br>
> +  }<br>
> +  return cseDone;<br>
> +}<br>
> +<br>
> +bool OptimizeLEAPass::<wbr>FactorizeLEAsBasicBlock(<wbr>MachineDomTreeNode *DN) {<br>
> +  bool Changed = false;<br>
> +  MachineBasicBlock *MBB = DN->getBlock();<br>
> +  FactorOpt.pushScope(MBB);<br>
> +<br>
> +  Changed |= processBasicBlock(*MBB);<br>
> +  for (auto Child : DN->getChildren())<br>
> +    FactorizeLEAsBasicBlock(Child)<wbr>;<br>
> +<br>
> +  FactorOpt.popScope();<br>
> +  return Changed;<br>
> +}<br>
> +<br>
> +bool OptimizeLEAPass::<wbr>FactorizeLEAsAllBasicBlocks(<wbr>MachineFunction &MF) {<br>
> +  bool Changed = FactorizeLEAsBasicBlock(DT-><wbr>getRootNode());<br>
> +  FactorOpt.performCleanup();<br>
> +  return Changed;<br>
> +}<br>
> +<br>
>  bool OptimizeLEAPass::<wbr>runOnMachineFunction(<wbr>MachineFunction &MF) {<br>
>    bool Changed = false;<br>
><br>
> @@ -656,6 +1045,10 @@ bool OptimizeLEAPass::<wbr>runOnMachineFuncti<br>
>    MRI = &MF.getRegInfo();<br>
>    TII = MF.getSubtarget<X86Subtarget>(<wbr>).getInstrInfo();<br>
>    TRI = MF.getSubtarget<X86Subtarget>(<wbr>).getRegisterInfo();<br>
> +  DT = &getAnalysis<<wbr>MachineDominatorTree>();<br>
> +<br>
> +  // Attempt factorizing LEAs.<br>
> +  Changed |= FactorizeLEAsAllBasicBlocks(<wbr>MF);<br>
><br>
>    // Process all basic blocks.<br>
>    for (auto &MBB : MF) {<br>
> @@ -672,6 +1065,9 @@ bool OptimizeLEAPass::<wbr>runOnMachineFuncti<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/<wbr>GlobalISel/callingconv.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/callingconv.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/GlobalISel/<wbr>callingconv.ll?rev=313343&r1=<wbr>313342&r2=313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/callingconv.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/callingconv.ll Thu Sep 14 22:29:51 2017<br>
> @@ -405,7 +405,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/<wbr>GlobalISel/gep.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/gep.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/GlobalISel/gep.ll?<wbr>rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/gep.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/gep.ll Thu Sep 14 22:29:51 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/<wbr>GlobalISel/memop-scalar.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/memop-scalar.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/GlobalISel/memop-<wbr>scalar.ll?rev=313343&r1=<wbr>313342&r2=313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/memop-scalar.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>GlobalISel/memop-scalar.ll Thu Sep 14 22:29:51 2017<br>
> @@ -181,7 +181,7 @@ define i32 @test_gep_folding_largeGepInd<br>
>  ; ALL-LABEL: test_gep_folding_<wbr>largeGepIndex:<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/<wbr>lea-opt-cse1.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt-cse1.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/lea-opt-cse1.ll?<wbr>rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse1.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse1.ll Thu Sep 14 22:29:51 2017<br>
> @@ -9,29 +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 %rcx, %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:  .Lcfi0:<br>
> -; X86-NEXT:    .cfi_def_cfa_offset 8<br>
> -; X86-NEXT:  .Lcfi1:<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/<wbr>lea-opt-cse2.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt-cse2.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/lea-opt-cse2.ll?<wbr>rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse2.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse2.ll Thu Sep 14 22:29:51 2017<br>
> @@ -1,6 +1,6 @@<br>
>  ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.<wbr>py<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,47 +10,41 @@ 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:    pushl %esi<br>
>  ; X86-NEXT:  .Lcfi0:<br>
>  ; X86-NEXT:    .cfi_def_cfa_offset 8<br>
> -; X86-NEXT:    pushl %esi<br>
>  ; X86-NEXT:  .Lcfi1:<br>
> -; X86-NEXT:    .cfi_def_cfa_offset 12<br>
> -; X86-NEXT:  .Lcfi2:<br>
> -; X86-NEXT:    .cfi_offset %esi, -12<br>
> -; X86-NEXT:  .Lcfi3:<br>
> -; X86-NEXT:    .cfi_offset %edi, -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/<wbr>lea-opt-cse3.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt-cse3.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/lea-opt-cse3.ll?<wbr>rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse3.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse3.ll Thu Sep 14 22:29:51 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,%rsi,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,%rsi,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,31 +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,%rsi,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:  .Lcfi0:<br>
> -; X86-NEXT:    .cfi_def_cfa_offset 8<br>
> -; X86-NEXT:  .Lcfi1:<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>
> @@ -131,9 +123,9 @@ define i32 @foo1_mult_basic_blocks_illeg<br>
>  ; X86-LABEL: foo1_mult_basic_blocks_<wbr>illegal_scale:<br>
>  ; X86:       # BB#0: # %entry<br>
>  ; X86-NEXT:    pushl %esi<br>
> -; X86-NEXT:  .Lcfi2:<br>
> +; X86-NEXT:  .Lcfi0:<br>
>  ; X86-NEXT:    .cfi_def_cfa_offset 8<br>
> -; X86-NEXT:  .Lcfi3:<br>
> +; X86-NEXT:  .Lcfi1:<br>
>  ; X86-NEXT:    .cfi_offset %esi, -8<br>
>  ; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx<br>
>  ; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi<br>
><br>
> Modified: llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse4.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt-cse4.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/lea-opt-cse4.ll?<wbr>rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse4.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>lea-opt-cse4.ll Thu Sep 14 22:29:51 2017<br>
> @@ -1,43 +1,31 @@<br>
>  ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.<wbr>py<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:  .Lcfi0:<br>
> -; X86-NEXT:    .cfi_def_cfa_offset 8<br>
> -; X86-NEXT:  .Lcfi1:<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>
> @@ -64,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>
> @@ -84,30 +72,25 @@ 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:  .Lcfi2:<br>
> -; X86-NEXT:    .cfi_def_cfa_offset 8<br>
>  ; X86-NEXT:    pushl %esi<br>
> -; X86-NEXT:  .Lcfi3:<br>
> -; X86-NEXT:    .cfi_def_cfa_offset 12<br>
> -; X86-NEXT:  .Lcfi4:<br>
> -; X86-NEXT:    .cfi_offset %esi, -12<br>
> -; X86-NEXT:  .Lcfi5:<br>
> -; X86-NEXT:    .cfi_offset %edi, -8<br>
> -; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx<br>
> +; X86-NEXT:  .Lcfi0:<br>
> +; X86-NEXT:    .cfi_def_cfa_offset 8<br>
> +; X86-NEXT:  .Lcfi1:<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>
> @@ -116,7 +99,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/<wbr>mul-constant-i16.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-i16.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/mul-constant-i16.<wbr>ll?rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i16.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i16.ll Thu Sep 14 22:29:51 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/<wbr>mul-constant-i32.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-i32.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/mul-constant-i32.<wbr>ll?rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i32.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i32.ll Thu Sep 14 22:29:51 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/<wbr>mul-constant-i64.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-i64.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/mul-constant-i64.<wbr>ll?rev=313343&r1=313342&r2=<wbr>313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i64.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-i64.ll Thu Sep 14 22:29:51 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/<wbr>mul-constant-result.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-result.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/mul-constant-<wbr>result.ll?rev=313343&r1=<wbr>313342&r2=313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-result.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>mul-constant-result.ll Thu Sep 14 22:29:51 2017<br>
> @@ -163,8 +163,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>
> @@ -322,16 +321,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/<wbr>umul-with-overflow.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/X86/umul-with-<wbr>overflow.ll?rev=313343&r1=<wbr>313342&r2=313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/CodeGen/X86/<wbr>umul-with-overflow.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/<wbr>umul-with-overflow.ll Thu Sep 14 22:29:51 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(<wbr>i32 %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(<wbr>i32 %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(<wbr>i32 %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(<wbr>i32 %tmp0, i32 4)<br>
> +        %tmp2 = extractvalue { i32, i1 } %tmp1, 0<br>
> +        ret i32 %tmp2<br>
>  }<br>
><br>
> Modified: llvm/trunk/test/Transforms/<wbr>LoopStrengthReduce/X86/<wbr>ivchain-X86.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/X86/ivchain-X86.ll?rev=313343&r1=313342&r2=313343&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/LoopStrengthReduce/<wbr>X86/ivchain-X86.ll?rev=313343&<wbr>r1=313342&r2=313343&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/test/Transforms/<wbr>LoopStrengthReduce/X86/<wbr>ivchain-X86.ll (original)<br>
> +++ llvm/trunk/test/Transforms/<wbr>LoopStrengthReduce/X86/<wbr>ivchain-X86.ll Thu Sep 14 22:29:51 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">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>
> ------------------------------<wbr>------------------------------<wbr>---------<br>
> Intel Israel (74) Limited<br>
><br>
> This e-mail and any attachments may contain confidential material for<br>
> the sole use of the intended recipient(s). Any review or distribution<br>
> by others is strictly prohibited. If you are not the intended<br>
> recipient, please contact the sender and delete all copies.<br>
> ______________________________<wbr>_________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org">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>
</div></div></blockquote></div><br></div>