Index: llvm/lib/Analysis/LoopAccessAnalysis.cpp =================================================================== --- llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -954,9 +954,18 @@ SmallVector> Scevs; findForkedSCEVs(SE, L, Ptr, Scevs, MaxForkedSCEVDepth); - // For now, we will only accept a forked pointer with two possible SCEVs. - if (Scevs.size() == 2) + // For now, we will only accept a forked pointer with two possible SCEVs + // that are either SCEVAddRecExprs or loop invariant. + if (Scevs.size() == 2 && + (isa(Scevs[0].first) || + SE->isLoopInvariant(Scevs[0].first, L)) && + (isa(Scevs[1].first) || + SE->isLoopInvariant(Scevs[1].first, L))) { + LLVM_DEBUG(dbgs() << "LAA: Found forked pointer: " << *Ptr << "\n"); + LLVM_DEBUG(dbgs() << "\t(1) " << *(Scevs[0].first) << "\n"); + LLVM_DEBUG(dbgs() << "\t(2) " << *(Scevs[1].first) << "\n"); return Scevs; + } return { std::make_pair(replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr), false)}; Index: llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll =================================================================== --- llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll +++ llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll @@ -569,13 +569,13 @@ ; CHECK-NEXT: Against group ([[G2:.+]]): ; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv ; CHECK-NEXT: Check 1: -; CHECK-NEXT: Comparing group ([[G1:.+]]): +; CHECK-NEXT: Comparing group ([[G1]]): ; CHECK-NEXT: %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv ; CHECK-NEXT: Against group ([[G3:.+]]): ; CHECK-NEXT: %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset ; CHECK-NEXT: %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset ; CHECK-NEXT: Grouped accesses: -; CHECK-NEXT: Group [[G1:.+]]: +; CHECK-NEXT: Group [[G1]]: ; CHECK-NEXT: (Low: %Dest High: (400 + %Dest)) ; CHECK-NEXT: Member: {%Dest,+,4}<%for.body> ; CHECK-NEXT: Group [[G2]]: @@ -880,3 +880,59 @@ for.cond.cleanup: ret void } + +; CHECK-LABEL: Loop access info in function 'sc_add_expr_ice': +; CHECK-NEXT: for.body.us: +; CHECK-NEXT: Memory dependences are safe with run-time checks +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Check 0: +; CHECK-NEXT: Comparing group ([[G1:.+]]): +; CHECK-NEXT: ptr %arrayidx3.i.i.us +; CHECK-NEXT: Against group ([[G2:.+]]): +; CHECK-NEXT: %cond.in.us = getelementptr inbounds double, ptr %0, i64 %cond.in.v.us +; CHECK-NEXT: Grouped accesses: +; CHECK-NEXT: Group [[G1]]: +; CHECK-NEXT: (Low: %arrayidx3.i.i.us High: (8 + %arrayidx3.i.i.us)) +; CHECK-NEXT: Member: %arrayidx3.i.i.us +; CHECK-NEXT: Group [[G2]]: +; CHECK-NEXT: (Low: %0 High: %0) +; CHECK-NEXT: Member: {%0,+,8}<%for.body.us> +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-NEXT: {0,+,1}<%for.body.us> Added Flags: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; CHECK-NEXT: [PSE] %cond.in.us = getelementptr inbounds double, ptr %0, i64 %cond.in.v.us: +; CHECK-NEXT: ((8 * (zext i32 {0,+,1}<%for.body.us> to i64)) + %0) +; CHECK-NEXT: --> {%0,+,8}<%for.body.us> + +;;; The following test caused an ICE with the initial forked pointers work. +;;; One fork is loop invariant (%0 + 0), the other is an scAddExpr that +;;; contains an scAddRecExpr inside it: +;;; ((8 * (zext i32 {0,+,1}<%for.body.us> to i64)) + %0) +;;; +;;; RtCheck::insert was expecting either loop invariant or SAR, so asserted +;;; on a plain scAddExpr. For now we restrict to loop invariant or SAR +;;; forks only, but we should be able to do better. + +define void @sc_add_expr_ice(ptr %arrayidx3.i.i.us, ptr %0) { +entry: + br label %for.body.us + +for.body.us: + %indvars.iv.us1 = phi i64 [ %indvars.iv.next.us, %for.body.us ], [ 0, %entry ] + %indvars79.us = trunc i64 %indvars.iv.us1 to i32 + store double 0.000000e+00, ptr %arrayidx3.i.i.us, align 8 + %conv22.us = zext i32 %indvars79.us to i64 + %cond.in.v.us = select i1 true, i64 %conv22.us, i64 0 + %cond.in.us = getelementptr inbounds double, ptr %0, i64 %cond.in.v.us + %cond.us = load double, ptr %cond.in.us, align 8 + %indvars.iv.next.us = add nuw nsw i64 %indvars.iv.us1, 1 + %exitcond.not.us = icmp eq i64 %indvars.iv.next.us, 0 + br i1 %exitcond.not.us, label %exit, label %for.body.us + +exit: + ret void +} \ No newline at end of file