<div dir="ltr">If you have android with arm 32bit, you probably can reproduce with running <a href="https://llvm.org/svn/llvm-project/zorg/trunk/zorg/buildbot/builders/sanitizers/buildbot_android.sh">https://llvm.org/svn/llvm-project/zorg/trunk/zorg/buildbot/builders/sanitizers/buildbot_android.sh</a> in empty directory.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Aug 17, 2017 at 6:23 PM, Vitaly Buka <span dir="ltr"><<a href="mailto:vitalybuka@google.com" target="_blank">vitalybuka@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"><div>I just hangs on "Running the AddressSanitizer tests" for arm</div><div><br></div><div>/var/lib/buildbot/sanitizer-<wbr>buildbot6/sanitizer-x86_64-<wbr>linux-android/build/compiler_<wbr>rt_build_android_arm/lib/asan/<wbr>tests/AsanTest: 1 file pus<br></div><div>hed. 3.7 MB/s (10602792 bytes in 2.742s)</div><div>+ echo @@@BUILD_STEP run asan lit tests '[arm/sailfish-userdebug/OPR1.<wbr>170621.001]@@@'</div><div>@@@BUILD_STEP run asan lit tests [arm/sailfish-userdebug/OPR1.<wbr>170621.001]@@@</div><div>+ cd /var/lib/buildbot/sanitizer-<wbr>buildbot6/sanitizer-x86_64-<wbr>linux-android/build/compiler_<wbr>rt_build_android_arm</div><div>+ ninja check-asan</div><div>[1/1] Running the AddressSanitizer tests</div><div><br></div><div><br></div><div>But the same device passes aarch64 tests:</div><div>[1/1] Running the AddressSanitizer tests<br></div><div><div>-- Testing: 407 tests, 12 threads --</div><div>Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90..</div><div>Testing Time: 87.09s</div><div>  Expected Passes    : 202</div><div>  Expected Failures  : 27</div><div>  Unsupported Tests  : 178</div><div>+ echo @@@BUILD_STEP run sanitizer_common tests '[aarch64/sailfish-userdebug/<wbr>OPR1.170621.001]@@@'</div><div>@@@BUILD_STEP run sanitizer_common tests [aarch64/sailfish-userdebug/<wbr>OPR1.170621.001]@@@</div></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Thu, Aug 17, 2017 at 5:42 PM, Geoff Berry <span dir="ltr"><<a href="mailto:gberry@codeaurora.org" target="_blank">gberry@codeaurora.org</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">It seems like this is still happening after fixing a couple of issues with this patch.  I'll revert again shortly.  I'm having a hard time understanding what is failing from looking at the buildbot logs though. Do you have any way of determining what exactly is timing out?<br>
<br>
On 8/16/2017 11:13 PM, Vitaly Buka wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
Looks like after this patch Android tests consistently hang<br>
<a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-android/builds/1825" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/build<wbr>ers/sanitizer-x86_64-linux-and<wbr>roid/builds/1825</a><br>
<br>
On Wed, Aug 16, 2017 at 1:50 PM, Geoff Berry via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a> <mailto:<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llv<wbr>m.org</a>>> wrote:<br>
<br>
    Author: gberry<br>
    Date: Wed Aug 16 13:50:01 2017<br>
    New Revision: 311038<br>
<br>
    URL: <a href="http://llvm.org/viewvc/llvm-project?rev=311038&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=311038&view=rev</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project?rev=311038&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject?rev=311038&view=rev</a>><br>
    Log:<br>
    [MachineCopyPropagation] Extend pass to do COPY source forwarding<br>
<br>
    This change extends MachineCopyPropagation to do COPY source forwarding.<br>
<br>
    This change also extends the MachineCopyPropagation pass to be able to<br>
    be run during register allocation, after physical registers have been<br>
    assigned, but before the virtual registers have been re-written, which<br>
    allows it to remove virtual register COPY LiveIntervals that become dead<br>
    through the forwarding of all of their uses.<br>
<br>
    Reviewers: qcolombet, javed.absar, MatzeB, jonpa<br>
<br>
    Subscribers: jyknight, nemanjai, llvm-commits, nhaehnle, mcrosier,<br>
    mgorny<br>
<br>
    Differential Revision: <a href="https://reviews.llvm.org/D30751" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3075<wbr>1</a><br>
    <<a href="https://reviews.llvm.org/D30751" rel="noreferrer" target="_blank">https://reviews.llvm.org/D307<wbr>51</a>><br>
<br>
    Modified:<br>
         llvm/trunk/include/llvm/CodeG<wbr>en/Passes.h<br>
         llvm/trunk/include/llvm/Initi<wbr>alizePasses.h<br>
         llvm/trunk/lib/CodeGen/CodeGe<wbr>n.cpp<br>
         llvm/trunk/lib/CodeGen/Machin<wbr>eCopyPropagation.cpp<br>
         llvm/trunk/lib/CodeGen/Target<wbr>PassConfig.cpp<br>
         llvm/trunk/test/CodeGen/AArch<wbr>64/aarch64-fold-lslfast.ll<br>
         llvm/trunk/test/CodeGen/AArch<wbr>64/arm64-AdvSIMD-Scalar.ll<br>
         llvm/trunk/test/CodeGen/AArch<wbr>64/arm64-zero-cycle-regmov.ll<br>
         llvm/trunk/test/CodeGen/AArch<wbr>64/f16-instructions.ll<br>
         llvm/trunk/test/CodeGen/AArch<wbr>64/flags-multiuse.ll<br>
         llvm/trunk/test/CodeGen/AArch<wbr>64/merge-store-dependency.ll<br>
         llvm/trunk/test/CodeGen/AArch<wbr>64/neg-imm.ll<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/byval-frame-setup.ll<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/call-argument-types.ll<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/call-preserved-registers.ll<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/callee-special-input-sgprs.l<wbr>l<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/callee-special-input-vgprs.l<wbr>l<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/mubuf-offset-private.ll<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/multilevel-break.ll<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/private-access-no-objects.ll<br>
         llvm/trunk/test/CodeGen/AMDGP<wbr>U/ret.ll<br>
         llvm/trunk/test/CodeGen/ARM/a<wbr>tomic-op.ll<br>
         llvm/trunk/test/CodeGen/ARM/s<wbr>wifterror.ll<br>
         llvm/trunk/test/CodeGen/Mips/<wbr>llvm-ir/sub.ll<br>
         llvm/trunk/test/CodeGen/Power<wbr>PC/fma-mutate.ll<br>
         llvm/trunk/test/CodeGen/Power<wbr>PC/inlineasm-i64-reg.ll<br>
         llvm/trunk/test/CodeGen/Power<wbr>PC/tail-dup-layout.ll<br>
         llvm/trunk/test/CodeGen/SPARC<wbr>/32abi.ll<br>
         llvm/trunk/test/CodeGen/SPARC<wbr>/atomics.ll<br>
         llvm/trunk/test/CodeGen/Thumb<wbr>/thumb-shrink-wrapping.ll<br>
         llvm/trunk/test/CodeGen/X86/2<wbr>006-03-01-InstrSchedBug.ll<br>
         llvm/trunk/test/CodeGen/X86/a<wbr>rg-copy-elide.ll<br>
         llvm/trunk/test/CodeGen/X86/a<wbr>vg.ll<br>
         llvm/trunk/test/CodeGen/X86/a<wbr>vx-load-store.ll<br>
         llvm/trunk/test/CodeGen/X86/a<wbr>vx512-bugfix-25270.ll<br>
         llvm/trunk/test/CodeGen/X86/a<wbr>vx512-calling-conv.ll<br>
         llvm/trunk/test/CodeGen/X86/a<wbr>vx512-mask-op.ll<br>
         llvm/trunk/test/CodeGen/X86/a<wbr>vx512bw-intrinsics-upgrade.ll<br>
         llvm/trunk/test/CodeGen/X86/b<wbr>itcast-int-to-vector-bool-sext<wbr>.ll<br>
         llvm/trunk/test/CodeGen/X86/b<wbr>itcast-int-to-vector-bool-zext<wbr>.ll<br>
         llvm/trunk/test/CodeGen/X86/b<wbr>uildvec-insertvec.ll<br>
         llvm/trunk/test/CodeGen/X86/c<wbr>ombine-fcopysign.ll<br>
         llvm/trunk/test/CodeGen/X86/c<wbr>omplex-fastmath.ll<br>
         llvm/trunk/test/CodeGen/X86/d<wbr>ivide-by-constant.ll<br>
         llvm/trunk/test/CodeGen/X86/f<wbr>maxnum.ll<br>
         llvm/trunk/test/CodeGen/X86/f<wbr>minnum.ll<br>
         llvm/trunk/test/CodeGen/X86/f<wbr>p128-i128.ll<br>
         llvm/trunk/test/CodeGen/X86/h<wbr>addsub-2.ll<br>
         llvm/trunk/test/CodeGen/X86/h<wbr>addsub-undef.ll<br>
         llvm/trunk/test/CodeGen/X86/h<wbr>alf.ll<br>
         llvm/trunk/test/CodeGen/X86/i<wbr>nline-asm-fpstack.ll<br>
         llvm/trunk/test/CodeGen/X86/i<wbr>pra-local-linkage.ll<br>
         llvm/trunk/test/CodeGen/X86/l<wbr>ocalescape.ll<br>
         llvm/trunk/test/CodeGen/X86/m<wbr>ul-i1024.ll<br>
         llvm/trunk/test/CodeGen/X86/m<wbr>ul-i512.ll<br>
         llvm/trunk/test/CodeGen/X86/m<wbr>ul128.ll<br>
         llvm/trunk/test/CodeGen/X86/p<wbr>mul.ll<br>
         llvm/trunk/test/CodeGen/X86/p<wbr>owi.ll<br>
         llvm/trunk/test/CodeGen/X86/p<wbr>r11334.ll<br>
         llvm/trunk/test/CodeGen/X86/p<wbr>r29112.ll<br>
         llvm/trunk/test/CodeGen/X86/p<wbr>subus.ll<br>
         llvm/trunk/test/CodeGen/X86/s<wbr>elect.ll<br>
         llvm/trunk/test/CodeGen/X86/s<wbr>hrink-wrap-chkstk.ll<br>
         llvm/trunk/test/CodeGen/X86/s<wbr>qrt-fastmath.ll<br>
         llvm/trunk/test/CodeGen/X86/s<wbr>se-scalar-fp-arith.ll<br>
         llvm/trunk/test/CodeGen/X86/s<wbr>se1.ll<br>
         llvm/trunk/test/CodeGen/X86/s<wbr>se3-avx-addsub-2.ll<br>
         llvm/trunk/test/CodeGen/X86/s<wbr>tatepoint-live-in.ll<br>
         llvm/trunk/test/CodeGen/X86/s<wbr>tatepoint-stack-usage.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ec_fp_to_int.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ec_int_to_fp.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ec_minmax_sint.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ec_shift4.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-blend.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-idiv-sdiv-128.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-idiv-udiv-128.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-rotate-128.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-sext.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-shift-ashr-128.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-shift-lshr-128.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-shift-shl-128.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-shuffle-combining.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-trunc-math.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>ector-zext.ll<br>
         llvm/trunk/test/CodeGen/X86/v<wbr>select-minmax.ll<br>
         llvm/trunk/test/CodeGen/X86/w<wbr>iden_conv-3.ll<br>
         llvm/trunk/test/CodeGen/X86/w<wbr>iden_conv-4.ll<br>
         llvm/trunk/test/CodeGen/X86/x<wbr>86-shrink-wrap-unwind.ll<br>
         llvm/trunk/test/CodeGen/X86/x<wbr>86-shrink-wrapping.ll<br>
<br>
    Modified: llvm/trunk/include/llvm/CodeGe<wbr>n/Passes.h<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>CodeGen/Passes.h?rev=311038&r1<wbr>=311037&r2=311038&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/include/llvm<wbr>/CodeGen/Passes.h?rev=311038&r<wbr>1=311037&r2=311038&view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/include/llvm/CodeGe<wbr>n/Passes.h (original)<br>
    +++ llvm/trunk/include/llvm/CodeGe<wbr>n/Passes.h Wed Aug 16 13:50:01 2017<br>
    @@ -278,6 +278,11 @@ namespace llvm {<br>
        /// MachineSinking - This pass performs sinking on machine<br>
    instructions.<br>
        extern char &MachineSinkingID;<br>
<br>
    +  /// MachineCopyPropagationPreRegRe<wbr>write - This pass performs copy<br>
    propagation<br>
    +  /// on machine instructions after register allocation but before<br>
    virtual<br>
    +  /// register re-writing..<br>
    +  extern char &MachineCopyPropagationPreRegR<wbr>ewriteID;<br>
    +<br>
        /// MachineCopyPropagation - This pass performs copy propagation on<br>
        /// machine instructions.<br>
        extern char &MachineCopyPropagationID;<br>
<br>
    Modified: llvm/trunk/include/llvm/Initia<wbr>lizePasses.h<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>InitializePasses.h?rev=311038&<wbr>r1=311037&r2=311038&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/include/llvm<wbr>/InitializePasses.h?rev=311038<wbr>&r1=311037&r2=311038&view=diff</a><wbr>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/include/llvm/Initia<wbr>lizePasses.h (original)<br>
    +++ llvm/trunk/include/llvm/Initia<wbr>lizePasses.h Wed Aug 16 13:50:01 2017<br>
    @@ -233,6 +233,7 @@ void initializeMachineBranchProbabi<wbr>lityI<br>
      void initializeMachineCSEPass(PassR<wbr>egistry&);<br>
      void initializeMachineCombinerPass(<wbr>PassRegistry&);<br>
      void initializeMachineCopyPropagati<wbr>onPass(PassRegistry&);<br>
    +void initializeMachineCopyPropagati<wbr>onPreRegRewritePass(PassRegist<wbr>ry&);<br>
      void initializeMachineDominanceFron<wbr>tierPass(PassRegistry&);<br>
      void initializeMachineDominatorTree<wbr>Pass(PassRegistry&);<br>
      void initializeMachineFunctionPrint<wbr>erPassPass(PassRegistry&);<br>
<br>
    Modified: llvm/trunk/lib/CodeGen/CodeGen<wbr>.cpp<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGen.cpp?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/CodeGen/C<wbr>odeGen.cpp?rev=311038&r1=31103<wbr>7&r2=311038&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGen.cpp?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/lib/CodeGen/<wbr>CodeGen.cpp?rev=311038&r1=3110<wbr>37&r2=311038&view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/lib/CodeGen/CodeGen<wbr>.cpp (original)<br>
    +++ llvm/trunk/lib/CodeGen/CodeGen<wbr>.cpp Wed Aug 16 13:50:01 2017<br>
    @@ -54,6 +54,7 @@ void llvm::initializeCodeGen(PassRe<wbr>gistr<br>
        initializeMachineCSEPass(Regis<wbr>try);<br>
        initializeMachineCombinerPass(<wbr>Registry);<br>
        initializeMachineCopyPropagati<wbr>onPass(Registry);<br>
    +  initializeMachineCopyPropagati<wbr>onPreRegRewritePass(Registry);<br>
        initializeMachineDominatorTree<wbr>Pass(Registry);<br>
        initializeMachineFunctionPrint<wbr>erPassPass(Registry);<br>
        initializeMachineLICMPass(Regi<wbr>stry);<br>
<br>
    Modified: llvm/trunk/lib/CodeGen/Machine<wbr>CopyPropagation.cpp<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/CodeGen/M<wbr>achineCopyPropagation.cpp?rev=<wbr>311038&r1=311037&r2=311038&vie<wbr>w=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/lib/CodeGen/<wbr>MachineCopyPropagation.cpp?rev<wbr>=311038&r1=311037&r2=311038&vi<wbr>ew=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/lib/CodeGen/Machine<wbr>CopyPropagation.cpp (original)<br>
    +++ llvm/trunk/lib/CodeGen/Machine<wbr>CopyPropagation.cpp Wed Aug 16<br>
    13:50:01 2017<br>
    @@ -7,18 +7,62 @@<br>
      //<br>
      //===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
      //<br>
    -// This is an extremely simple MachineInstr-level copy propagation<br>
    pass.<br>
    +// This is a simple MachineInstr-level copy forwarding pass.  It<br>
    may be run at<br>
    +// two places in the codegen pipeline:<br>
    +//   - After register allocation but before virtual registers have<br>
    been remapped<br>
    +//     to physical registers.<br>
    +//   - After physical register remapping.<br>
    +//<br>
    +// The optimizations done vary slightly based on whether virtual<br>
    registers are<br>
    +// still present.  In both cases, this pass forwards the source of<br>
    COPYs to the<br>
    +// users of their destinations when doing so is legal.  For example:<br>
    +//<br>
    +//   %vreg1 = COPY %vreg0<br>
    +//   ...<br>
    +//   ... = OP %vreg1<br>
    +//<br>
    +// If<br>
    +//   - the physical register assigned to %vreg0 has not been<br>
    clobbered by the<br>
    +//     time of the use of %vreg1<br>
    +//   - the register class constraints are satisfied<br>
    +//   - the COPY def is the only value that reaches OP<br>
    +// then this pass replaces the above with:<br>
    +//<br>
    +//   %vreg1 = COPY %vreg0<br>
    +//   ...<br>
    +//   ... = OP %vreg0<br>
    +//<br>
    +// and updates the relevant state required by VirtRegMap (e.g.<br>
    LiveIntervals).<br>
    +// COPYs whose LiveIntervals become dead as a result of this<br>
    forwarding (i.e. if<br>
    +// all uses of %vreg1 are changed to %vreg0) are removed.<br>
    +//<br>
    +// When being run with only physical registers, this pass will also<br>
    remove some<br>
    +// redundant COPYs.  For example:<br>
    +//<br>
    +//    %R1 = COPY %R0<br>
    +//    ... // No clobber of %R1<br>
    +//    %R0 = COPY %R1 <<< Removed<br>
    +//<br>
    +// or<br>
    +//<br>
    +//    %R1 = COPY %R0<br>
    +//    ... // No clobber of %R0<br>
    +//    %R1 = COPY %R0 <<< Removed<br>
      //<br>
      //===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
<br>
    +#include "LiveDebugVariables.h"<br>
      #include "llvm/ADT/DenseMap.h"<br>
      #include "llvm/ADT/SetVector.h"<br>
      #include "llvm/ADT/SmallVector.h"<br>
      #include "llvm/ADT/Statistic.h"<br>
    +#include "llvm/CodeGen/LiveRangeEdit.h"<br>
    +#include "llvm/CodeGen/LiveStackAnalysi<wbr>s.h"<br>
      #include "llvm/CodeGen/MachineFunction.<wbr>h"<br>
      #include "llvm/CodeGen/MachineFunctionP<wbr>ass.h"<br>
      #include "llvm/CodeGen/MachineRegisterI<wbr>nfo.h"<br>
      #include "llvm/CodeGen/Passes.h"<br>
    +#include "llvm/CodeGen/VirtRegMap.h"<br>
      #include "llvm/Pass.h"<br>
      #include "llvm/Support/Debug.h"<br>
      #include "llvm/Support/raw_ostream.h"<br>
    @@ -30,24 +74,48 @@ using namespace llvm;<br>
      #define DEBUG_TYPE "machine-cp"<br>
<br>
      STATISTIC(NumDeletes, "Number of dead copies deleted");<br>
    +STATISTIC(NumCopyForwards, "Number of copy uses forwarded");<br>
<br>
      namespace {<br>
        typedef SmallVector<unsigned, 4> RegList;<br>
        typedef DenseMap<unsigned, RegList> SourceMap;<br>
        typedef DenseMap<unsigned, MachineInstr*> Reg2MIMap;<br>
<br>
    -  class MachineCopyPropagation : public MachineFunctionPass {<br>
    +  class MachineCopyPropagation : public MachineFunctionPass,<br>
    +                                 private LiveRangeEdit::Delegate {<br>
          const TargetRegisterInfo *TRI;<br>
          const TargetInstrInfo *TII;<br>
    -    const MachineRegisterInfo *MRI;<br>
    +    MachineRegisterInfo *MRI;<br>
    +    MachineFunction *MF;<br>
    +    SlotIndexes *Indexes;<br>
    +    LiveIntervals *LIS;<br>
    +    const VirtRegMap *VRM;<br>
    +    // True if this pass being run before virtual registers are<br>
    remapped to<br>
    +    // physical ones.<br>
    +    bool PreRegRewrite;<br>
    +    bool NoSubRegLiveness;<br>
    +<br>
    +  protected:<br>
    +    MachineCopyPropagation(char &ID, bool PreRegRewrite)<br>
    +        : MachineFunctionPass(ID), PreRegRewrite(PreRegRewrite) {}<br>
<br>
        public:<br>
          static char ID; // Pass identification, replacement for typeid<br>
    -    MachineCopyPropagation() : MachineFunctionPass(ID) {<br>
    +    MachineCopyPropagation() : MachineCopyPropagation(ID, false) {<br>
                initializeMachineCopyPropagati<wbr>onPass(*PassRegistry::getPassR<wbr>egistry());<br>
          }<br>
<br>
          void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
    +      if (PreRegRewrite) {<br>
    +        AU.addRequired<SlotIndexes>();<br>
    +        AU.addPreserved<SlotIndexes>()<wbr>;<br>
    +        AU.addRequired<LiveIntervals>(<wbr>);<br>
    +        AU.addPreserved<LiveIntervals><wbr>();<br>
    +        AU.addRequired<VirtRegMap>();<br>
    +        AU.addPreserved<VirtRegMap>();<br>
    +        AU.addPreserved<LiveDebugVaria<wbr>bles>();<br>
    +        AU.addPreserved<LiveStacks>();<br>
    +      }<br>
            AU.setPreservesCFG();<br>
            MachineFunctionPass::getAnalys<wbr>isUsage(AU);<br>
          }<br>
    @@ -55,6 +123,10 @@ namespace {<br>
          bool runOnMachineFunction(MachineFu<wbr>nction &MF) override;<br>
<br>
          MachineFunctionProperties getRequiredProperties() const override {<br>
    +      if (PreRegRewrite)<br>
    +        return MachineFunctionProperties()<br>
    +            .set(MachineFunctionProperties<wbr>::Property::NoPHIs)<br>
    +            .set(MachineFunctionProperties<wbr>::Property::TracksLiveness);<br>
            return MachineFunctionProperties().se<wbr>t(<br>
                MachineFunctionProperties::Pro<wbr>perty::NoVRegs);<br>
          }<br>
    @@ -64,6 +136,28 @@ namespace {<br>
          void ReadRegister(unsigned Reg);<br>
          void CopyPropagateBlock(MachineBasi<wbr>cBlock &MBB);<br>
          bool eraseIfRedundant(MachineInstr &Copy, unsigned Src,<br>
    unsigned Def);<br>
    +    unsigned getPhysReg(unsigned Reg, unsigned SubReg);<br>
    +    unsigned getPhysReg(const MachineOperand &Opnd) {<br>
    +      return getPhysReg(Opnd.getReg(), Opnd.getSubReg());<br>
    +    }<br>
    +    unsigned getFullPhysReg(const MachineOperand &Opnd) {<br>
    +      return getPhysReg(Opnd.getReg(), 0);<br>
    +    }<br>
    +    void forwardUses(MachineInstr &MI);<br>
    +    bool isForwardableRegClassCopy(cons<wbr>t MachineInstr &Copy,<br>
    +                                   const MachineInstr &UseI);<br>
    +    std::tuple<unsigned, unsigned, bool><br>
    +    checkUseSubReg(const MachineOperand &CopySrc, const<br>
    MachineOperand &MOUse);<br>
    +    bool hasImplicitOverlap(const MachineInstr &MI, const<br>
    MachineOperand &Use);<br>
    +    void narrowRegClass(const MachineInstr &MI, const<br>
    MachineOperand &MOUse,<br>
    +                        unsigned NewUseReg, unsigned NewUseSubReg);<br>
    +    void updateForwardedCopyLiveInterva<wbr>l(const MachineInstr &Copy,<br>
    +                                         const MachineInstr &UseMI,<br>
    +                                         unsigned OrigUseReg,<br>
    +                                         unsigned NewUseReg,<br>
    +                                         unsigned NewUseSubReg);<br>
    +    /// LiveRangeEdit callback for eliminateDeadDefs().<br>
    +    void LRE_WillEraseInstruction(Machi<wbr>neInstr *MI) override;<br>
<br>
          /// Candidates for deletion.<br>
          SmallSetVector<MachineInstr*, 8> MaybeDeadCopies;<br>
    @@ -75,6 +169,15 @@ namespace {<br>
          SourceMap SrcMap;<br>
          bool Changed;<br>
        };<br>
    +<br>
    +  class MachineCopyPropagationPreRegRe<wbr>write : public<br>
    MachineCopyPropagation {<br>
    +  public:<br>
    +    static char ID; // Pass identification, replacement for typeid<br>
    +    MachineCopyPropagationPreRegRe<wbr>write()<br>
    +        : MachineCopyPropagation(ID, true) {<br>
    +         initializeMachineCopyPropagat<wbr>ionPreRegRewritePass(*<wbr>PassRegistry::getPassRegistry(<wbr>));<br>
    +    }<br>
    +  };<br>
      }<br>
      char MachineCopyPropagation::ID = 0;<br>
      char &llvm::MachineCopyPropagationI<wbr>D = MachineCopyPropagation::ID;<br>
    @@ -82,6 +185,29 @@ char &llvm::MachineCopyPropagationI<wbr>D = M<br>
      INITIALIZE_PASS(MachineCopyPro<wbr>pagation, DEBUG_TYPE,<br>
                      "Machine Copy Propagation Pass", false, false)<br>
<br>
    +/// We have two separate passes that are very similar, the only<br>
    difference being<br>
    +/// where they are meant to be run in the pipeline.  This is done<br>
    for several<br>
    +/// reasons:<br>
    +/// - the two passes have different dependencies<br>
    +/// - some targets want to disable the later run of this pass, but<br>
    not the<br>
    +///   earlier one (e.g. NVPTX and WebAssembly)<br>
    +/// - it allows for easier debugging via llc<br>
    +<br>
    +char MachineCopyPropagationPreRegRe<wbr>write::ID = 0;<br>
    +char &llvm::MachineCopyPropagationP<wbr>reRegRewriteID =<br>
    MachineCopyPropagationPreRegRe<wbr>write::ID;<br>
    +<br>
    +INITIALIZE_PASS_BEGIN(Machine<wbr>CopyPropagationPreRegRewrite,<br>
    +                      "machine-cp-prerewrite",<br>
    +                      "Machine Copy Propagation Pre-Register<br>
    Rewrite Pass",<br>
    +                      false, false)<br>
    +INITIALIZE_PASS_DEPENDENCY(Sl<wbr>otIndexes)<br>
    +INITIALIZE_PASS_DEPENDENCY(Li<wbr>veIntervals)<br>
    +INITIALIZE_PASS_DEPENDENCY(Vi<wbr>rtRegMap)<br>
    +INITIALIZE_PASS_END(MachineCo<wbr>pyPropagationPreRegRewrite,<br>
    +                    "machine-cp-prerewrite",<br>
    +                    "Machine Copy Propagation Pre-Register Rewrite<br>
    Pass", false,<br>
    +                    false)<br>
    +<br>
      /// Remove any entry in \p Map where the register is a subregister<br>
    or equal to<br>
      /// a register contained in \p Regs.<br>
      static void removeRegsFromMap(Reg2MIMap &Map, const RegList &Regs,<br>
    @@ -122,6 +248,10 @@ void MachineCopyPropagation::Clobbe<wbr>rRegi<br>
      }<br>
<br>
      void MachineCopyPropagation::ReadRe<wbr>gister(unsigned Reg) {<br>
    +  // We don't track MaybeDeadCopies when running pre-VirtRegRewriter.<br>
    +  if (PreRegRewrite)<br>
    +    return;<br>
    +<br>
        // If 'Reg' is defined by a copy, the copy is no longer a candidate<br>
        // for elimination.<br>
        for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {<br>
    @@ -153,6 +283,46 @@ static bool isNopCopy(const MachineInstr<br>
        return SubIdx == TRI->getSubRegIndex(PreviousDe<wbr>f, Def);<br>
      }<br>
<br>
    +/// Return the physical register assigned to \p Reg if it is a<br>
    virtual register,<br>
    +/// otherwise just return the physical reg from the operand itself.<br>
    +///<br>
    +/// If \p SubReg is 0 then return the full physical register<br>
    assigned to the<br>
    +/// virtual register ignoring subregs.  If we aren't tracking<br>
    sub-reg liveness<br>
    +/// then we need to use this to be more conservative with clobbers<br>
    by killing<br>
    +/// all super reg and their sub reg COPYs as well.  This is to<br>
    prevent COPY<br>
    +/// forwarding in cases like the following:<br>
    +///<br>
    +///    %vreg2 = COPY %vreg1:sub1<br>
    +///    %vreg3 = COPY %vreg1:sub0<br>
    +///    ...    = OP1 %vreg2<br>
    +///    ...    = OP2 %vreg3<br>
    +///<br>
    +/// After forward %vreg2 (assuming this is the last use of %vreg1) and<br>
    +/// VirtRegRewriter adding kill markers we have:<br>
    +///<br>
    +///    %vreg3 = COPY %vreg1:sub0<br>
    +///    ...    = OP1 %vreg1:sub1<kill><br>
    +///    ...    = OP2 %vreg3<br>
    +///<br>
    +/// If %vreg3 is assigned to a sub-reg of %vreg1, then after<br>
    rewriting we have:<br>
    +///<br>
    +///    ...     = OP1 R0:sub1, R0<imp-use,kill><br>
    +///    ...     = OP2 R0:sub0<br>
    +///<br>
    +/// and the use of R0 by OP2 will not have a valid definition.<br>
    +unsigned MachineCopyPropagation::getPhy<wbr>sReg(unsigned Reg, unsigned<br>
    SubReg) {<br>
    +<br>
    +  // Physical registers cannot have subregs.<br>
    +  if (!TargetRegisterInfo::isVirtua<wbr>lRegister(Reg))<br>
    +    return Reg;<br>
    +<br>
    +  assert(PreRegRewrite && "Unexpected virtual register encountered");<br>
    +  Reg = VRM->getPhys(Reg);<br>
    +  if (SubReg && !NoSubRegLiveness)<br>
    +    Reg = TRI->getSubReg(Reg, SubReg);<br>
    +  return Reg;<br>
    +}<br>
    +<br>
      /// Remove instruction \p Copy if there exists a previous copy<br>
    that copies the<br>
      /// register \p Src to the register \p Def; This may happen<br>
    indirectly by<br>
      /// copying the super registers.<br>
    @@ -190,6 +360,325 @@ bool MachineCopyPropagation::eraseI<wbr>fRedu<br>
        return true;<br>
      }<br>
<br>
    +<br>
    +/// Decide whether we should forward the destination of \param Copy<br>
    to its use<br>
    +/// in \param UseI based on the register class of the Copy<br>
    operands.  Same-class<br>
    +/// COPYs are always accepted by this function, but cross-class<br>
    COPYs are only<br>
    +/// accepted if they are forwarded to another COPY with the operand<br>
    register<br>
    +/// classes reversed.  For example:<br>
    +///<br>
    +///   RegClassA = COPY RegClassB  // Copy parameter<br>
    +///   ...<br>
    +///   RegClassB = COPY RegClassA  // UseI parameter<br>
    +///<br>
    +/// which after forwarding becomes<br>
    +///<br>
    +///   RegClassA = COPY RegClassB<br>
    +///   ...<br>
    +///   RegClassB = COPY RegClassB<br>
    +///<br>
    +/// so we have reduced the number of cross-class COPYs and potentially<br>
    +/// introduced a no COPY that can be removed.<br>
    +bool MachineCopyPropagation::isForw<wbr>ardableRegClassCopy(<br>
    +    const MachineInstr &Copy, const MachineInstr &UseI) {<br>
    +  auto isCross = [&](const MachineOperand &Dst, const<br>
    MachineOperand &Src) {<br>
    +    unsigned DstReg = Dst.getReg();<br>
    +    unsigned SrcPhysReg = getPhysReg(Src);<br>
    +    const TargetRegisterClass *DstRC;<br>
    +    if (TargetRegisterInfo::isVirtual<wbr>Register(DstReg)) {<br>
    +      DstRC = MRI->getRegClass(DstReg);<br>
    +      unsigned DstSubReg = Dst.getSubReg();<br>
    +      if (DstSubReg)<br>
    +        SrcPhysReg = TRI->getMatchingSuperReg(SrcPh<wbr>ysReg,<br>
    DstSubReg, DstRC);<br>
    +    } else<br>
    +      DstRC = TRI->getMinimalPhysRegClass(Ds<wbr>tReg);<br>
    +<br>
    +    return !DstRC->contains(SrcPhysReg);<br>
    +  };<br>
    +<br>
    +  const MachineOperand &CopyDst = Copy.getOperand(0);<br>
    +  const MachineOperand &CopySrc = Copy.getOperand(1);<br>
    +<br>
    +  if (!isCross(CopyDst, CopySrc))<br>
    +    return true;<br>
    +<br>
    +  if (!UseI.isCopy())<br>
    +    return false;<br>
    +<br>
    +  assert(getFullPhysReg(UseI.get<wbr>Operand(1)) ==<br>
    getFullPhysReg(CopyDst));<br>
    +  return !isCross(UseI.getOperand(0), CopySrc);<br>
    +}<br>
    +<br>
    +/// Check that the subregs on the copy source operand (\p CopySrc)<br>
    and the use<br>
    +/// operand to be forwarded to (\p MOUse) are compatible with doing the<br>
    +/// forwarding.  Also computes the new register and subregister to<br>
    be used in<br>
    +/// the forwarded-to instruction.<br>
    +std::tuple<unsigned, unsigned, bool><br>
    MachineCopyPropagation::checkU<wbr>seSubReg(<br>
    +    const MachineOperand &CopySrc, const MachineOperand &MOUse) {<br>
    +  unsigned NewUseReg = CopySrc.getReg();<br>
    +  unsigned NewUseSubReg;<br>
    +<br>
    +  if (TargetRegisterInfo::isPhysica<wbr>lRegister(NewUseReg)) {<br>
    +    // If MOUse is a virtual reg, we need to apply it to the new<br>
    physical reg<br>
    +    // we're going to replace it with.<br>
    +    if (MOUse.getSubReg())<br>
    +      NewUseReg = TRI->getSubReg(NewUseReg, MOUse.getSubReg());<br>
    +    // If the original use subreg isn't valid on the new src reg,<br>
    we can't<br>
    +    // forward it here.<br>
    +    if (!NewUseReg)<br>
    +      return std::make_tuple(0, 0, false);<br>
    +    NewUseSubReg = 0;<br>
    +  } else {<br>
    +    // %v1 = COPY %v2:sub1<br>
    +    //    USE %v1:sub2<br>
    +    // The new use is %v2:sub1:sub2<br>
    +    NewUseSubReg =<br>
    +        TRI->composeSubRegIndices(Copy<wbr>Src.getSubReg(),<br>
    MOUse.getSubReg());<br>
    +    // Check that NewUseSubReg is valid on NewUseReg<br>
    +    if (NewUseSubReg &&<br>
    +        !TRI->getSubClassWithSubReg(MR<wbr>I->getRegClass(NewUseReg),<br>
    NewUseSubReg))<br>
    +      return std::make_tuple(0, 0, false);<br>
    +  }<br>
    +<br>
    +  return std::make_tuple(NewUseReg, NewUseSubReg, true);<br>
    +}<br>
    +<br>
    +/// Check that \p MI does not have implicit uses that overlap with<br>
    it's \p Use<br>
    +/// operand (the register being replaced), since these can sometimes be<br>
    +/// implicitly tied to other operands.  For example, on AMDGPU:<br>
    +///<br>
    +/// V_MOVRELS_B32_e32 %VGPR2, %M0<imp-use>, %EXEC<imp-use>,<br>
    %VGPR2_VGPR3_VGPR4_VGPR5<imp-u<wbr>se><br>
    +///<br>
    +/// the %VGPR2 is implicitly tied to the larger reg operand, but we<br>
    have no<br>
    +/// way of knowing we need to update the latter when updating the<br>
    former.<br>
    +bool MachineCopyPropagation::hasImp<wbr>licitOverlap(const MachineInstr &MI,<br>
    +                                                const<br>
    MachineOperand &Use) {<br>
    +  if (!TargetRegisterInfo::isPhysic<wbr>alRegister(Use.getReg()))<br>
    +    return false;<br>
    +<br>
    +  for (const MachineOperand &MIUse : MI.uses())<br>
    +    if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&<br>
    +        TRI->regsOverlap(Use.getReg(), MIUse.getReg()))<br>
    +      return true;<br>
    +<br>
    +  return false;<br>
    +}<br>
    +<br>
    +/// Narrow the register class of the forwarded vreg so it matches any<br>
    +/// instruction constraints.  \p MI is the instruction being<br>
    forwarded to. \p<br>
    +/// MOUse is the operand being replaced in \p MI (which hasn't yet<br>
    been updated<br>
    +/// at the time this function is called).  \p NewUseReg and \p<br>
    NewUseSubReg are<br>
    +/// what the \p MOUse will be changed to after forwarding.<br>
    +///<br>
    +/// If we are forwarding<br>
    +///    A:RCA = COPY B:RCB<br>
    +/// into<br>
    +///    ... = OP A:RCA<br>
    +///<br>
    +/// then we need to narrow the register class of B so that it is a<br>
    subclass<br>
    +/// of RCA so that it meets the instruction register class constraints.<br>
    +void MachineCopyPropagation::narrow<wbr>RegClass(const MachineInstr &MI,<br>
    +                                            const MachineOperand<br>
    &MOUse,<br>
    +                                            unsigned NewUseReg,<br>
    +                                            unsigned NewUseSubReg) {<br>
    +  if (!TargetRegisterInfo::isVirtua<wbr>lRegister(NewUseReg))<br>
    +    return;<br>
    +<br>
    +  // Make sure the virtual reg class allows the subreg.<br>
    +  if (NewUseSubReg) {<br>
    +    const TargetRegisterClass *CurUseRC = MRI->getRegClass(NewUseReg);<br>
    +    const TargetRegisterClass *NewUseRC =<br>
    +        TRI->getSubClassWithSubReg(Cur<wbr>UseRC, NewUseSubReg);<br>
    +    if (CurUseRC != NewUseRC) {<br>
    +      DEBUG(dbgs() << "MCP: Setting regclass of " <<<br>
    PrintReg(NewUseReg, TRI)<br>
    +                   << " to " << TRI->getRegClassName(NewUseRC) <<<br>
    "\n");<br>
    +      MRI->setRegClass(NewUseReg, NewUseRC);<br>
    +    }<br>
    +  }<br>
    +<br>
    +  unsigned MOUseOpNo = &MOUse - &MI.getOperand(0);<br>
    +  const TargetRegisterClass *InstRC =<br>
    +      TII->getRegClass(MI.getDesc(), MOUseOpNo, TRI, *MF);<br>
    +  if (InstRC) {<br>
    +    const TargetRegisterClass *CurUseRC = MRI->getRegClass(NewUseReg);<br>
    +    if (NewUseSubReg)<br>
    +      InstRC = TRI->getMatchingSuperRegClass(<wbr>CurUseRC, InstRC,<br>
    NewUseSubReg);<br>
    +    if (!InstRC->hasSubClassEq(CurUse<wbr>RC)) {<br>
    +      const TargetRegisterClass *NewUseRC =<br>
    +          TRI->getCommonSubClass(InstRC, CurUseRC);<br>
    +      DEBUG(dbgs() << "MCP: Setting regclass of " <<<br>
    PrintReg(NewUseReg, TRI)<br>
    +                   << " to " << TRI->getRegClassName(NewUseRC) <<<br>
    "\n");<br>
    +      MRI->setRegClass(NewUseReg, NewUseRC);<br>
    +    }<br>
    +  }<br>
    +}<br>
    +<br>
    +/// Update the LiveInterval information to reflect the destination<br>
    of \p Copy<br>
    +/// being forwarded to a use in \p UseMI.  \p OrigUseReg is the<br>
    register being<br>
    +/// forwarded through. It should be the destination register of \p<br>
    Copy and has<br>
    +/// already been replaced in \p UseMI at the point this function is<br>
    called.  \p<br>
    +/// NewUseReg and \p NewUseSubReg are the register and subregister<br>
    being<br>
    +/// forwarded.  They should be the source register of the \p Copy<br>
    and should be<br>
    +/// the value of the \p UseMI operand being forwarded at the point<br>
    this function<br>
    +/// is called.<br>
    +void MachineCopyPropagation::update<wbr>ForwardedCopyLiveInterval(<br>
    +    const MachineInstr &Copy, const MachineInstr &UseMI, unsigned<br>
    OrigUseReg,<br>
    +    unsigned NewUseReg, unsigned NewUseSubReg) {<br>
    +<br>
    +  assert(TRI->isSubRegisterEq(ge<wbr>tPhysReg(OrigUseReg, 0),<br>
    +                              getFullPhysReg(Copy.getOperand<wbr>(0))) &&<br>
    +         "OrigUseReg mismatch");<br>
    +  assert(TRI->isSubRegisterEq(ge<wbr>tFullPhysReg(Copy.getOperand(1<wbr>)),<br>
    +                              getPhysReg(NewUseReg, 0)) &&<br>
    +         "NewUseReg mismatch");<br>
    +<br>
    +  // Extend live range starting from COPY early-clobber slot, since<br>
    that<br>
    +  // is where the original src live range ends.<br>
    +  SlotIndex CopyUseIdx =<br>
    +      Indexes->getInstructionIndex(C<wbr>opy).getRegSlot(true<br>
    /*=EarlyClobber*/);<br>
    +  SlotIndex UseIdx = Indexes->getInstructionIndex(U<wbr>seMI).getRegSlot();<br>
    +  if (TargetRegisterInfo::isVirtual<wbr>Register(NewUseReg)) {<br>
    +    LiveInterval &LI = LIS->getInterval(NewUseReg);<br>
    +    LI.extendInBlock(CopyUseIdx, UseIdx);<br>
    +    LaneBitmask UseMask = TRI->getSubRegIndexLaneMask(Ne<wbr>wUseSubReg);<br>
    +    for (auto &S : LI.subranges())<br>
    +      if ((S.LaneMask & UseMask).any() && S.find(CopyUseIdx))<br>
    +        S.extendInBlock(CopyUseIdx, UseIdx);<br>
    +  } else {<br>
    +    assert(NewUseSubReg == 0 && "Unexpected subreg on physical<br>
    register!");<br>
    +    for (MCRegUnitIterator UI(NewUseReg, TRI); UI.isValid(); ++UI) {<br>
    +      LiveRange &LR = LIS->getRegUnit(*UI);<br>
    +      LR.extendInBlock(CopyUseIdx, UseIdx);<br>
    +    }<br>
    +  }<br>
    +<br>
    +  if (!TargetRegisterInfo::isVirtua<wbr>lRegister(OrigUseReg))<br>
    +    return;<br>
    +<br>
    +  LiveInterval &LI = LIS->getInterval(OrigUseReg);<br>
    +<br>
    +  // Can happen for undef uses.<br>
    +  if (LI.empty())<br>
    +    return;<br>
    +<br>
    +  SlotIndex UseIndex = Indexes->getInstructionIndex(U<wbr>seMI);<br>
    +  const LiveRange::Segment *UseSeg = LI.getSegmentContaining(UseInd<wbr>ex);<br>
    +<br>
    +  // Only shrink if forwarded use is the end of a segment.<br>
    +  if (UseSeg->end != UseIndex.getRegSlot())<br>
    +    return;<br>
    +<br>
    +  SmallVector<MachineInstr *, 4> DeadInsts;<br>
    +  LIS->shrinkToUses(&LI, &DeadInsts);<br>
    +  if (!DeadInsts.empty()) {<br>
    +    SmallVector<unsigned, 8> NewRegs;<br>
    +    LiveRangeEdit(nullptr, NewRegs, *MF, *LIS, nullptr, this)<br>
    +        .eliminateDeadDefs(DeadInsts);<br>
    +  }<br>
    +}<br>
    +<br>
    +void MachineCopyPropagation::LRE_Wi<wbr>llEraseInstruction(MachineInst<wbr>r<br>
    *MI) {<br>
    +  // Remove this COPY from further consideration for forwarding.<br>
    +  ClobberRegister(getFullPhysReg<wbr>(MI->getOperand(0)));<br>
    +  Changed = true;<br>
    +}<br>
    +<br>
    +/// Look for available copies whose destination register is used by<br>
    \p MI and<br>
    +/// replace the use in \p MI with the copy's source register.<br>
    +void MachineCopyPropagation::forwar<wbr>dUses(MachineInstr &MI) {<br>
    +  if (AvailCopyMap.empty())<br>
    +    return;<br>
    +<br>
    +  // Look for non-tied explicit vreg uses that have an active COPY<br>
    +  // instruction that defines the physical register allocated to them.<br>
    +  // Replace the vreg with the source of the active COPY.<br>
    +  for (MachineOperand &MOUse : MI.explicit_uses()) {<br>
    +    if (!MOUse.isReg() || MOUse.isTied())<br>
    +      continue;<br>
    +<br>
    +    unsigned UseReg = MOUse.getReg();<br>
    +    if (!UseReg)<br>
    +      continue;<br>
    +<br>
    +    if (TargetRegisterInfo::isVirtual<wbr>Register(UseReg))<br>
    +      UseReg = VRM->getPhys(UseReg);<br>
    +    else if (MI.isCall() || MI.isReturn() || MI.isInlineAsm() ||<br>
    +             MI.hasUnmodeledSideEffects() || MI.isDebugValue() ||<br>
    MI.isKill())<br>
    +      // Some instructions seem to have ABI uses e.g. not marked as<br>
    +      // implicit, which can lead to forwarding them when we<br>
    shouldn't, so<br>
    +      // restrict the types of instructions we forward physical<br>
    regs into.<br>
    +      continue;<br>
    +<br>
    +    // Don't forward COPYs via non-allocatable regs since they can have<br>
    +    // non-standard semantics.<br>
    +    if (!MRI->isAllocatable(UseReg))<br>
    +      continue;<br>
    +<br>
    +    auto CI = AvailCopyMap.find(UseReg);<br>
    +    if (CI == AvailCopyMap.end())<br>
    +      continue;<br>
    +<br>
    +    MachineInstr &Copy = *CI->second;<br>
    +    MachineOperand &CopyDst = Copy.getOperand(0);<br>
    +    MachineOperand &CopySrc = Copy.getOperand(1);<br>
    +<br>
    +    // Don't forward COPYs that are already NOPs due to register<br>
    assignment.<br>
    +    if (getPhysReg(CopyDst) == getPhysReg(CopySrc))<br>
    +      continue;<br>
    +<br>
    +    // FIXME: Don't handle partial uses of wider COPYs yet.<br>
    +    if (CopyDst.getSubReg() != 0 || UseReg != getPhysReg(CopyDst))<br>
    +      continue;<br>
    +<br>
    +    // Don't forward COPYs of non-allocatable regs unless they are<br>
    constant.<br>
    +    unsigned CopySrcReg = CopySrc.getReg();<br>
    +    if (TargetRegisterInfo::isPhysica<wbr>lRegister(CopySrcReg) &&<br>
    +        !MRI->isAllocatable(CopySrcReg<wbr>) &&<br>
    !MRI->isConstantPhysReg(CopySr<wbr>cReg))<br>
    +      continue;<br>
    +<br>
    +    if (!isForwardableRegClassCopy(Co<wbr>py, MI))<br>
    +      continue;<br>
    +<br>
    +    unsigned NewUseReg, NewUseSubReg;<br>
    +    bool SubRegOK;<br>
    +    std::tie(NewUseReg, NewUseSubReg, SubRegOK) =<br>
    +        checkUseSubReg(CopySrc, MOUse);<br>
    +    if (!SubRegOK)<br>
    +      continue;<br>
    +<br>
    +    if (hasImplicitOverlap(MI, MOUse))<br>
    +      continue;<br>
    +<br>
    +    DEBUG(dbgs() << "MCP: Replacing "<br>
    +          << PrintReg(MOUse.getReg(), TRI, MOUse.getSubReg())<br>
    +          << "\n     with "<br>
    +          << PrintReg(NewUseReg, TRI, CopySrc.getSubReg())<br>
    +          << "\n     in "<br>
    +          << MI<br>
    +          << "     from "<br>
    +          << Copy);<br>
    +<br>
    +    narrowRegClass(MI, MOUse, NewUseReg, NewUseSubReg);<br>
    +<br>
    +    unsigned OrigUseReg = MOUse.getReg();<br>
    +    MOUse.setReg(NewUseReg);<br>
    +    MOUse.setSubReg(NewUseSubReg);<br>
    +<br>
    +    DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");<br>
    +<br>
    +    if (PreRegRewrite)<br>
    +      updateForwardedCopyLiveInterva<wbr>l(Copy, MI, OrigUseReg, NewUseReg,<br>
    +                                      NewUseSubReg);<br>
    +    else<br>
    +      for (MachineInstr &KMI :<br>
    +             make_range(Copy.getIterator()<wbr>,<br>
    std::next(MI.getIterator())))<br>
    +        KMI.clearRegisterKills(NewUseR<wbr>eg, TRI);<br>
    +<br>
    +    ++NumCopyForwards;<br>
    +    Changed = true;<br>
    +  }<br>
    +}<br>
    +<br>
      void MachineCopyPropagation::CopyPr<wbr>opagateBlock(MachineBasicBlock<br>
    &MBB) {<br>
        DEBUG(dbgs() << "MCP: CopyPropagateBlock " << MBB.getName() <<<br>
    "\n");<br>
<br>
    @@ -198,12 +687,8 @@ void MachineCopyPropagation::CopyPr<wbr>opaga<br>
          ++I;<br>
<br>
          if (MI->isCopy()) {<br>
    -      unsigned Def = MI->getOperand(0).getReg();<br>
    -      unsigned Src = MI->getOperand(1).getReg();<br>
    -<br>
    -      assert(!TargetRegisterInfo::is<wbr>VirtualRegister(Def) &&<br>
    -             !TargetRegisterInfo::isVirtua<wbr>lRegister(Src) &&<br>
    -             "MachineCopyPropagation should be run after register<br>
    allocation!");<br>
    +      unsigned Def = getPhysReg(MI->getOperand(0));<br>
    +      unsigned Src = getPhysReg(MI->getOperand(1));<br>
<br>
            // The two copies cancel out and the source of the first copy<br>
            // hasn't been overridden, eliminate the second one. e.g.<br>
    @@ -220,8 +705,16 @@ void MachineCopyPropagation::CopyPr<wbr>opaga<br>
            //  %ECX<def> = COPY %EAX<br>
            // =><br>
            //  %ECX<def> = COPY %EAX<br>
    -      if (eraseIfRedundant(*MI, Def, Src) || eraseIfRedundant(*MI,<br>
    Src, Def))<br>
    -        continue;<br>
    +      if (!PreRegRewrite)<br>
    +        if (eraseIfRedundant(*MI, Def, Src) ||<br>
    eraseIfRedundant(*MI, Src, Def))<br>
    +          continue;<br>
    +<br>
    +      forwardUses(*MI);<br>
    +<br>
    +      // Src may have been changed by forwardUses()<br>
    +      Src = getPhysReg(MI->getOperand(1));<br>
    +      unsigned DefClobber = getFullPhysReg(MI->getOperand(<wbr>0));<br>
    +      unsigned SrcClobber = getFullPhysReg(MI->getOperand(<wbr>1));<br>
<br>
            // If Src is defined by a previous copy, the previous copy<br>
    cannot be<br>
            // eliminated.<br>
    @@ -238,7 +731,10 @@ void MachineCopyPropagation::CopyPr<wbr>opaga<br>
            DEBUG(dbgs() << "MCP: Copy is a deletion candidate: ";<br>
    MI->dump());<br>
<br>
            // Copy is now a candidate for deletion.<br>
    -      if (!MRI->isReserved(Def))<br>
    +      // Only look for dead COPYs if we're not running just before<br>
    +      // VirtRegRewriter, since presumably these COPYs will have<br>
    already been<br>
    +      // removed.<br>
    +      if (!PreRegRewrite && !MRI->isReserved(Def))<br>
              MaybeDeadCopies.insert(MI);<br>
<br>
            // If 'Def' is previously source of another copy, then this<br>
    earlier copy's<br>
    @@ -248,11 +744,11 @@ void MachineCopyPropagation::CopyPr<wbr>opaga<br>
            // %xmm2<def> = copy %xmm0<br>
            // ...<br>
            // %xmm2<def> = copy %xmm9<br>
    -      ClobberRegister(Def);<br>
    +      ClobberRegister(DefClobber);<br>
            for (const MachineOperand &MO : MI->implicit_operands()) {<br>
              if (!MO.isReg() || !MO.isDef())<br>
                continue;<br>
    -        unsigned Reg = MO.getReg();<br>
    +        unsigned Reg = getFullPhysReg(MO);<br>
              if (!Reg)<br>
                continue;<br>
              ClobberRegister(Reg);<br>
    @@ -267,13 +763,27 @@ void MachineCopyPropagation::CopyPr<wbr>opaga<br>
<br>
            // Remember source that's copied to Def. Once it's<br>
    clobbered, then<br>
            // it's no longer available for copy propagation.<br>
    -      RegList &DestList = SrcMap[Src];<br>
    -      if (!is_contained(DestList, Def))<br>
    -        DestList.push_back(Def);<br>
    +      RegList &DestList = SrcMap[SrcClobber];<br>
    +      if (!is_contained(DestList, DefClobber))<br>
    +        DestList.push_back(DefClobber)<wbr>;<br>
<br>
            continue;<br>
          }<br>
<br>
    +    // Clobber any earlyclobber regs first.<br>
    +    for (const MachineOperand &MO : MI->operands())<br>
    +      if (MO.isReg() && MO.isEarlyClobber()) {<br>
    +        unsigned Reg = getFullPhysReg(MO);<br>
    +        // If we have a tied earlyclobber, that means it is also<br>
    read by this<br>
    +        // instruction, so we need to make sure we don't remove it<br>
    as dead<br>
    +        // later.<br>
    +        if (MO.isTied())<br>
    +          ReadRegister(Reg);<br>
    +        ClobberRegister(Reg);<br>
    +      }<br>
    +<br>
    +    forwardUses(*MI);<br>
    +<br>
          // Not a copy.<br>
          SmallVector<unsigned, 2> Defs;<br>
          const MachineOperand *RegMask = nullptr;<br>
    @@ -282,14 +792,11 @@ void MachineCopyPropagation::CopyPr<wbr>opaga<br>
              RegMask = &MO;<br>
            if (!MO.isReg())<br>
              continue;<br>
    -      unsigned Reg = MO.getReg();<br>
    +      unsigned Reg = getFullPhysReg(MO);<br>
            if (!Reg)<br>
              continue;<br>
<br>
    -      assert(!TargetRegisterInfo::is<wbr>VirtualRegister(Reg) &&<br>
    -             "MachineCopyPropagation should be run after register<br>
    allocation!");<br>
    -<br>
    -      if (MO.isDef()) {<br>
    +      if (MO.isDef() && !MO.isEarlyClobber()) {<br>
              Defs.push_back(Reg);<br>
              continue;<br>
            } else if (MO.readsReg())<br>
    @@ -346,6 +853,8 @@ void MachineCopyPropagation::CopyPr<wbr>opaga<br>
        // since we don't want to trust live-in lists.<br>
        if (MBB.succ_empty()) {<br>
          for (MachineInstr *MaybeDead : MaybeDeadCopies) {<br>
    +      DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: ";<br>
    +            MaybeDead->dump());<br>
            assert(!MRI->isReserved(MaybeD<wbr>ead->getOperand(0).getReg()));<br>
            MaybeDead->eraseFromParent();<br>
            Changed = true;<br>
    @@ -368,10 +877,16 @@ bool MachineCopyPropagation::runOnM<wbr>achin<br>
        TRI = MF.getSubtarget().getRegisterI<wbr>nfo();<br>
        TII = MF.getSubtarget().getInstrInfo<wbr>();<br>
        MRI = &MF.getRegInfo();<br>
    +  this->MF = &MF;<br>
    +  if (PreRegRewrite) {<br>
    +    Indexes = &getAnalysis<SlotIndexes>();<br>
    +    LIS = &getAnalysis<LiveIntervals>();<br>
    +    VRM = &getAnalysis<VirtRegMap>();<br>
    +  }<br>
    +  NoSubRegLiveness = !MRI->subRegLivenessEnabled();<br>
<br>
        for (MachineBasicBlock &MBB : MF)<br>
          CopyPropagateBlock(MBB);<br>
<br>
        return Changed;<br>
      }<br>
    -<br>
<br>
    Modified: llvm/trunk/lib/CodeGen/TargetP<wbr>assConfig.cpp<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetPassConfig.cpp?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/CodeGen/T<wbr>argetPassConfig.cpp?rev=311038<wbr>&r1=311037&r2=311038&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetPassConfig.cpp?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/lib/CodeGen/<wbr>TargetPassConfig.cpp?rev=31103<wbr>8&r1=311037&r2=311038&view=<wbr>diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/lib/CodeGen/TargetP<wbr>assConfig.cpp (original)<br>
    +++ llvm/trunk/lib/CodeGen/TargetP<wbr>assConfig.cpp Wed Aug 16 13:50:01 2017<br>
    @@ -88,6 +88,8 @@ static cl::opt<bool> DisableCGP("disable<br>
          cl::desc("Disable Codegen Prepare"));<br>
      static cl::opt<bool> DisableCopyProp("disable-copyp<wbr>rop", cl::Hidden,<br>
          cl::desc("Disable Copy Propagation pass"));<br>
    +static cl::opt<bool><br>
    DisableCopyPropPreRegRewrite("<wbr>disable-copyprop-prerewrite", cl::Hidden,<br>
    +    cl::desc("Disable Copy Propagation Pre-Register Re-write pass"));<br>
      static cl::opt<bool><br>
    DisablePartialLibcallInlining(<wbr>"disable-partial-libcall-inlin<wbr>ing",<br>
          cl::Hidden, cl::desc("Disable Partial Libcall Inlining"));<br>
      static cl::opt<bool> EnableImplicitNullChecks(<br>
    @@ -248,6 +250,9 @@ static IdentifyingPassPtr overridePass(A<br>
        if (StandardID == &MachineCopyPropagationID)<br>
          return applyDisable(TargetID, DisableCopyProp);<br>
<br>
    +  if (StandardID == &MachineCopyPropagationPreRegR<wbr>ewriteID)<br>
    +    return applyDisable(TargetID, DisableCopyPropPreRegRewrite);<br>
    +<br>
        return TargetID;<br>
      }<br>
<br>
    @@ -1059,6 +1064,10 @@ void TargetPassConfig::addOptimized<wbr>RegAl<br>
          // Allow targets to change the register assignments before<br>
    rewriting.<br>
          addPreRewrite();<br>
<br>
    +    // Copy propagate to forward register uses and try to eliminate<br>
    COPYs that<br>
    +    // were not coalesced.<br>
    +    addPass(&MachineCopyPropagatio<wbr>nPreRegRewriteID);<br>
    +<br>
          // Finally rewrite virtual registers.<br>
          addPass(&VirtRegRewriterID);<br>
<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AArch6<wbr>4/aarch64-fold-lslfast.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/aarch64-fold-lslfast.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AArch64/aarch64-fold-lslfast.l<wbr>l?rev=311038&r1=311037&r2=3110<wbr>38&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/aarch64-fold-lslfast.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/test/CodeGen<wbr>/AArch64/aarch64-fold-lslfast.<wbr>ll?rev=311038&r1=311037&r2=311<wbr>038&view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/test/CodeGen/AArch6<wbr>4/aarch64-fold-lslfast.ll (original)<br>
    +++ llvm/trunk/test/CodeGen/AArch6<wbr>4/aarch64-fold-lslfast.ll Wed Aug<br>
    16 13:50:01 2017<br>
    @@ -9,7 +9,8 @@ define i16 @halfword(%struct.a* %ctx, i3<br>
      ; CHECK-LABEL: halfword:<br>
      ; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #8<br>
      ; CHECK: ldrh [[REG1:w[0-9]+]], [{{.*}}[[REG2:x[0-9]+]], [[REG]],<br>
    lsl #1]<br>
    -; CHECK: strh [[REG1]], [{{.*}}[[REG2]], [[REG]], lsl #1]<br>
    +; CHECK: mov [[REG3:x[0-9]+]], [[REG2]]<br>
    +; CHECK: strh [[REG1]], [{{.*}}[[REG3]], [[REG]], lsl #1]<br>
        %shr81 = lshr i32 %xor72, 9<br>
        %conv82 = zext i32 %shr81 to i64<br>
        %idxprom83 = and i64 %conv82, 255<br>
    @@ -24,7 +25,8 @@ define i32 @word(%struct.b* %ctx, i32 %x<br>
      ; CHECK-LABEL: word:<br>
      ; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #8<br>
      ; CHECK: ldr [[REG1:w[0-9]+]], [{{.*}}[[REG2:x[0-9]+]], [[REG]],<br>
    lsl #2]<br>
    -; CHECK: str [[REG1]], [{{.*}}[[REG2]], [[REG]], lsl #2]<br>
    +; CHECK: mov [[REG3:x[0-9]+]], [[REG2]]<br>
    +; CHECK: str [[REG1]], [{{.*}}[[REG3]], [[REG]], lsl #2]<br>
        %shr81 = lshr i32 %xor72, 9<br>
        %conv82 = zext i32 %shr81 to i64<br>
        %idxprom83 = and i64 %conv82, 255<br>
    @@ -39,7 +41,8 @@ define i64 @doubleword(%struct.c* %ctx,<br>
      ; CHECK-LABEL: doubleword:<br>
      ; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #8<br>
      ; CHECK: ldr [[REG1:x[0-9]+]], [{{.*}}[[REG2:x[0-9]+]], [[REG]],<br>
    lsl #3]<br>
    -; CHECK: str [[REG1]], [{{.*}}[[REG2]], [[REG]], lsl #3]<br>
    +; CHECK: mov [[REG3:x[0-9]+]], [[REG2]]<br>
    +; CHECK: str [[REG1]], [{{.*}}[[REG3]], [[REG]], lsl #3]<br>
        %shr81 = lshr i32 %xor72, 9<br>
        %conv82 = zext i32 %shr81 to i64<br>
        %idxprom83 = and i64 %conv82, 255<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AArch6<wbr>4/arm64-AdvSIMD-Scalar.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-AdvSIMD-Scalar.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AArch64/arm64-AdvSIMD-Scalar.l<wbr>l?rev=311038&r1=311037&r2=3110<wbr>38&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-AdvSIMD-Scalar.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/test/CodeGen<wbr>/AArch64/arm64-AdvSIMD-Scalar.<wbr>ll?rev=311038&r1=311037&r2=311<wbr>038&view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/test/CodeGen/AArch6<wbr>4/arm64-AdvSIMD-Scalar.ll (original)<br>
    +++ llvm/trunk/test/CodeGen/AArch6<wbr>4/arm64-AdvSIMD-Scalar.ll Wed Aug<br>
    16 13:50:01 2017<br>
    @@ -8,15 +8,9 @@ define <2 x i64> @bar(<2 x i64> %a, <2 x<br>
      ; CHECK: add.2d        v[[REG:[0-9]+]], v0, v1<br>
      ; CHECK: add   d[[REG3:[0-9]+]], d[[REG]], d1<br>
      ; CHECK: sub   d[[REG2:[0-9]+]], d[[REG]], d1<br>
    -; Without advanced copy optimization, we end up with cross register<br>
    -; banks copies that cannot be coalesced.<br>
    -; CHECK-NOOPT: fmov [[COPY_REG3:x[0-9]+]], d[[REG3]]<br>
    -; With advanced copy optimization, we end up with just one copy<br>
    -; to insert the computed high part into the V register.<br>
    -; CHECK-OPT-NOT: fmov<br>
    +; CHECK-NOT: fmov<br>
      ; CHECK: fmov [[COPY_REG2:x[0-9]+]], d[[REG2]]<br>
    -; CHECK-NOOPT: fmov d0, [[COPY_REG3]]<br>
    -; CHECK-OPT-NOT: fmov<br>
    +; CHECK-NOT: fmov<br>
      ; CHECK: ins.d v0[1], [[COPY_REG2]]<br>
      ; CHECK-NEXT: ret<br>
      ;<br>
    @@ -24,11 +18,9 @@ define <2 x i64> @bar(<2 x i64> %a, <2 x<br>
      ; GENERIC: add v[[REG:[0-9]+]].2d, v0.2d, v1.2d<br>
      ; GENERIC: add d[[REG3:[0-9]+]], d[[REG]], d1<br>
      ; GENERIC: sub d[[REG2:[0-9]+]], d[[REG]], d1<br>
    -; GENERIC-NOOPT: fmov [[COPY_REG3:x[0-9]+]], d[[REG3]]<br>
    -; GENERIC-OPT-NOT: fmov<br>
    +; GENERIC-NOT: fmov<br>
      ; GENERIC: fmov [[COPY_REG2:x[0-9]+]], d[[REG2]]<br>
    -; GENERIC-NOOPT: fmov d0, [[COPY_REG3]]<br>
    -; GENERIC-OPT-NOT: fmov<br>
    +; GENERIC-NOT: fmov<br>
      ; GENERIC: ins v0.d[1], [[COPY_REG2]]<br>
      ; GENERIC-NEXT: ret<br>
        %add = add <2 x i64> %a, %b<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AArch6<wbr>4/arm64-zero-cycle-regmov.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-zero-cycle-regmov.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AArch64/arm64-zero-cycle-regmo<wbr>v.ll?rev=311038&r1=311037&r2=<wbr>311038&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-zero-cycle-regmov.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/test/CodeGen<wbr>/AArch64/arm64-zero-cycle-regm<wbr>ov.ll?rev=311038&r1=311037&r2=<wbr>311038&view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/test/CodeGen/AArch6<wbr>4/arm64-zero-cycle-regmov.ll<br>
    (original)<br>
    +++ llvm/trunk/test/CodeGen/AArch6<wbr>4/arm64-zero-cycle-regmov.ll Wed<br>
    Aug 16 13:50:01 2017<br>
    @@ -4,8 +4,10 @@<br>
      define i32 @t(i32 %a, i32 %b, i32 %c, i32 %d) nounwind ssp {<br>
      entry:<br>
      ; CHECK-LABEL: t:<br>
    -; CHECK: mov x0, [[REG1:x[0-9]+]]<br>
    -; CHECK: mov x1, [[REG2:x[0-9]+]]<br>
    +; CHECK: mov [[REG2:x[0-9]+]], x3<br>
    +; CHECK: mov [[REG1:x[0-9]+]], x2<br>
    +; CHECK: mov x0, x2<br>
    +; CHECK: mov x1, x3<br>
      ; CHECK: bl _foo<br>
      ; CHECK: mov x0, [[REG1]]<br>
      ; CHECK: mov x1, [[REG2]]<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AArch6<wbr>4/f16-instructions.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/f16-instructions.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AArch64/f16-instructions.ll?re<wbr>v=311038&r1=311037&r2=311038&<wbr>view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/f16-instructions.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/test/CodeGen<wbr>/AArch64/f16-instructions.ll?r<wbr>ev=311038&r1=311037&r2=311038&<wbr>view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/test/CodeGen/AArch6<wbr>4/f16-instructions.ll (original)<br>
    +++ llvm/trunk/test/CodeGen/AArch6<wbr>4/f16-instructions.ll Wed Aug 16<br>
    13:50:01 2017<br>
    @@ -350,7 +350,7 @@ else:<br>
<br>
      ; CHECK-LABEL: test_phi:<br>
      ; CHECK: mov  x[[PTR:[0-9]+]], x0<br>
    -; CHECK: ldr  h[[AB:[0-9]+]], [x[[PTR]]]<br>
    +; CHECK: ldr  h[[AB:[0-9]+]], [x0]<br>
      ; CHECK: [[LOOP:LBB[0-9_]+]]:<br>
      ; CHECK: mov.16b  v[[R:[0-9]+]], v[[AB]]<br>
      ; CHECK: ldr  h[[AB]], [x[[PTR]]]<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AArch6<wbr>4/flags-multiuse.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/flags-multiuse.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AArch64/flags-multiuse.ll?rev=<wbr>311038&r1=311037&r2=311038&vie<wbr>w=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/flags-multiuse.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/test/CodeGen<wbr>/AArch64/flags-multiuse.ll?rev<wbr>=311038&r1=311037&r2=311038&<wbr>view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/test/CodeGen/AArch6<wbr>4/flags-multiuse.ll (original)<br>
    +++ llvm/trunk/test/CodeGen/AArch6<wbr>4/flags-multiuse.ll Wed Aug 16<br>
    13:50:01 2017<br>
    @@ -17,6 +17,9 @@ define i32 @test_multiflag(i32 %n, i32 %<br>
        %val = zext i1 %test to i32<br>
      ; CHECK: cset {{[xw][0-9]+}}, ne<br>
<br>
    +; CHECK: mov [[RHSCOPY:w[0-9]+]], [[RHS]]<br>
    +; CHECK: mov [[LHSCOPY:w[0-9]+]], [[LHS]]<br>
    +<br>
        store i32 %val, i32* @var<br>
<br>
        call void @bar()<br>
    @@ -25,7 +28,7 @@ define i32 @test_multiflag(i32 %n, i32 %<br>
        ; Currently, the comparison is emitted again. An MSR/MRS pair<br>
    would also be<br>
        ; acceptable, but assuming the call preserves NZCV is not.<br>
        br i1 %test, label %iftrue, label %iffalse<br>
    -; CHECK: cmp [[LHS]], [[RHS]]<br>
    +; CHECK: cmp [[LHSCOPY]], [[RHSCOPY]]<br>
      ; CHECK: b.eq<br>
<br>
      iftrue:<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AArch6<wbr>4/merge-store-dependency.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/merge-store-dependency.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AArch64/merge-store-dependency<wbr>.ll?rev=311038&r1=311037&r2=31<wbr>1038&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/merge-store-dependency.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/test/CodeGen<wbr>/AArch64/merge-store-dependenc<wbr>y.ll?rev=311038&r1=311037&r2=3<wbr>11038&view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/test/CodeGen/AArch6<wbr>4/merge-store-dependency.ll (original)<br>
    +++ llvm/trunk/test/CodeGen/AArch6<wbr>4/merge-store-dependency.ll Wed<br>
    Aug 16 13:50:01 2017<br>
    @@ -8,10 +8,9 @@<br>
      define void @test(%struct1* %fde, i32 %fd, void (i32, i32, i8*)*<br>
    %func, i8* %arg)  {<br>
      ;CHECK-LABEL: test<br>
      entry:<br>
    -; A53: mov [[DATA:w[0-9]+]], w1<br>
      ; A53: str q{{[0-9]+}}, {{.*}}<br>
      ; A53: str q{{[0-9]+}}, {{.*}}<br>
    -; A53: str [[DATA]], {{.*}}<br>
    +; A53: str w1, {{.*}}<br>
<br>
        %0 = bitcast %struct1* %fde to i8*<br>
        tail call void @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 40, i32<br>
    8, i1 false)<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AArch6<wbr>4/neg-imm.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/neg-imm.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AArch64/neg-imm.ll?rev=311038&<wbr>r1=311037&r2=311038&view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/neg-imm.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/test/CodeGen<wbr>/AArch64/neg-imm.ll?rev=311038<wbr>&r1=311037&r2=311038&view=diff</a><wbr>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/test/CodeGen/AArch6<wbr>4/neg-imm.ll (original)<br>
    +++ llvm/trunk/test/CodeGen/AArch6<wbr>4/neg-imm.ll Wed Aug 16 13:50:01 2017<br>
    @@ -7,8 +7,8 @@ declare void @foo(i32)<br>
      define void @test(i32 %px) {<br>
      ; CHECK_LABEL: test:<br>
      ; CHECK_LABEL: %entry<br>
    -; CHECK: subs<br>
    -; CHECK-NEXT: csel<br>
    +; CHECK: subs [[REG0:w[0-9]+]],<br>
    +; CHECK: csel {{w[0-9]+}}, wzr, [[REG0]]<br>
      entry:<br>
        %sub = add nsw i32 %px, -1<br>
        %cmp = icmp slt i32 %px, 1<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AMDGPU<wbr>/byval-frame-setup.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AMDGPU/byval-frame-setup.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AMDGPU/byval-frame-setup.ll?re<wbr>v=311038&r1=311037&r2=311038&<wbr>view=diff</a><br>
    <<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AMDGPU/byval-frame-setup.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-p<wbr>roject/llvm/trunk/test/CodeGen<wbr>/AMDGPU/byval-frame-setup.ll?r<wbr>ev=311038&r1=311037&r2=311038&<wbr>view=diff</a>><br>
    ==============================<wbr>==============================<wbr>==================<br>
    --- llvm/trunk/test/CodeGen/AMDGPU<wbr>/byval-frame-setup.ll (original)<br>
    +++ llvm/trunk/test/CodeGen/AMDGPU<wbr>/byval-frame-setup.ll Wed Aug 16<br>
    13:50:01 2017<br>
    @@ -127,20 +127,21 @@ entry:<br>
      }<br>
<br>
      ; GCN-LABEL: {{^}}call_void_func_byval_stru<wbr>ct_kernel:<br>
    -; GCN: s_mov_b32 s33, s7<br>
    -; GCN: s_add_u32 s32, s33, 0xa00{{$}}<br>
    +; GCN: s_add_u32 s32, s7, 0xa00{{$}}<br>
<br>
      ; GCN-DAG: v_mov_b32_e32 [[NINE:v[0-9]+]], 9<br>
      ; GCN-DAG: v_mov_b32_e32 [[THIRTEEN:v[0-9]+]], 13<br>
    -; GCN-DAG: buffer_store_dword [[NINE]], off, s[0:3], s33 offset:8<br>
    -; GCN: buffer_store_dword [[THIRTEEN]], off, s[0:3], s33 offset:24<br>
    +; GCN-DAG: buffer_store_dword [[NINE]], off, s[0:3], s7 offset:8<br>
    +; GCN: buffer_store_dword [[THIRTEEN]], off, s[0:3], s7 offset:24<br>
    +<br>
    +; GCN: s_mov_b32 s33, s7<br>
<br>
      ; GCN-DAG: s_add_u32 s32, s32, 0x800{{$}}<br>
<br>
    -; GCN-DAG: buffer_load_dword [[LOAD0:v[0-9]+]], off, s[0:3], s33<br>
    offset:8<br>
    -; GCN-DAG: buffer_load_dword [[LOAD1:v[0-9]+]], off, s[0:3], s33<br>
    offset:12<br>
    -; GCN-DAG: buffer_load_dword [[LOAD2:v[0-9]+]], off, s[0:3], s33<br>
    offset:16<br>
    -; GCN-DAG: buffer_load_dword [[LOAD3:v[0-9]+]], off, s[0:3], s33<br>
    offset:20<br>
    +; GCN-DAG: buffer_load_dword [[LOAD0:v[0-9]+]], off, s[0:3],<br>
    s{{7|33}} offset:8<br></div></div>
    +; GCN-DAG: buffer_load_dword [[LOAD1:v[0-9]+]], off, s[0:3],<span class=""><br>
    s{{7|33}} offset:12<br></span>
    +; GCN-DAG: buffer_load_dword [[LOAD2:v[0-9]+]], off, s[0:3],<span class=""><br>
    s{{7|33}} offset:16<br></span>
    +; GCN-DAG: buffer_load_dword [[LOAD3:v[0-9]+]], off, s[0:3],<span class=""><br>
    s{{7|33}} offset:20<br>
<br>
      ; GCN-DAG: buffer_store_dword [[LOAD0]], off, s[0:3], s32<br>
    offset:4{{$}}<br>
      ; GCN-DAG: buffer_store_dword [[LOAD1]], off, s[0:3], s32 offset:8<br>
<br>
    Modified: llvm/trunk/test/CodeGen/AMDGPU<wbr>/call-argument-types.ll<br>
    URL:<br>
    <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AMDGPU/call-argument-types.ll?rev=311038&r1=311037&r2=311038&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/CodeGen/<wbr>AMDGPU/call-argument-types.ll?<wbr>rev=311038&r1=311037&r2=311038<wbr>&view=diff</a></span></blockquote>
</blockquote></div><br></div>
</blockquote></div><br></div>