[llvm] [SCEVExpander] Do not insert after callbr (PR #201322)
Le Gia Bao via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 6 14:24:32 PDT 2026
https://github.com/L3GiaBao updated https://github.com/llvm/llvm-project/pull/201322
>From 4ae5444c202819cb37211e94f4969c2aee137828 Mon Sep 17 00:00:00 2001
From: Le Gia Bao <legiabao7300 at gmail.com>
Date: Wed, 3 Jun 2026 07:08:18 -0400
Subject: [PATCH 1/2] [SCEVExpander] Do not insert after callbr
---
.../Transforms/Utils/ScalarEvolutionExpander.cpp | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index 39da38e491817..d21fb4339b664 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -147,9 +147,18 @@ Value *SCEVExpander::ReuseOrCreateCast(Value *V, Type *Ty,
BasicBlock::iterator
SCEVExpander::findInsertPointAfter(Instruction *I,
Instruction *MustDominate) const {
- BasicBlock::iterator IP = ++I->getIterator();
- if (auto *II = dyn_cast<InvokeInst>(I))
+ BasicBlock::iterator IP;
+ if (auto *II = dyn_cast<InvokeInst>(I)) {
IP = II->getNormalDest()->begin();
+ } else if (isa<CallBrInst>(I)) {
+ // callbr is a terminator, so there is no valid same-block point after it.
+ // Use the point we need the result to dominate.
+ assert(SE.DT.dominates(I, MustDominate) &&
+ "callbr result must dominate the insertion point");
+ IP = MustDominate->getIterator();
+ } else {
+ IP = ++I->getIterator();
+ }
while (isa<PHINode>(IP))
++IP;
>From bcdcf9a8a94acab1645a07335b5f85e286f1e79e Mon Sep 17 00:00:00 2001
From: Le Gia Bao <legiabao7300 at gmail.com>
Date: Sat, 6 Jun 2026 17:24:18 -0400
Subject: [PATCH 2/2] Add test file and cleanup
---
.../Utils/ScalarEvolutionExpander.cpp | 32 +++++------
llvm/test/Transforms/IndVarSimplify/callbr.ll | 53 +++++++++++++++++++
2 files changed, 65 insertions(+), 20 deletions(-)
create mode 100644 llvm/test/Transforms/IndVarSimplify/callbr.ll
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index d21fb4339b664..97d0bedddfce8 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -148,27 +148,19 @@ BasicBlock::iterator
SCEVExpander::findInsertPointAfter(Instruction *I,
Instruction *MustDominate) const {
BasicBlock::iterator IP;
- if (auto *II = dyn_cast<InvokeInst>(I)) {
- IP = II->getNormalDest()->begin();
- } else if (isa<CallBrInst>(I)) {
- // callbr is a terminator, so there is no valid same-block point after it.
- // Use the point we need the result to dominate.
- assert(SE.DT.dominates(I, MustDominate) &&
- "callbr result must dominate the insertion point");
- IP = MustDominate->getIterator();
- } else {
- IP = ++I->getIterator();
- }
-
- while (isa<PHINode>(IP))
- ++IP;
-
- if (isa<FuncletPadInst>(IP) || isa<LandingPadInst>(IP)) {
- ++IP;
- } else if (isa<CatchSwitchInst>(IP)) {
- IP = MustDominate->getParent()->getFirstInsertionPt();
+ if (auto MaybeIP = I->getInsertionPointAfterDef()) {
+ IP = *MaybeIP;
} else {
- assert(!IP->isEHPad() && "unexpected eh pad!");
+ assert(SE.DT.dominates(I, MustDominate) &&
+ "instruction must dominate the insertion point");
+ if (isa<CallBrInst>(I)) {
+ // Def is available in multiple successors, so use the point that needs
+ // to be dominated.
+ IP = MustDominate->getIterator();
+ } else {
+ // catchswitch blocks don't have any legal insertion point.
+ IP = MustDominate->getParent()->getFirstInsertionPt();
+ }
}
// Adjust insert point to be after instructions inserted by the expander, so
diff --git a/llvm/test/Transforms/IndVarSimplify/callbr.ll b/llvm/test/Transforms/IndVarSimplify/callbr.ll
new file mode 100644
index 0000000000000..eb545fa3be236
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/callbr.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=indvars < %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+
+define ptr @callbr_result_exit_value(ptr %a0) {
+; CHECK-LABEL: define ptr @callbr_result_exit_value(
+; CHECK-SAME: ptr [[A0:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[A02:%.*]] = ptrtoint ptr [[A0]] to i64
+; CHECK-NEXT: [[OUT:%.*]] = callbr ptr asm "", "=r,!i"()
+; CHECK-NEXT: to label %[[D:.*]] [label %indirect]
+; CHECK: [[INDIRECT:.*:]]
+; CHECK-NEXT: ret ptr null
+; CHECK: [[D]]:
+; CHECK-NEXT: [[CMP0:%.*]] = icmp eq ptr [[A0]], [[OUT]]
+; CHECK-NEXT: br i1 [[CMP0]], label %[[END:.*]], label %[[LOOP_PREHEADER:.*]]
+; CHECK: [[LOOP_PREHEADER]]:
+; CHECK-NEXT: [[OUT1:%.*]] = ptrtoint ptr [[OUT]] to i64
+; CHECK-NEXT: [[TMP4:%.*]] = sub i64 [[OUT1]], [[A02]]
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A0]], i64 [[TMP4]]
+; CHECK-NEXT: ret ptr [[SCEVGEP]]
+; CHECK: [[END]]:
+; CHECK-NEXT: ret ptr [[A0]]
+;
+entry:
+ %out = callbr ptr asm "", "=r,!i"()
+ to label %d [label %indirect]
+
+indirect:
+ ret ptr null
+
+d:
+ %cmp0 = icmp eq ptr %a0, %out
+ br i1 %cmp0, label %end, label %loop
+
+loop:
+ %iv = phi ptr [ %a0, %d ], [ %inc, %loop ]
+ %inc = getelementptr inbounds i8, ptr %iv, i64 1
+ %cmp = icmp eq ptr %inc, %out
+ br i1 %cmp, label %exit, label %loop
+
+exit:
+ %lcssa = phi ptr [ %inc, %loop ]
+ ret ptr %lcssa
+
+end:
+ ret ptr %a0
+}
More information about the llvm-commits
mailing list