<div dir="ltr">Thanks, it passes now.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jul 9, 2015 at 8:22 AM, Silviu Baranga <span dir="ltr"><<a href="mailto:Silviu.Baranga@arm.com" target="_blank">Silviu.Baranga@arm.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">







<div lang="EN-US" link="blue" vlink="purple">
<div>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">I’ve committed a fix for this for this in r241809.<u></u><u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">@Reid: I couldn’t test this on windows. Is this issue fixed for you now?<u></u><u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Regarding stage2/3 differences, I’ve tested this locally and now the only
 difference seems to be the binary timestamp.<u></u><u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Thanks,<u></u><u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Silviu<u></u><u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></font></p>
<p class="MsoNormal"><font size="2" color="#1f497d" face="Calibri"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></font></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt">
<div>
<div style="border:none;border-top:solid #b5c4df 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><font size="2" face="Tahoma"><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";font-weight:bold">From:</span></font></b><font size="2" face="Tahoma"><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">
 NAKAMURA Takumi [mailto:<a href="mailto:geek4civic@gmail.com" target="_blank">geek4civic@gmail.com</a>] <br><span class="">
<b><span style="font-weight:bold">Sent:</span></b> 09 July 2015 02:33<br>
<b><span style="font-weight:bold">To:</span></b> Reid Kleckner; Silviu Baranga<br>
<b><span style="font-weight:bold">Cc:</span></b> llvm-commits<br>
</span><b><span style="font-weight:bold">Subject:</span></b> Re: [llvm] r241673 - [LAA] Merge memchecks for accesses separated by a constant offset<u></u><u></u></span></font></p>
</div>
</div><div><div class="h5">
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
<div>
<p class="MsoNormal"><font size="1" color="black" face="Menlo"><span style="font-size:8.5pt;font-family:"Menlo","serif";color:black;background:#aaffaa">DepCandidates (std::set) is dubious.</span></font><u></u><u></u></p>
</div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">On Thu, Jul 9, 2015 at 10:06 AM NAKAMURA Takumi <<a href="mailto:geek4civic@gmail.com" target="_blank">geek4civic@gmail.com</a>> wrote:<u></u><u></u></span></font></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">Seems causes different emissions between stage2 and stage3.<br>
<br>
  <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__bb.pgr.jp_builders_clang-2D3stage-2Di686-2Dlinux_builds_2726&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=PG9tyRTJ35Lzcl2x8waPaa4EM6Bmd6AaTefsOAlgF64&s=EgSaT1NJ8Cr-w2nH8Vk6ZsxMdzr-fNM6tym1yAetDz4&e=" target="_blank">http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2726</a><u></u><u></u></span></font></p>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">Stage2 is built by clang built by g++, +Asserts.<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">Stage3 is built by clang built by stage2-clang, -Asserts.<u></u><u></u></span></font></p>
</div>
</div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">On Thu, Jul 9, 2015 at 6:25 AM Reid Kleckner <<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>> wrote:<u></u><u></u></span></font></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">The number-memchecks.ll test fails for me on Windows because the output ordering is different. The two check groups are printed in opposite order:<u></u><u></u></span></font></p>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">"""<u></u><u></u></span></font></p>
</div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">Printing analysis 'Loop Access Analysis' for function 'testg':<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">  for.body:<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">    Report: unsafe dependent memory operations in loop<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">    Interesting Dependences:<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">      Unknown:<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">          store i16 %mul1, i16* %arrayidxC, align 2 -><u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">          store i16 %mul, i16* %arrayidxC1, align 2<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">    Run-time memory checks:<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">    Check 0:<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">      Comparing group 0:<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">        %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">      Against group 2:<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">        %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">        %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">    Check 1:<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">      Comparing group 1:<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">        %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">        %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">      Against group 2:<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">        %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">        %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<u></u><u></u></span></font></p>
</div>
</div>
</div>
<div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">"""<u></u><u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">Can you fix the code to be deterministic, i.e. not rely on hashtable ordering?<u></u><u></u></span></font></p>
</div>
</div>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
<div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">On Wed, Jul 8, 2015 at 2:16 AM, Silviu Baranga <<a href="mailto:silviu.baranga@arm.com" target="_blank">silviu.baranga@arm.com</a>> wrote:<u></u><u></u></span></font></p>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">Author: sbaranga<br>
Date: Wed Jul  8 04:16:33 2015<br>
New Revision: 241673<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D241673-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=Dxo7K237VlAGYajD5SNgUt5XddeKt_mFDUjKmbGQiqw&e=" target="_blank">
http://llvm.org/viewvc/llvm-project?rev=241673&view=rev</a><br>
Log:<br>
[LAA] Merge memchecks for accesses separated by a constant offset<br>
<br>
Summary:<br>
Often filter-like loops will do memory accesses that are<br>
separated by constant offsets. In these cases it is<br>
common that we will exceed the threshold for the<br>
allowable number of checks.<br>
<br>
However, it should be possible to merge such checks,<br>
sice a check of any interval againt two other intervals separated<br>
by a constant offset (a,b), (a+c, b+c) will be equivalent with<br>
a check againt (a, b+c), as long as (a,b) and (a+c, b+c) overlap.<br>
Assuming the loop will be executed for a sufficient number of<br>
iterations, this will be true. If not true, checking against<br>
(a, b+c) is still safe (although not equivalent).<br>
<br>
As long as there are no dependencies between two accesses,<br>
we can merge their checks into a single one. We use this<br>
technique to construct groups of accesses, and then check<br>
the intervals associated with the groups instead of<br>
checking the accesses directly.<br>
<br>
Reviewers: anemet<br>
<br>
Subscribers: llvm-commits<br>
<br>
Differential Revision: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__reviews.llvm.org_D10386&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=WZTW9zyjMHaRKXUhKETIcSFkjBukReMt6Zx5q0F5GLo&e=" target="_blank">
http://reviews.llvm.org/D10386</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h<br>
    llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp<br>
    llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll<br>
    llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll<br>
    llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll<br>
    llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll<br>
<br>
Modified: llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_include_llvm_Analysis_LoopAccessAnalysis.h-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=ee7qyjv9D3q1usyor7Ut8EOQ4lfsGoBXXa40MufUDrQ&e=" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h?rev=241673&r1=241672&r2=241673&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h (original)<br>
+++ llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h Wed Jul  8 04:16:33 2015<br>
@@ -311,7 +311,7 @@ public:<br>
   /// This struct holds information about the memory runtime legality check that<br>
   /// a group of pointers do not overlap.<br>
   struct RuntimePointerCheck {<br>
-    RuntimePointerCheck() : Need(false) {}<br>
+    RuntimePointerCheck(ScalarEvolution *SE) : Need(false), SE(SE) {}<br>
<br>
     /// Reset the state of the pointer runtime information.<br>
     void reset() {<br>
@@ -322,16 +322,55 @@ public:<br>
       IsWritePtr.clear();<br>
       DependencySetId.clear();<br>
       AliasSetId.clear();<br>
+      Exprs.clear();<br>
     }<br>
<br>
     /// Insert a pointer and calculate the start and end SCEVs.<br>
-    void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr,<br>
-                unsigned DepSetId, unsigned ASId,<br>
-                const ValueToValueMap &Strides);<br>
+    void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,<br>
+                unsigned ASId, const ValueToValueMap &Strides);<br>
<br>
     /// \brief No run-time memory checking is necessary.<br>
     bool empty() const { return Pointers.empty(); }<br>
<br>
+    /// A grouping of pointers. A single memcheck is required between<br>
+    /// two groups.<br>
+    struct CheckingPtrGroup {<br>
+      /// \brief Create a new pointer checking group containing a single<br>
+      /// pointer, with index \p Index in RtCheck.<br>
+      CheckingPtrGroup(unsigned Index, RuntimePointerCheck &RtCheck)<br>
+          : RtCheck(RtCheck), High(RtCheck.Ends[Index]),<br>
+            Low(RtCheck.Starts[Index]) {<br>
+        Members.push_back(Index);<br>
+      }<br>
+<br>
+      /// \brief Tries to add the pointer recorded in RtCheck at index<br>
+      /// \p Index to this pointer checking group. We can only add a pointer<br>
+      /// to a checking group if we will still be able to get<br>
+      /// the upper and lower bounds of the check. Returns true in case<br>
+      /// of success, false otherwise.<br>
+      bool addPointer(unsigned Index);<br>
+<br>
+      /// Constitutes the context of this pointer checking group. For each<br>
+      /// pointer that is a member of this group we will retain the index<br>
+      /// at which it appears in RtCheck.<br>
+      RuntimePointerCheck &RtCheck;<br>
+      /// The SCEV expression which represents the upper bound of all the<br>
+      /// pointers in this group.<br>
+      const SCEV *High;<br>
+      /// The SCEV expression which represents the lower bound of all the<br>
+      /// pointers in this group.<br>
+      const SCEV *Low;<br>
+      /// Indices of all the pointers that constitute this grouping.<br>
+      SmallVector<unsigned, 2> Members;<br>
+    };<br>
+<br>
+    /// \brief Groups pointers such that a single memcheck is required<br>
+    /// between two different groups. This will clear the CheckingGroups vector<br>
+    /// and re-compute it. We will only group dependecies if \p UseDependencies<br>
+    /// is true, otherwise we will create a separate group for each pointer.<br>
+    void groupChecks(MemoryDepChecker::DepCandidates &DepCands,<br>
+                     bool UseDependencies);<br>
+<br>
     /// \brief Decide whether we need to issue a run-time check for pointer at<br>
     /// index \p I and \p J to prove their independence.<br>
     ///<br>
@@ -341,6 +380,12 @@ public:<br>
     bool needsChecking(unsigned I, unsigned J,<br>
                        const SmallVectorImpl<int> *PtrPartition) const;<br>
<br>
+    /// \brief Decide if we need to add a check between two groups of pointers,<br>
+    /// according to needsChecking.<br>
+    bool needsChecking(const CheckingPtrGroup &M,<br>
+                       const CheckingPtrGroup &N,<br>
+                       const SmallVectorImpl<int> *PtrPartition) const;<br>
+<br>
     /// \brief Return true if any pointer requires run-time checking according<br>
     /// to needsChecking.<br>
     bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;<br>
@@ -372,6 +417,12 @@ public:<br>
     SmallVector<unsigned, 2> DependencySetId;<br>
     /// Holds the id of the disjoint alias set to which this pointer belongs.<br>
     SmallVector<unsigned, 2> AliasSetId;<br>
+    /// Holds at position i the SCEV for the access i<br>
+    SmallVector<const SCEV *, 2> Exprs;<br>
+    /// Holds a partitioning of pointers into "check groups".<br>
+    SmallVector<CheckingPtrGroup, 2> CheckingGroups;<br>
+    /// Holds a pointer to the ScalarEvolution analysis.<br>
+    ScalarEvolution *SE;<br>
   };<br>
<br>
   LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,<br>
