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<Instruction>(Ptr);
unsigned Opcode = I->getOpcode();
switch (Opcode) {
std::make_pair(Scev, !isGuaranteedNotToBeUndefOrPoison(Ptr)));
break;
}
+ case Instruction::Add:
+ case Instruction::Sub: {
+ SmallVector<std::pair<const SCEV *, bool>> LScevs;
+ SmallVector<std::pair<const SCEV *, bool>> 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");
; 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}<nuw><%for.body>
+; CHECK-NEXT: Group [[G2]]:
+; CHECK-NEXT: (Low: %Preds High: (400 + %Preds))
+; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%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:
; 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}<nuw><%for.body>
+; CHECK-NEXT: Group [[G2]]:
+; CHECK-NEXT: (Low: %Preds High: (400 + %Preds))
+; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%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:
; 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}<nuw><%for.body>
+; CHECK-NEXT: Group [[G2]]:
+; CHECK-NEXT: (Low: %Preds High: (400 + %Preds))
+; CHECK-NEXT: Member: {%Preds,+,4}<nuw><%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: