[llvm-branch-commits] [llvm] [LoopInterchange] Take base pointer into account in profitability check (PR #193477)
Ryotaro Kasuga via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu May 21 03:57:25 PDT 2026
https://github.com/kasuga-fj updated https://github.com/llvm/llvm-project/pull/193477
>From 6a9a4e790a73a14f8255345ed0ac899abc826ee7 Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Wed, 22 Apr 2026 10:32:00 +0000
Subject: [PATCH 1/2] [LoopInterchange] Take base pointer into account in
profitability check
---
.../lib/Transforms/Scalar/LoopInterchange.cpp | 25 +++++++++++++------
.../profitability-instorder.ll | 24 ++++++------------
2 files changed, 25 insertions(+), 24 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
index 35d2716f74dd7..48fb0836c4d7d 100644
--- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
@@ -1640,17 +1640,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)
@@ -1680,11 +1682,20 @@ int LoopInterchangeProfitability::getInstrOrderCost() {
//
// then it is a bad order.
if (SE->isKnownPredicate(ICmpInst::ICMP_SLT, InnerStep, OuterStep))
- GoodOrder++;
+ BasePtr2Score[BasePtr].first = true;
else if (SE->isKnownPredicate(ICmpInst::ICMP_SLT, OuterStep, InnerStep))
- 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 9479eaa00a1f0..c69a75c63e2da 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]], 42
-; 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]], 42
-; 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]], 42
-; 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
;
>From fbd8a187e8306171a28d38f55ed1148c97ab2cc0 Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Tue, 19 May 2026 12:04:10 +0000
Subject: [PATCH 2/2] update impl
---
llvm/lib/Transforms/Scalar/LoopInterchange.cpp | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
index 48fb0836c4d7d..bd09ca12f338a 100644
--- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
@@ -1640,9 +1640,7 @@ std::optional<const SCEV *> getAddRecCoefficient(ScalarEvolution &SE,
}
int LoopInterchangeProfitability::getInstrOrderCost() {
- // 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;
+ SmallPtrSet<const SCEV *, 4> GoodBasePtrs, BadBasePtrs;
for (BasicBlock *BB : InnerLoop->blocks()) {
for (Instruction &Ins : *BB) {
if (!isa<LoadInst, StoreInst>(&Ins))
@@ -1682,20 +1680,14 @@ int LoopInterchangeProfitability::getInstrOrderCost() {
//
// then it is a bad order.
if (SE->isKnownPredicate(ICmpInst::ICMP_SLT, InnerStep, OuterStep))
- BasePtr2Score[BasePtr].first = true;
+ GoodBasePtrs.insert(BasePtr);
else if (SE->isKnownPredicate(ICmpInst::ICMP_SLT, OuterStep, InnerStep))
- BasePtr2Score[BasePtr].second = true;
+ BadBasePtrs.insert(BasePtr);
}
}
- int GoodOrder = 0, BadOrder = 0;
- for (const auto &[BasePtr, Score] : BasePtr2Score) {
- auto [Good, Bad] = Score;
- if (Good)
- GoodOrder++;
- if (Bad)
- BadOrder++;
- }
+ int GoodOrder = GoodBasePtrs.size();
+ int BadOrder = BadBasePtrs.size();
return GoodOrder - BadOrder;
}
More information about the llvm-branch-commits
mailing list