[llvm-branch-commits] [llvm] [LoopInterchange] Take base pointer into account in profitability check (PR #193477)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 22 05:21:13 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Ryotaro Kasuga (kasuga-fj)
<details>
<summary>Changes</summary>
Currently `getInstrOrderCost` doesn't check the base pointers of the accesses, which can lead to undesirable profitability decisions. This patch makes the function take the base pointers into account. Fix the test case added in #<!-- -->193476.
---
Full diff: https://github.com/llvm/llvm-project/pull/193477.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/LoopInterchange.cpp (+18-7)
- (modified) llvm/test/Transforms/LoopInterchange/profitability-instorder.ll (+7-17)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
index 5094d18501354..b5989b32b2e5f 100644
--- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
@@ -1589,17 +1589,19 @@ std::optional<const SCEV *> getAddRecCoefficient(ScalarEvolution &SE,
}
int LoopInterchangeProfitability::getInstrOrderCost() {
- unsigned GoodOrder, BadOrder;
- BadOrder = GoodOrder = 0;
+ // Map from the base pointer fo an acess to a pair of booleans indicating
+ // whether we find good or bad order.
+ DenseMap<const SCEV *, std::pair<bool, bool>> BasePtr2Score;
for (BasicBlock *BB : InnerLoop->blocks()) {
for (Instruction &Ins : *BB) {
if (!isa<LoadInst, StoreInst>(&Ins))
continue;
- const SCEV *Ptr = SE->getSCEV(getLoadStorePointerOperand(&Ins));
+ const SCEV *Access = SE->getSCEV(getLoadStorePointerOperand(&Ins));
+ const SCEV *BasePtr = SE->getPointerBase(Access);
std::optional<const SCEV *> OuterCoeff =
- getAddRecCoefficient(*SE, Ptr, OuterLoop);
+ getAddRecCoefficient(*SE, Access, OuterLoop);
std::optional<const SCEV *> InnerCoeff =
- getAddRecCoefficient(*SE, Ptr, InnerLoop);
+ getAddRecCoefficient(*SE, Access, InnerLoop);
if (!OuterCoeff.has_value() || !*OuterCoeff || !InnerCoeff.has_value() ||
!*InnerCoeff)
@@ -1619,7 +1621,7 @@ int LoopInterchangeProfitability::getInstrOrderCost() {
// for(int j=0;j<N;j++)
// A[i][j] = A[i-1][j-1]+k;
// then it is a good order.
- GoodOrder++;
+ BasePtr2Score[BasePtr].first = true;
} else if (SE->isKnownPredicate(ICmpInst::ICMP_SLT, OuterStep,
InnerStep)) {
// If we find the outer induction after an inner induction e.g.
@@ -1627,10 +1629,19 @@ int LoopInterchangeProfitability::getInstrOrderCost() {
// for(int j=0;j<N;j++)
// A[j][i] = A[j-1][i-1]+k;
// then it is a bad order.
- BadOrder++;
+ BasePtr2Score[BasePtr].second = true;
}
}
}
+
+ int GoodOrder = 0, BadOrder = 0;
+ for (const auto &[BasePtr, Score] : BasePtr2Score) {
+ auto [Good, Bad] = Score;
+ if (Good)
+ GoodOrder++;
+ if (Bad)
+ BadOrder++;
+ }
return GoodOrder - BadOrder;
}
diff --git a/llvm/test/Transforms/LoopInterchange/profitability-instorder.ll b/llvm/test/Transforms/LoopInterchange/profitability-instorder.ll
index 92d56b98e2591..9c192a85b5781 100644
--- a/llvm/test/Transforms/LoopInterchange/profitability-instorder.ll
+++ b/llvm/test/Transforms/LoopInterchange/profitability-instorder.ll
@@ -198,19 +198,13 @@ exit:
define void @unprofitable1(ptr noalias %A, ptr noalias %B, ptr noalias %C) {
; CHECK-LABEL: define void @unprofitable1(
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: br label %[[LOOP_J_PREHEADER:.*]]
-; CHECK: [[LOOP_I_HEADER_PREHEADER:.*]]:
-; CHECK-NEXT: br label %[[LOOP_I_HEADER:.*]]
-; CHECK: [[LOOP_I_HEADER]]:
-; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_INC:%.*]], %[[LOOP_I_LATCH:.*]] ], [ 0, %[[LOOP_I_HEADER_PREHEADER]] ]
-; CHECK-NEXT: br label %[[LOOP_J_SPLIT1:.*]]
-; CHECK: [[LOOP_J_PREHEADER]]:
+; CHECK-NEXT: [[LOOP_J_PREHEADER:.*]]:
; CHECK-NEXT: br label %[[LOOP_J:.*]]
; CHECK: [[LOOP_J]]:
-; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[TMP0:%.*]], %[[LOOP_J_SPLIT:.*]] ], [ 0, %[[LOOP_J_PREHEADER]] ]
-; CHECK-NEXT: br label %[[LOOP_I_HEADER_PREHEADER]]
-; CHECK: [[LOOP_J_SPLIT1]]:
+; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, %[[LOOP_J_PREHEADER]] ], [ [[I_INC:%.*]], %[[LOOP_I_LATCH:.*]] ]
+; CHECK-NEXT: br label %[[LOOP_I_HEADER_PREHEADER:.*]]
+; CHECK: [[LOOP_I_HEADER_PREHEADER]]:
+; CHECK-NEXT: [[J:%.*]] = phi i64 [ 0, %[[LOOP_J]] ], [ [[TMP0:%.*]], %[[LOOP_I_HEADER_PREHEADER]] ]
; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds [100 x i8], ptr [[A]], i64 [[I]], i64 [[J]]
; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds [100 x i8], ptr [[B]], i64 [[I]], i64 [[J]]
; CHECK-NEXT: [[GEP_C0:%.*]] = getelementptr inbounds [100 x i8], ptr [[C]], i64 [[J]], i64 [[I]]
@@ -224,17 +218,13 @@ define void @unprofitable1(ptr noalias %A, ptr noalias %B, ptr noalias %C) {
; CHECK-NEXT: [[SUM_1:%.*]] = add i8 [[SUM_0]], [[VAL_C1]]
; CHECK-NEXT: [[SUM_2:%.*]] = add i8 [[SUM_1]], [[VAL_C2]]
; CHECK-NEXT: store i8 [[SUM_2]], ptr [[GEP_A]], align 1
-; CHECK-NEXT: [[J_INC:%.*]] = add i64 [[J]], 1
-; CHECK-NEXT: [[EC_J:%.*]] = icmp eq i64 [[J_INC]], 10
-; CHECK-NEXT: br label %[[LOOP_I_LATCH]]
-; CHECK: [[LOOP_J_SPLIT]]:
; CHECK-NEXT: [[TMP0]] = add i64 [[J]], 1
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 10
-; CHECK-NEXT: br i1 [[TMP1]], label %[[EXIT:.*]], label %[[LOOP_J]]
+; CHECK-NEXT: br i1 [[TMP1]], label %[[LOOP_I_LATCH]], label %[[LOOP_I_HEADER_PREHEADER]]
; CHECK: [[LOOP_I_LATCH]]:
; CHECK-NEXT: [[I_INC]] = add i64 [[I]], 1
; CHECK-NEXT: [[EC_I:%.*]] = icmp eq i64 [[I_INC]], 10
-; CHECK-NEXT: br i1 [[EC_I]], label %[[LOOP_J_SPLIT]], label %[[LOOP_I_HEADER]]
+; CHECK-NEXT: br i1 [[EC_I]], label %[[EXIT:.*]], label %[[LOOP_J]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
``````````
</details>
https://github.com/llvm/llvm-project/pull/193477
More information about the llvm-branch-commits
mailing list