<br>
Modified: llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Analysis_LoopAccessAnalysis.cpp-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=jgDoUSmGrEpNcijw3f5mG6psVDXWQp5Rz1pJjlCtKRQ&e=" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp?rev=241673&r1=241672&r2=241673&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp Wed Jul  8 04:16:33 2015<br>
@@ -48,6 +48,13 @@ static cl::opt<unsigned, true> RuntimeMe<br>
     cl::location(VectorizerParams::RuntimeMemoryCheckThreshold), cl::init(8));<br>
 unsigned VectorizerParams::RuntimeMemoryCheckThreshold;<br>
<br>
+/// \brief The maximum iterations used to merge memory checks<br>
+static cl::opt<unsigned> MemoryCheckMergeThreshold(<br>
+    "memory-check-merge-threshold", cl::Hidden,<br>
+    cl::desc("Maximum number of comparisons done when trying to merge "<br>
+             "runtime memory checks. (default = 100)"),<br>
+    cl::init(100));<br>
+<br>
 /// Maximum SIMD width.<br>
 const unsigned VectorizerParams::MaxVectorWidth = 64;<br>
<br>
@@ -113,8 +120,8 @@ const SCEV *llvm::replaceSymbolicStrideS<br>
 }<br>
<br>
 void LoopAccessInfo::RuntimePointerCheck::insert(<br>
-    ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,<br>
-    unsigned ASId, const ValueToValueMap &Strides) {<br>
+    Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId, unsigned ASId,<br>
+    const ValueToValueMap &Strides) {<br>
   // Get the stride replaced scev.<br>
   const SCEV *Sc = replaceSymbolicStrideSCEV(SE, Strides, Ptr);<br>
   const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Sc);<br>
@@ -127,6 +134,136 @@ void LoopAccessInfo::RuntimePointerCheck<br>
   IsWritePtr.push_back(WritePtr);<br>
   DependencySetId.push_back(DepSetId);<br>
   AliasSetId.push_back(ASId);<br>
+  Exprs.push_back(Sc);<br>
+}<br>
+<br>
+bool LoopAccessInfo::RuntimePointerCheck::needsChecking(<br>
+    const CheckingPtrGroup &M, const CheckingPtrGroup &N,<br>
+    const SmallVectorImpl<int> *PtrPartition) const {<br>
+  for (unsigned I = 0, EI = M.Members.size(); EI != I; ++I)<br>
+    for (unsigned J = 0, EJ = N.Members.size(); EJ != J; ++J)<br>
+      if (needsChecking(M.Members[I], N.Members[J], PtrPartition))<br>
+        return true;<br>
+  return false;<br>
+}<br>
+<br>
+/// Compare \p I and \p J and return the minimum.<br>
+/// Return nullptr in case we couldn't find an answer.<br>
+static const SCEV *getMinFromExprs(const SCEV *I, const SCEV *J,<br>
+                                   ScalarEvolution *SE) {<br>
+  const SCEV *Diff = SE->getMinusSCEV(J, I);<br>
+  const SCEVConstant *C = dyn_cast<const SCEVConstant>(Diff);<br>
+<br>
+  if (!C)<br>
+    return nullptr;<br>
+  if (C->getValue()->isNegative())<br>
+    return J;<br>
+  return I;<br>
+}<br>
+<br>
+bool LoopAccessInfo::RuntimePointerCheck::CheckingPtrGroup::addPointer(<br>
+    unsigned Index) {<br>
+  // Compare the starts and ends with the known minimum and maximum<br>
+  // of this set. We need to know how we compare against the min/max<br>
+  // of the set in order to be able to emit memchecks.<br>
+  const SCEV *Min0 = getMinFromExprs(RtCheck.Starts[Index], Low, RtCheck.SE);<br>
+  if (!Min0)<br>
+    return false;<br>
+<br>
+  const SCEV *Min1 = getMinFromExprs(RtCheck.Ends[Index], High, RtCheck.SE);<br>
+  if (!Min1)<br>
+    return false;<br>
+<br>
+  // Update the low bound  expression if we've found a new min value.<br>
+  if (Min0 == RtCheck.Starts[Index])<br>
+    Low = RtCheck.Starts[Index];<br>
+<br>
+  // Update the high bound expression if we've found a new max value.<br>
+  if (Min1 != RtCheck.Ends[Index])<br>
+    High = RtCheck.Ends[Index];<br>
+<br>
+  Members.push_back(Index);<br>
+  return true;<br>
+}<br>
+<br>
+void LoopAccessInfo::RuntimePointerCheck::groupChecks(<br>
+    MemoryDepChecker::DepCandidates &DepCands,<br>
+    bool UseDependencies) {<br>
+  // We build the groups from dependency candidates equivalence classes<br>
+  // because:<br>
+  //    - We know that pointers in the same equivalence class share<br>
+  //      the same underlying object and therefore there is a chance<br>
+  //      that we can compare pointers<br>
+  //    - We wouldn't be able to merge two pointers for which we need<br>
+  //      to emit a memcheck. The classes in DepCands are already<br>
+  //      conveniently built such that no two pointers in the same<br>
+  //      class need checking against each other.<br>
+<br>
+  // We use the following (greedy) algorithm to construct the groups<br>
+  // For every pointer in the equivalence class:<br>
+  //   For each existing group:<br>
+  //   - if the difference between this pointer and the min/max bounds<br>
+  //     of the group is a constant, then make the pointer part of the<br>
+  //     group and update the min/max bounds of that group as required.<br>
+<br>
+  CheckingGroups.clear();<br>
+<br>
+  // If we don't have the dependency partitions, construct a new<br>
+  // checking pointer group for each pointer.<br>
+  if (!UseDependencies) {<br>
+    for (unsigned I = 0; I < Pointers.size(); ++I)<br>
+      CheckingGroups.push_back(CheckingPtrGroup(I, *this));<br>
+    return;<br>
+  }<br>
+<br>
+  unsigned TotalComparisons = 0;<br>
+<br>
+  DenseMap<Value *, unsigned> PositionMap;<br>
+  for (unsigned Pointer = 0; Pointer < Pointers.size(); ++Pointer)<br>
+    PositionMap[Pointers[Pointer]] = Pointer;<br>
+<br>
+  // Go through all equivalence classes, get the the "pointer check groups"<br>
+  // and add them to the overall solution.<br>
+  for (auto DI = DepCands.begin(), DE = DepCands.end(); DI != DE; ++DI) {<br>
+    if (!DI->isLeader())<br>
+      continue;<br>
+<br>
+    SmallVector<CheckingPtrGroup, 2> Groups;<br>
+<br>
+    for (auto MI = DepCands.member_begin(DI), ME = DepCands.member_end();<br>
+         MI != ME; ++MI) {<br>
+      unsigned Pointer = PositionMap[MI->getPointer()];<br>
+      bool Merged = false;<br>
+<br>
+      // Go through all the existing sets and see if we can find one<br>
+      // which can include this pointer.<br>
+      for (CheckingPtrGroup &Group : Groups) {<br>
+        // Don't perform more than a certain amount of comparisons.<br>
+        // This should limit the cost of grouping the pointers to something<br>
+        // reasonable.  If we do end up hitting this threshold, the algorithm<br>
+        // will create separate groups for all remaining pointers.<br>
+        if (TotalComparisons > MemoryCheckMergeThreshold)<br>
+          break;<br>
+<br>
+        TotalComparisons++;<br>
+<br>
+        if (Group.addPointer(Pointer)) {<br>
+          Merged = true;<br>
+          break;<br>
+        }<br>
+      }<br>
+<br>
+      if (!Merged)<br>
+        // We couldn't add this pointer to any existing set or the threshold<br>
+        // for the number of comparisons has been reached. Create a new group<br>
+        // to hold the current pointer.<br>
+        Groups.push_back(CheckingPtrGroup(Pointer, *this));<br>
+    }<br>
+<br>
+    // We've computed the grouped checks for this partition.<br>
+    // Save the results and continue with the next one.<br>
+    std::copy(Groups.begin(), Groups.end(), std::back_inserter(CheckingGroups));<br>
+  }<br>
 }<br>
<br>
 bool LoopAccessInfo::RuntimePointerCheck::needsChecking(<br>
@@ -156,42 +293,71 @@ bool LoopAccessInfo::RuntimePointerCheck<br>
 void LoopAccessInfo::RuntimePointerCheck::print(<br>
     raw_ostream &OS, unsigned Depth,<br>
     const SmallVectorImpl<int> *PtrPartition) const {<br>
-  unsigned NumPointers = Pointers.size();<br>
-  if (NumPointers == 0)<br>
-    return;<br>
<br>
   OS.indent(Depth) << "Run-time memory checks:\n";<br>
+<br>
   unsigned N = 0;<br>
-  for (unsigned I = 0; I < NumPointers; ++I)<br>
-    for (unsigned J = I + 1; J < NumPointers; ++J)<br>
-      if (needsChecking(I, J, PtrPartition)) {<br>
-        OS.indent(Depth) << N++ << ":\n";<br>
-        OS.indent(Depth + 2) << *Pointers[I];<br>
-        if (PtrPartition)<br>
-          OS << " (Partition: " << (*PtrPartition)[I] << ")";<br>
-        OS << "\n";<br>
-        OS.indent(Depth + 2) << *Pointers[J];<br>
-        if (PtrPartition)<br>
-          OS << " (Partition: " << (*PtrPartition)[J] << ")";<br>
-        OS << "\n";<br>
+  for (unsigned I = 0; I < CheckingGroups.size(); ++I)<br>
+    for (unsigned J = I + 1; J < CheckingGroups.size(); ++J)<br>
+      if (needsChecking(CheckingGroups[I], CheckingGroups[J], PtrPartition)) {<br>
+        OS.indent(Depth) << "Check " << N++ << ":\n";<br>
+        OS.indent(Depth + 2) << "Comparing group " << I << ":\n";<br>
+<br>
+        for (unsigned K = 0; K < CheckingGroups[I].Members.size(); ++K) {<br>
+          OS.indent(Depth + 2) << *Pointers[CheckingGroups[I].Members[K]]<br>
+                               << "\n";<br>
+          if (PtrPartition)<br>
+            OS << " (Partition: "<br>
+               << (*PtrPartition)[CheckingGroups[I].Members[K]] << ")"<br>
+               << "\n";<br>
+        }<br>
+<br>
+        OS.indent(Depth + 2) << "Against group " << J << ":\n";<br>
+<br>
+        for (unsigned K = 0; K < CheckingGroups[J].Members.size(); ++K) {<br>
+          OS.indent(Depth + 2) << *Pointers[CheckingGroups[J].Members[K]]<br>
+                               << "\n";<br>
+          if (PtrPartition)<br>
+            OS << " (Partition: "<br>
+               << (*PtrPartition)[CheckingGroups[J].Members[K]] << ")"<br>
+               << "\n";<br>
+        }<br>
       }<br>
+<br>
+  OS.indent(Depth) << "Grouped accesses:\n";<br>
+  for (unsigned I = 0; I < CheckingGroups.size(); ++I) {<br>
+    OS.indent(Depth + 2) << "Group " << I << ":\n";<br>
+    OS.indent(Depth + 4) << "(Low: " << *CheckingGroups[I].Low<br>
+                         << " High: " << *CheckingGroups[I].High << ")\n";<br>
+    for (unsigned J = 0; J < CheckingGroups[I].Members.size(); ++J) {<br>
+      OS.indent(Depth + 6) << "Member: " << *Exprs[CheckingGroups[I].Members[J]]<br>
+                           << "\n";<br>
+    }<br>
+  }<br>
 }<br>
<br>
 unsigned LoopAccessInfo::RuntimePointerCheck::getNumberOfChecks(<br>
     const SmallVectorImpl<int> *PtrPartition) const {<br>
-  unsigned NumPointers = Pointers.size();<br>
+<br>
+  unsigned NumPartitions = CheckingGroups.size();<br>
   unsigned CheckCount = 0;<br>
<br>
-  for (unsigned I = 0; I < NumPointers; ++I)<br>
-    for (unsigned J = I + 1; J < NumPointers; ++J)<br>
-      if (needsChecking(I, J, PtrPartition))<br>
+  for (unsigned I = 0; I < NumPartitions; ++I)<br>
+    for (unsigned J = I + 1; J < NumPartitions; ++J)<br>
+      if (needsChecking(CheckingGroups[I], CheckingGroups[J], PtrPartition))<br>
         CheckCount++;<br>
   return CheckCount;<br>
 }<br>
<br>
 bool LoopAccessInfo::RuntimePointerCheck::needsAnyChecking(<br>
     const SmallVectorImpl<int> *PtrPartition) const {<br>
-  return getNumberOfChecks(PtrPartition) != 0;<br>
+  unsigned NumPointers = Pointers.size();<br>
+<br>
+  for (unsigned I = 0; I < NumPointers; ++I)<br>
+    for (unsigned J = I + 1; J < NumPointers; ++J)<br>
+      if (needsChecking(I, J, PtrPartition))<br>
+        return true;<br>
+  return false;<br>
 }<br>
<br>
 namespace {<br>
@@ -341,7 +507,7 @@ bool AccessAnalysis::canCheckPtrAtRT(<br>
           // Each access has its own dependence set.<br>
           DepId = RunningDepId++;<br>
<br>
-        RtCheck.insert(SE, TheLoop, Ptr, IsWrite, DepId, ASId, StridesMap);<br>
+        RtCheck.insert(TheLoop, Ptr, IsWrite, DepId, ASId, StridesMap);<br>
<br>
         DEBUG(dbgs() << "LAA: Found a runtime check ptr:" << *Ptr << '\n');<br>
       } else {<br>
@@ -387,6 +553,9 @@ bool AccessAnalysis::canCheckPtrAtRT(<br>
     }<br>
   }<br>
<br>
+  if (NeedRTCheck && CanDoRT)<br>
+    RtCheck.groupChecks(DepCands, IsDepCheckNeeded);<br>
+<br>
   return CanDoRT;<br>
 }<br>
<br>
@@ -1360,32 +1529,35 @@ std::pair<Instruction *, Instruction *><br>
   if (!PtrRtCheck.Need)<br>
     return std::make_pair(nullptr, nullptr);<br>
<br>
-  unsigned NumPointers = PtrRtCheck.Pointers.size();<br>
-  SmallVector<TrackingVH<Value> , 2> Starts;<br>
-  SmallVector<TrackingVH<Value> , 2> Ends;<br>
+  SmallVector<TrackingVH<Value>, 2> Starts;<br>
+  SmallVector<TrackingVH<Value>, 2> Ends;<br>
<br>
   LLVMContext &Ctx = Loc->getContext();<br>
   SCEVExpander Exp(*SE, DL, "induction");<br>
   Instruction *FirstInst = nullptr;<br>
<br>
-  for (unsigned i = 0; i < NumPointers; ++i) {<br>
-    Value *Ptr = PtrRtCheck.Pointers[i];<br>
+  for (unsigned i = 0; i < PtrRtCheck.CheckingGroups.size(); ++i) {<br>
+    const RuntimePointerCheck::CheckingPtrGroup &CG =<br>
+        PtrRtCheck.CheckingGroups[i];<br>
+    Value *Ptr = PtrRtCheck.Pointers[CG.Members[0]];<br>
     const SCEV *Sc = SE->getSCEV(Ptr);<br>
<br>
     if (SE->isLoopInvariant(Sc, TheLoop)) {<br>
-      DEBUG(dbgs() << "LAA: Adding RT check for a loop invariant ptr:" <<<br>
-            *Ptr <<"\n");<br>
+      DEBUG(dbgs() << "LAA: Adding RT check for a loop invariant ptr:" << *Ptr<br>
+                   << "\n");<br>
       Starts.push_back(Ptr);<br>
       Ends.push_back(Ptr);<br>
     } else {<br>
-      DEBUG(dbgs() << "LAA: Adding RT check for range:" << *Ptr << '\n');<br>
       unsigned AS = Ptr->getType()->getPointerAddressSpace();<br>
<br>
       // Use this type for pointer arithmetic.<br>
       Type *PtrArithTy = Type::getInt8PtrTy(Ctx, AS);<br>
+      Value *Start = nullptr, *End = nullptr;<br>
<br>
-      Value *Start = Exp.expandCodeFor(PtrRtCheck.Starts[i], PtrArithTy, Loc);<br>
-      Value *End = Exp.expandCodeFor(PtrRtCheck.Ends[i], PtrArithTy, Loc);<br>
+      DEBUG(dbgs() << "LAA: Adding RT check for range:\n");<br>
+      Start = Exp.expandCodeFor(CG.Low, PtrArithTy, Loc);<br>
+      End = Exp.expandCodeFor(CG.High, PtrArithTy, Loc);<br>
+      DEBUG(dbgs() << "Start: " << *CG.Low << " End: " << *CG.High << "\n");<br>
       Starts.push_back(Start);<br>
       Ends.push_back(End);<br>
     }<br>
@@ -1394,9 +1566,14 @@ std::pair<Instruction *, Instruction *><br>
   IRBuilder<> ChkBuilder(Loc);<br>
   // Our instructions might fold to a constant.<br>
   Value *MemoryRuntimeCheck = nullptr;<br>
-  for (unsigned i = 0; i < NumPointers; ++i) {<br>
-    for (unsigned j = i+1; j < NumPointers; ++j) {<br>
-      if (!PtrRtCheck.needsChecking(i, j, PtrPartition))<br>
+  for (unsigned i = 0; i < PtrRtCheck.CheckingGroups.size(); ++i) {<br>
+    for (unsigned j = i + 1; j < PtrRtCheck.CheckingGroups.size(); ++j) {<br>
+      const RuntimePointerCheck::CheckingPtrGroup &CGI =<br>
+          PtrRtCheck.CheckingGroups[i];<br>
+      const RuntimePointerCheck::CheckingPtrGroup &CGJ =<br>
+          PtrRtCheck.CheckingGroups[j];<br>
+<br>
+      if (!PtrRtCheck.needsChecking(CGI, CGJ, PtrPartition))<br>
         continue;<br>
<br>
       unsigned AS0 = Starts[i]->getType()->getPointerAddressSpace();<br>
@@ -1447,8 +1624,8 @@ LoopAccessInfo::LoopAccessInfo(Loop *L,<br>
                                const TargetLibraryInfo *TLI, AliasAnalysis *AA,<br>
                                DominatorTree *DT, LoopInfo *LI,<br>
                                const ValueToValueMap &Strides)<br>
-    : DepChecker(SE, L), TheLoop(L), SE(SE), DL(DL),<br>
-      TLI(TLI), AA(AA), DT(DT), LI(LI), NumLoads(0), NumStores(0),<br>
+    : PtrRtCheck(SE), DepChecker(SE, L), TheLoop(L), SE(SE), DL(DL), TLI(TLI),<br>
+      AA(AA), DT(DT), LI(LI), NumLoads(0), NumStores(0),<br>
       MaxSafeDepDistBytes(-1U), CanVecMem(false),<br>
       StoreToLoopInvariantAddress(false) {<br>
   if (canAnalyzeLoop())<br>
<br>
Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Analysis_LoopAccessAnalysis_number-2Dof-2Dmemchecks.ll-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=Y-v3S_4R47_3pPyXhbHdLm4ACVBkEjbE-9GgFMygShY&e=" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll?rev=241673&r1=241672&r2=241673&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll (original)<br>
+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll Wed Jul  8 04:16:33 2015<br>
@@ -1,19 +1,20 @@<br>
 ; RUN: opt -loop-accesses -analyze < %s | FileCheck %s<br>
<br>
-; 3 reads and 3 writes should need 12 memchecks<br>
-<br>
 target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"<br>
 target triple = "aarch64--linux-gnueabi"<br>
<br>
+; 3 reads and 3 writes should need 12 memchecks<br>
+; CHECK: function 'testf':<br>
 ; CHECK: Memory dependences are safe with run-time checks<br>
-; Memory dependecies have labels starting from 0, so in<br>
+<br>
+; Memory dependencies have labels starting from 0, so in<br>
 ; order to verify that we have n checks, we look for<br>
 ; (n-1): and not n:.<br>
<br>
 ; CHECK: Run-time memory checks:<br>
-; CHECK-NEXT: 0:<br>
-; CHECK: 11:<br>
-; CHECK-NOT: 12:<br>
+; CHECK-NEXT: Check 0:<br>
+; CHECK: Check 11:<br>
+; CHECK-NOT: Check 12:<br>
<br>
 define void @testf(i16* %a,<br>
                i16* %b,<br>
@@ -52,6 +53,165 @@ for.body:<br>
<br>
   %exitcond = icmp eq i64 %add, 20<br>
   br i1 %exitcond, label %for.end, label %for.body<br>
+<br>
+for.end:                                          ; preds = %for.body<br>
+  ret void<br>
+}<br>
+<br>
+; The following (testg and testh) check that we can group<br>
+; memory checks of accesses which differ by a constant value.<br>
+; Both tests are based on the following C code:<br>
+;<br>
+; void testh(short *a, short *b, short *c) {<br>
+;   unsigned long ind = 0;<br>
+;   for (unsigned long ind = 0; ind < 20; ++ind) {<br>
+;     c[2 * ind] = a[ind] * a[ind + 1];<br>
+;     c[2 * ind + 1] = a[ind] * a[ind + 1] * b[ind];<br>
+;   }<br>
+; }<br>
+;<br>
+; It is sufficient to check the intervals<br>
+; [a, a + 21], [b, b + 20] against [c, c + 41].<br>
+<br>
+; 3 reads and 2 writes - two of the reads can be merged,<br>
+; and the writes can be merged as well. This gives us a<br>
+; total of 2 memory checks.<br>
+<br>
+; CHECK: function 'testg':<br>
+<br>
+; CHECK: Run-time memory checks:<br>
+; CHECK-NEXT:   Check 0:<br>
+; CHECK-NEXT:     Comparing group 0:<br>
+; CHECK-NEXT:       %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add<br>
+; CHECK-NEXT:       %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind<br>
+; CHECK-NEXT:     Against group 2:<br>
+; CHECK-NEXT:       %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>
+; CHECK-NEXT:       %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>
+; CHECK-NEXT:   Check 1:<br>
+; CHECK-NEXT:     Comparing group 1:<br>
+; CHECK-NEXT:       %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind<br>
+; CHECK-NEXT:     Against group 2:<br>
+; CHECK-NEXT:       %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>
+; CHECK-NEXT:       %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>
+; CHECK-NEXT:   Grouped accesses:<br>
+; CHECK-NEXT:    Group 0:<br>
+; CHECK-NEXT:       (Low: %a High: (40 + %a))<br>
+; CHECK-NEXT:         Member: {(2 + %a),+,2}<br>
+; CHECK-NEXT:         Member: {%a,+,2}<br>
+; CHECK-NEXT:     Group 1:<br>
+; CHECK-NEXT:       (Low: %b High: (38 + %b))<br>
+; CHECK-NEXT:         Member: {%b,+,2}<br>
+; CHECK-NEXT:     Group 2:<br>
+; CHECK-NEXT:       (Low: %c High: (78 + %c))<br>
+; CHECK-NEXT:         Member: {(2 + %c),+,4}<br>
+; CHECK-NEXT:         Member: {%c,+,4}<br>
+<br>
+define void @testg(i16* %a,<br>
+               i16* %b,<br>
+               i16* %c) {<br>
+entry:<br>
+  br label %for.body<br>
+<br>
+for.body:                                         ; preds = %for.body, %entry<br>
+  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]<br>
+  %store_ind = phi i64 [ 0, %entry ], [ %store_ind_next, %for.body ]<br>
+<br>
+  %add = add nuw nsw i64 %ind, 1<br>
+  %store_ind_inc = add nuw nsw i64 %store_ind, 1<br>
+  %store_ind_next = add nuw nsw i64 %store_ind_inc, 1<br>
+<br>
+  %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind<br>
+  %loadA = load i16, i16* %arrayidxA, align 2<br>
+<br>
+  %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add<br>
+  %loadA1 = load i16, i16* %arrayidxA1, align 2<br>
+<br>
+  %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind<br>
+  %loadB = load i16, i16* %arrayidxB, align 2<br>
+<br>
+  %mul = mul i16 %loadA, %loadA1<br>
+  %mul1 = mul i16 %mul, %loadB<br>
+<br>
+  %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>
+  store i16 %mul1, i16* %arrayidxC, align 2<br>
+<br>
+  %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>
+  store i16 %mul, i16* %arrayidxC1, align 2<br>
+<br>
+  %exitcond = icmp eq i64 %add, 20<br>
+  br i1 %exitcond, label %for.end, label %for.body<br>
+<br>
+for.end:                                          ; preds = %for.body<br>
+  ret void<br>
+}<br>
+<br>
+; 3 reads and 2 writes - the writes can be merged into a single<br>
+; group, but the GEPs used for the reads are not marked as inbounds.<br>
+; We can still merge them because we are using a unit stride for<br>
+; accesses, so we cannot overflow the GEPs.<br>
+<br>
+; CHECK: function 'testh':<br>
+; CHECK: Run-time memory checks:<br>
+; CHECK-NEXT:   Check 0:<br>
+; CHECK-NEXT:     Comparing group 0:<br>
+; CHECK-NEXT:         %arrayidxA1 = getelementptr i16, i16* %a, i64 %add<br>
+; CHECK-NEXT:         %arrayidxA = getelementptr i16, i16* %a, i64 %ind<br>
+; CHECK-NEXT:     Against group 2:<br>
+; CHECK-NEXT:         %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>
+; CHECK-NEXT:         %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>
+; CHECK-NEXT:   Check 1:<br>
+; CHECK-NEXT:     Comparing group 1:<br>
+; CHECK-NEXT:         %arrayidxB = getelementptr i16, i16* %b, i64 %ind<br>
+; CHECK-NEXT:     Against group 2:<br>
+; CHECK-NEXT:         %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>
+; CHECK-NEXT:         %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>
+; CHECK-NEXT:   Grouped accesses:<br>
+; CHECK-NEXT:     Group 0:<br>
+; CHECK-NEXT:       (Low: %a High: (40 + %a))<br>
+; CHECK-NEXT:         Member: {(2 + %a),+,2}<br>
+; CHECK-NEXT:         Member: {%a,+,2}<br>
+; CHECK-NEXT:     Group 1:<br>
+; CHECK-NEXT:       (Low: %b High: (38 + %b))<br>
+; CHECK-NEXT:         Member: {%b,+,2}<br>
+; CHECK-NEXT:     Group 2:<br>
+; CHECK-NEXT:       (Low: %c High: (78 + %c))<br>
+; CHECK-NEXT:         Member: {(2 + %c),+,4}<br>
+; CHECK-NEXT:         Member: {%c,+,4}<br>
+<br>
+define void @testh(i16* %a,<br>
+               i16* %b,<br>
+               i16* %c) {<br>
+entry:<br>
+  br label %for.body<br>
+<br>
+for.body:                                         ; preds = %for.body, %entry<br>
+  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]<br>
+  %store_ind = phi i64 [ 0, %entry ], [ %store_ind_next, %for.body ]<br>
+<br>
+  %add = add nuw nsw i64 %ind, 1<br>
+  %store_ind_inc = add nuw nsw i64 %store_ind, 1<br>
+  %store_ind_next = add nuw nsw i64 %store_ind_inc, 1<br>
+<br>
+  %arrayidxA = getelementptr i16, i16* %a, i64 %ind<br>
+  %loadA = load i16, i16* %arrayidxA, align 2<br>
+<br>
+  %arrayidxA1 = getelementptr i16, i16* %a, i64 %add<br>
+  %loadA1 = load i16, i16* %arrayidxA1, align 2<br>
+<br>
+  %arrayidxB = getelementptr i16, i16* %b, i64 %ind<br>
+  %loadB = load i16, i16* %arrayidxB, align 2<br>
+<br>
+  %mul = mul i16 %loadA, %loadA1<br>
+  %mul1 = mul i16 %mul, %loadB<br>
+<br>
+  %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind<br>
+  store i16 %mul1, i16* %arrayidxC, align 2<br>
+<br>
+  %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc<br>
+  store i16 %mul, i16* %arrayidxC1, align 2<br>
+<br>
+  %exitcond = icmp eq i64 %add, 20<br>
+  br i1 %exitcond, label %for.end, label %for.body<br>
<br>
 for.end:                                          ; preds = %for.body<br>
   ret void<br>
<br>
Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Analysis_LoopAccessAnalysis_resort-2Dto-2Dmemchecks-2Donly.ll-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=JOc5_PXhNth6VnQN3CEEvSTM90SHTXct7enPAEmHz7I&e=" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll?rev=241673&r1=241672&r2=241673&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll (original)<br>
+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/resort-to-memchecks-only.ll Wed Jul  8 04:16:33 2015<br>
@@ -15,7 +15,9 @@ target triple = "x86_64-apple-macosx10.1<br>
 ; CHECK-NEXT: Interesting Dependences:<br>
 ; CHECK-NEXT: Run-time memory checks:<br>
 ; CHECK-NEXT: 0:<br>
+; CHECK-NEXT: Comparing group<br>
 ; CHECK-NEXT:   %arrayidxA2 = getelementptr inbounds i16, i16* %a, i64 %idx<br>
+; CHECK-NEXT: Against group<br>
 ; CHECK-NEXT:   %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %indvar<br>
<br>
 @B = common global i16* null, align 8<br>
<br>
Modified: llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Analysis_LoopAccessAnalysis_unsafe-2Dand-2Drt-2Dchecks.ll-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=YLQkgpXK7eq7uHA9rBwftq4p-U7welp1znOtw8VfhGI&e=" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll?rev=241673&r1=241672&r2=241673&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll (original)<br>
+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll Wed Jul  8 04:16:33 2015<br>
@@ -14,10 +14,16 @@ target triple = "x86_64-apple-macosx10.1<br>
 ; CHECK-NEXT:     store i16 %mul1, i16* %arrayidxA_plus_2, align 2<br>
 ; CHECK: Run-time memory checks:<br>
 ; CHECK-NEXT: 0:<br>
+; CHECK-NEXT: Comparing group<br>
+; CHECK-NEXT:   %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3<br>
 ; CHECK-NEXT:   %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add<br>
+; CHECK-NEXT: Against group<br>
 ; CHECK-NEXT:   %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %storemerge3<br>
 ; CHECK-NEXT: 1:<br>
+; CHECK-NEXT: Comparing group<br>
+; CHECK-NEXT:   %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3<br>
 ; CHECK-NEXT:   %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add<br>
+; CHECK-NEXT: Against group<br>
 ; CHECK-NEXT:   %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %storemerge3<br>
<br>
 @B = common global i16* null, align 8<br>
<br>
Modified: llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Transforms_LoopDistribute_basic-2Dwith-2Dmemchecks.ll-3Frev-3D241673-26r1-3D241672-26r2-3D241673-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=uFcf0gLR_MIrQFYhuAb8gVsoNdftcSB1mZMezpDReAU&s=e-P3DrwxY7CSNu_j9MVwxJ2dBrtPl4pmQ_epAx9j5BY&e=" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll?rev=241673&r1=241672&r2=241673&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll (original)<br>
+++ llvm/trunk/test/Transforms/LoopDistribute/basic-with-memchecks.ll Wed Jul  8 04:16:33 2015<br>
@@ -32,16 +32,14 @@ entry:<br>
   %e = load i32*, i32** @E, align 8<br>
   br label %for.body<br>
<br>
-; We have two compares for each array overlap check which is a total of 10<br>
-; compares.<br>
+; We have two compares for each array overlap check.<br>
+; Since the checks to A and A + 4 get merged, this will give us a<br>
+; total of 8 compares.<br>
 ;<br>
 ; CHECK: for.body.lver.memcheck:<br>
 ; CHECK:     = icmp<br>
 ; CHECK:     = icmp<br>
<br>
-; CHECK:     = icmp<br>
-; CHECK:     = icmp<br>
-<br>
 ; CHECK:     = icmp<br>
 ; CHECK:     = icmp<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><u></u><u></u></span></font></p>
</div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><u></u> <u></u></span></font></p>
</div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt">_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><u></u><u></u></span></font></p>
</blockquote>
</div>
</blockquote>
</div>
</div></div></div>
</div>
<br>
<font face="Arial" color="Black" size="2">-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents
 to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.<br>
<br>
ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No: 2557590<br>
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No: 2548782<br>
</font>
</div>

</blockquote></div><br></div>