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 @@ -825,6 +825,17 @@ return S.second; }; + auto GetBinOpExpr = [&SE](unsigned Opcode, const SCEV *L, const SCEV *R) { + switch (Opcode) { + case Instruction::Add: + return SE->getAddExpr(L, R); + case Instruction::Sub: + return SE->getMinusSCEV(L, R); + default: + llvm_unreachable("Unexpected binary operator when walking ForkedPtrs"); + } + }; + Instruction *I = cast(Ptr); unsigned Opcode = I->getOpcode(); switch (Opcode) { @@ -894,6 +905,35 @@ std::make_pair(Scev, !isGuaranteedNotToBeUndefOrPoison(Ptr))); break; } + case Instruction::Add: + case Instruction::Sub: { + SmallVector> LScevs; + SmallVector> RScevs; + findForkedSCEVs(SE, L, I->getOperand(0), LScevs, Depth); + findForkedSCEVs(SE, L, I->getOperand(1), RScevs, Depth); + + // See if we need to freeze our fork... + bool NeedsFreeze = + any_of(LScevs, UndefPoisonCheck) || any_of(RScevs, UndefPoisonCheck); + + // Check that we only have a single fork, on either the left or right side. + // Copy the SCEV across for the one without a fork in order to generate + // the full SCEV for both sides of the BinOp. + if (LScevs.size() == 2 && RScevs.size() == 1) + RScevs.push_back(RScevs[0]); + else if (RScevs.size() == 2 && LScevs.size() == 1) + LScevs.push_back(LScevs[0]); + else { + ScevList.push_back(std::make_pair(Scev, NeedsFreeze)); + break; + } + + ScevList.push_back(std::make_pair( + GetBinOpExpr(Opcode, LScevs[0].first, RScevs[0].first), NeedsFreeze)); + ScevList.push_back(std::make_pair( + GetBinOpExpr(Opcode, LScevs[1].first, RScevs[1].first), NeedsFreeze)); + break; + } default: // Just return the current SCEV if we haven't handled the instruction yet. LLVM_DEBUG(dbgs() << "ForkedPtr unhandled instruction: " << *I << "\n"); diff --git a/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll b/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll --- a/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll @@ -448,10 +448,31 @@ ; CHECK-LABEL: function 'forked_ptrs_add_to_offset' ; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: cannot identify array bounds +; 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: %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv +; 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: %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: (Low: %Dest High: (400 + %Dest)) +; CHECK-NEXT: Member: {%Dest,+,4}<%for.body> +; CHECK-NEXT: Group [[G2]]: +; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) +; CHECK-NEXT: Member: {%Preds,+,4}<%for.body> +; CHECK-NEXT: Group [[G3]]: +; CHECK-NEXT: (Low: ((4 * %extra_offset) + %Base) High: (404 + (4 * %extra_offset) + %Base)) +; CHECK-NEXT: Member: {(4 + (4 * %extra_offset) + %Base),+,4}<%for.body> +; CHECK-NEXT: Member: {((4 * %extra_offset) + %Base),+,4}<%for.body> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: @@ -483,10 +504,31 @@ ; CHECK-LABEL: function 'forked_ptrs_sub_from_offset' ; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: cannot identify array bounds +; 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: %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv +; 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: %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: (Low: %Dest High: (400 + %Dest)) +; CHECK-NEXT: Member: {%Dest,+,4}<%for.body> +; CHECK-NEXT: Group [[G2]]: +; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) +; CHECK-NEXT: Member: {%Preds,+,4}<%for.body> +; CHECK-NEXT: Group [[G3]]: +; CHECK-NEXT: (Low: ((-4 * %extra_offset) + %Base) High: (404 + (-4 * %extra_offset) + %Base)) +; CHECK-NEXT: Member: {(4 + (-4 * %extra_offset) + %Base),+,4}<%for.body> +; CHECK-NEXT: Member: {((-4 * %extra_offset) + %Base),+,4}<%for.body> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: @@ -518,10 +560,31 @@ ; CHECK-LABEL: function 'forked_ptrs_add_sub_offset' ; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: cannot identify array bounds +; 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: %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv +; 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: %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: (Low: %Dest High: (400 + %Dest)) +; CHECK-NEXT: Member: {%Dest,+,4}<%for.body> +; CHECK-NEXT: Group [[G2]]: +; CHECK-NEXT: (Low: %Preds High: (400 + %Preds)) +; CHECK-NEXT: Member: {%Preds,+,4}<%for.body> +; CHECK-NEXT: Group [[G3]]: +; CHECK-NEXT: (Low: ((4 * %to_add) + (-4 * %to_sub) + %Base) High: (404 + (4 * %to_add) + (-4 * %to_sub) + %Base)) +; CHECK-NEXT: Member: {(4 + (4 * %to_add) + (-4 * %to_sub) + %Base),+,4}<%for.body> +; CHECK-NEXT: Member: {((4 * %to_add) + (-4 * %to_sub) + %Base),+,4}<%for.body> ; CHECK-EMPTY: ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. ; CHECK-NEXT: SCEV assumptions: