diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -1264,16 +1264,22 @@ static void visitPointers(Value *StartPtr, const Loop &InnermostLoop, function_ref AddPointer) { - auto *PN = dyn_cast(StartPtr); - // SCEV does not look through non-header PHIs inside the loop. Such phis - // can be analyzed by adding separate accesses for each incoming pointer - // value. - if (PN && InnermostLoop.contains(PN->getParent()) && - PN->getParent() != InnermostLoop.getHeader()) { - for (const Use &Inc : PN->incoming_values()) - AddPointer(Inc); - } else - AddPointer(StartPtr); + SmallVector WorkList; + WorkList.push_back(StartPtr); + + while (!WorkList.empty()) { + Value *Ptr = WorkList.pop_back_val(); + auto *PN = dyn_cast(Ptr); + // SCEV does not look through non-header PHIs inside the loop. Such phis + // can be analyzed by adding separate accesses for each incoming pointer + // value. + if (PN && InnermostLoop.contains(PN->getParent()) && + PN->getParent() != InnermostLoop.getHeader()) { + for (const Use &Inc : PN->incoming_values()) + WorkList.push_back(Inc); + } else + AddPointer(Ptr); + } } void MemoryDepChecker::addAccess(StoreInst *SI) { diff --git a/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll b/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll --- a/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll @@ -78,18 +78,18 @@ ; CHECK-NEXT: Memory dependences are safe with run-time checks ; CHECK: Run-time memory checks: ; CHECK-NEXT: Check 0: -; CHECK-NEXT: Comparing group ([[GROUP_C:.+]]): -; CHECK-NEXT: %gep.2 = getelementptr inbounds double, double* %C, i64 %iv -; CHECK-NEXT: Against group ([[GROUP_B:.+]]): +; CHECK-NEXT: Comparing group ([[GROUP_B:.+]]): ; CHECK-NEXT: %gep.1 = getelementptr inbounds double, double* %B, i64 %iv -; CHECK-NEXT: Check 1: -; CHECK-NEXT: Comparing group ([[GROUP_C]]): +; CHECK-NEXT: Against group ([[GROUP_C:.+]]): ; CHECK-NEXT: %gep.2 = getelementptr inbounds double, double* %C, i64 %iv +; CHECK-NEXT: Check 1: +; CHECK-NEXT: Comparing group ([[GROUP_B]]): +; CHECK-NEXT: %gep.1 = getelementptr inbounds double, double* %B, i64 %iv ; CHECK-NEXT: Against group ([[GROUP_A:.+]]): ; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv ; CHECK-NEXT: Check 2: -; CHECK-NEXT: Comparing group ([[GROUP_B]]): -; CHECK-NEXT: %gep.1 = getelementptr inbounds double, double* %B, i64 %iv +; CHECK-NEXT: Comparing group ([[GROUP_C]]): +; CHECK-NEXT: %gep.2 = getelementptr inbounds double, double* %C, i64 %iv ; CHECK-NEXT: Against group ([[GROUP_A]]): ; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv ; @@ -163,13 +163,42 @@ define i32 @store_with_pointer_phi_incoming_phi(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) { ; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi' ; CHECK-NEXT: loop.header: -; CHECK-NEXT: Report: cannot identify array bounds +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop ; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 -> +; CHECK-NEXT: store double %mul16, double* %ptr.2, align 8 +; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Check 0: +; CHECK-NEXT: Comparing group ([[GROUP_C:.+]]): +; CHECK-NEXT: double* %C +; CHECK-NEXT: Against group ([[GROUP_B:.+]]): +; CHECK-NEXT: double* %B +; CHECK-NEXT: Check 1: +; CHECK-NEXT: Comparing group ([[GROUP_C]]): +; CHECK-NEXT: double* %C +; CHECK-NEXT: Against group ([[GROUP_A:.+]]): +; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv +; CHECK-NEXT: double* %A +; CHECK-NEXT: Check 2: +; CHECK-NEXT: Comparing group ([[GROUP_B]]): +; CHECK-NEXT: double* %B +; CHECK-NEXT: Against group ([[GROUP_A]]): +; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv +; CHECK-NEXT: double* %A ; CHECK-NEXT: Grouped accesses: -; CHECK-EMPTY: -; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. -; +; CHECK-NEXT: Group [[GROUP_C]]: +; CHECK-NEXT: (Low: %C High: (8 + %C)) +; CHECK-NEXT: Member: %C +; CHECK-NEXT: Group [[GROUP_B]]: +; CHECK-NEXT: (Low: %B High: (8 + %B)) +; CHECK-NEXT: Member: %B +; CHECK-NEXT: Group [[GROUP_A]]: +; CHECK-NEXT: (Low: %A High: (256000 + %A)) +; CHECK-NEXT: Member: {%A,+,8}<%loop.header> +; CHECK-NEXT: Member: %A +; CHECK-EMPTY entry: br label %loop.header @@ -243,6 +272,8 @@ ret i32 10 } + + define i32 @store_with_pointer_phi_in_same_bb_use_other_phi(double* %A, double* %B, double* %C, double* %D, i1 %c.0, i1 %c.1) { ; CHECK-LABEL: Loop access info in function 'store_with_pointer_phi_in_same_bb_use_other_phi': ; CHECK-NEXT: loop.header: @@ -294,39 +325,39 @@ ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Check 0: -; CHECK-NEXT: Comparing group ([[GROUP_A:.*]]): +; CHECK-NEXT: Comparing group ([[GROUP_A:.+]]): ; CHECK-NEXT: i16* %A ; CHECK-NEXT: i16* %A -; CHECK-NEXT: Against group ([[GROUP_B:.*]]): -; CHECK-NEXT: i16* %B -; CHECK-NEXT: i16* %B +; CHECK-NEXT: Against group ([[GROUP_C:.+]]): +; CHECK-NEXT: i16* %C +; CHECK-NEXT: i16* %C ; CHECK-NEXT: Check 1: ; CHECK-NEXT: Comparing group ([[GROUP_A]]): ; CHECK-NEXT: i16* %A ; CHECK-NEXT: i16* %A -; CHECK-NEXT: Against group ([[GROUP_C:.*]]): -; CHECK-NEXT: i16* %C -; CHECK-NEXT: i16* %C -; CHECK-NEXT: Check 2: -; CHECK-NEXT: Comparing group ([[GROUP_B]]): +; CHECK-NEXT: Against group ([[GROUP_B:.+]]): ; CHECK-NEXT: i16* %B ; CHECK-NEXT: i16* %B -; CHECK-NEXT: Against group ([[GROUP_C]]): +; CHECK-NEXT: Check 2: +; CHECK-NEXT: Comparing group ([[GROUP_C]]): ; CHECK-NEXT: i16* %C ; CHECK-NEXT: i16* %C +; CHECK-NEXT: Against group ([[GROUP_B]]): +; CHECK-NEXT: i16* %B +; CHECK-NEXT: i16* %B ; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Group [[GROUP_A]] ; CHECK-NEXT: (Low: %A High: (2 + %A)) ; CHECK-NEXT: Member: %A ; CHECK-NEXT: Member: %A -; CHECK-NEXT: Group [[GROUP_B]] -; CHECK-NEXT: (Low: %B High: (2 + %B)) -; CHECK-NEXT: Member: %B -; CHECK-NEXT: Member: %B ; CHECK-NEXT: Group [[GROUP_C]] ; CHECK-NEXT: (Low: %C High: (2 + %C)) ; CHECK-NEXT: Member: %C ; CHECK-NEXT: Member: %C +; CHECK-NEXT: Group [[GROUP_B]] +; CHECK-NEXT: (Low: %B High: (2 + %B)) +; CHECK-NEXT: Member: %B +; CHECK-NEXT: Member: %B ; CHECK-EMPTY: ; entry: