[llvm] 70d3544 - [LAA] Handle forked pointers with add/sub instructions
Graham Hunter via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 17 01:52:26 PDT 2022
Author: Graham Hunter
Date: 2022-08-17T09:51:13+01:00
New Revision: 70d35443dc8f7e4310f5be6362fd12eac35558e8
URL: https://github.com/llvm/llvm-project/commit/70d35443dc8f7e4310f5be6362fd12eac35558e8
DIFF: https://github.com/llvm/llvm-project/commit/70d35443dc8f7e4310f5be6362fd12eac35558e8.diff
LOG: [LAA] Handle forked pointers with add/sub instructions
Handle cases where a forked pointer has an add or sub instruction
before reaching a select.
Reviewed By: fhahn
Reviewed By: paulwalker-arm
Differential Revision: https://reviews.llvm.org/D130278
Added:
Modified:
llvm/lib/Analysis/LoopAccessAnalysis.cpp
llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 547e9a8123054..8b5513b4e75fc 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -825,6 +825,17 @@ findForkedSCEVs(ScalarEvolution *SE, const Loop *L, Value *Ptr,
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) {
@@ -894,6 +905,35 @@ findForkedSCEVs(ScalarEvolution *SE, const Loop *L, Value *Ptr,
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");
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll b/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
index 84385719a2b70..332a29457e486 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll
@@ -448,10 +448,31 @@ for.body: ; preds = %entry, %for.body
; 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:
@@ -483,10 +504,31 @@ for.body: ; preds = %entry, %for.body
; 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:
@@ -518,10 +560,31 @@ for.body: ; preds = %entry, %for.body
; 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:
More information about the llvm-commits
mailing list