[LAA] LLE 2/6: Fix a NoDep case that should be a Forward dependence
authorAdam Nemet <anemet@apple.com>
Tue, 3 Nov 2015 20:13:43 +0000 (20:13 +0000)
committerAdam Nemet <anemet@apple.com>
Tue, 3 Nov 2015 20:13:43 +0000 (20:13 +0000)
Summary:
When the dependence distance in zero then we have a loop-independent
dependence from the earlier to the later access.

No current client of LAA uses forward dependences so other than
potentially hitting the MaxDependences threshold earlier, this change
shouldn't affect anything right now.

This and the previous patch were tested together for compile-time
regression.  None found in LNT/SPEC.

Reviewers: hfinkel

Subscribers: rengolin, llvm-commits

Differential Revision: http://reviews.llvm.org/D13255

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251973 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/LoopAccessAnalysis.h
lib/Analysis/LoopAccessAnalysis.cpp
test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll [new file with mode: 0644]

index 97a72b3d1cd15aa3678efbf2199ab61035c5b1c5..ea080bc7f873c4f9aa5fcfd89ca2d02ad5707480 100644 (file)
@@ -136,6 +136,14 @@ public:
       // We couldn't determine the direction or the distance.
       Unknown,
       // Lexically forward.
+      //
+      // FIXME: If we only have loop-independent forward dependences (e.g. a
+      // read and write of A[i]), LAA will locally deem the dependence "safe"
+      // without querying the MemoryDepChecker.  Therefore we can miss
+      // enumerating loop-independent forward dependences in
+      // getInterestingDependences.  Note that as soon as there are different
+      // indices used to access the same array, the MemoryDepChecker *is*
+      // queried and the dependence list is complete.
       Forward,
       // Forward, but if vectorized, is likely to prevent store-to-load
       // forwarding.
index b4b646f81443d0886512f8d579adf79e4c37b314..80d6575a9c249999705fd026218d9c1e3e40aae3 100644 (file)
@@ -1090,7 +1090,7 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
   // Could be improved to assert type sizes are the same (i32 == float, etc).
   if (Val == 0) {
     if (ATy == BTy)
-      return Dependence::NoDep;
+      return Dependence::Forward;
     DEBUG(dbgs() << "LAA: Zero dependence difference but different types\n");
     return Dependence::Unknown;
   }
diff --git a/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll b/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll
new file mode 100644 (file)
index 0000000..c5573ae
--- /dev/null
@@ -0,0 +1,64 @@
+; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
+
+; Check that loop-indepedent forward dependences are discovered properly.
+;
+; FIXME: This does not actually always work which is pretty confusing.  Right
+; now there is hack in LAA that tries to figure out loop-indepedent forward
+; dependeces *outside* of the MemoryDepChecker logic (i.e. proper dependence
+; analysis).
+;
+; Therefore if there is only loop-independent dependences for an array
+; (i.e. the same index is used), we don't discover the forward dependence.
+; So, at ***, we add another non-I-based access of A to trigger
+; MemoryDepChecker analysis for accesses of A.
+;
+;   for (unsigned i = 0; i < 100; i++) {
+;     A[i + 1] = B[i] + 1;   // ***
+;     A[i] = B[i] + 2;
+;     C[i] = A[i] * 2;
+;   }
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* noalias %A, i32* noalias %B, i32* noalias %C, i64 %N) {
+
+; CHECK: Interesting Dependences:
+; CHECK-NEXT:   Forward:
+; CHECK-NEXT:       store i32 %b_p1, i32* %Aidx, align 4 ->
+; CHECK-NEXT:       %a = load i32, i32* %Aidx, align 4
+; CHECK:        ForwardButPreventsForwarding:
+; CHECK-NEXT:       store i32 %b_p2, i32* %Aidx_next, align 4 ->
+; CHECK-NEXT:       %a = load i32, i32* %Aidx, align 4
+; CHECK:        Forward:
+; CHECK-NEXT:       store i32 %b_p2, i32* %Aidx_next, align 4 ->
+; CHECK-NEXT:       store i32 %b_p1, i32* %Aidx, align 4
+
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+
+  %Bidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
+  %Cidx = getelementptr inbounds i32, i32* %C, i64 %indvars.iv
+  %Aidx_next = getelementptr inbounds i32, i32* %A, i64 %indvars.iv.next
+  %Aidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+
+  %b = load i32, i32* %Bidx, align 4
+  %b_p2 = add i32 %b, 1
+  store i32 %b_p2, i32* %Aidx_next, align 4
+
+  %b_p1 = add i32 %b, 2
+  store i32 %b_p1, i32* %Aidx, align 4
+
+  %a = load i32, i32* %Aidx, align 4
+  %c = mul i32 %a, 2
+  store i32 %c, i32* %Cidx, align 4
+
+  %exitcond = icmp eq i64 %indvars.iv.next, %N
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+  ret void
+}