[llvm] [CodeGenPrepare] Reject select address combining if a new select's operand does not dominate it (PR #226968)
Aochang Liu via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 23:10:08 PDT 2026
https://github.com/HelloWorldU updated https://github.com/llvm/llvm-project/pull/226968
>From 761138ab248dd68b2ea96c44ed7d6f7476a650ba Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Mon, 28 Sep 2026 19:35:17 +0800
Subject: [PATCH 1/3] [CodeGenPrepare] Reject select address combining if a new
select's operand does not dominate it
When address sinking traverses a select, AddressingModeCombiner inserts
the new select at the original select's position. The addressing mode
matcher only guarantees that a combined field dominates the memory
instruction -- for example, when it reuses an IV increment as the index,
the increment may be defined after the original select in the same
block, leaving the new select using a value before its definition.
Validate the operands of every newly created select and give up the
combination if any of them does not dominate the select.
Fixes #226709
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 41 +++++++++++++++---
.../X86/sink-addrmode-select-iv.ll | 43 +++++++++++++++++++
2 files changed, 77 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-select-iv.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 3e0b8a956ca8138..b2aa918cfe6fe26 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -4161,6 +4161,10 @@ class SimplificationTracker {
unsigned countNewSelectNodes() const { return AllSelectNodes.size(); }
+ const SmallPtrSet<SelectInst *, 32> &newSelectNodes() const {
+ return AllSelectNodes;
+ }
+
void destroyNewNodes(Type *CommonType) {
// For safe erasing, replace the uses with dummy value first.
auto *Dummy = PoisonValue::get(CommonType);
@@ -4203,9 +4207,14 @@ class AddressingModeCombiner {
/// Common value among addresses
Value *CommonValue = nullptr;
+ /// Deferred getter for the dominator tree, so that it is only computed
+ /// when it is actually needed.
+ const std::function<const DominatorTree &()> getDTFn;
+
public:
- AddressingModeCombiner(const DataLayout &DL, Value *OriginalValue)
- : DL(DL), Original(OriginalValue) {}
+ AddressingModeCombiner(const DataLayout &DL, Value *OriginalValue,
+ const std::function<const DominatorTree &()> &getDTFn)
+ : DL(DL), Original(OriginalValue), getDTFn(getDTFn) {}
~AddressingModeCombiner() { eraseCommonValueIfDead(); }
@@ -4389,6 +4398,24 @@ class AddressingModeCombiner {
return nullptr;
}
+ // New selects are inserted at the original selects' positions, so their
+ // operands must be available there. The addressing mode matcher only
+ // guarantees that a combined field dominates the memory instruction (e.g.
+ // when it reuses an IV increment), which may be defined after the original
+ // select in the same block. Reject the combination if any new select would
+ // use a value that does not dominate it.
+ const DominatorTree &DT = getDTFn();
+ bool ValidSelects =
+ all_of(ST.newSelectNodes(), [&DT](const SelectInst *SI) {
+ return all_of(SI->operands(), [&DT, SI](const Value *Op) {
+ return DT.dominates(Op, SI);
+ });
+ });
+ if (!ValidSelects) {
+ ST.destroyNewNodes(CommonType);
+ return nullptr;
+ }
+
auto *Result = ST.Get(Map.find(Original)->second);
if (Result) {
NumMemoryInstsPhiCreated += ST.countNewPhiNodes() + PhiNotMatchedCount;
@@ -5916,7 +5943,11 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
// the graph are compatible.
bool PhiOrSelectSeen = false;
SmallVector<Instruction *, 16> AddrModeInsts;
- AddressingModeCombiner AddrModes(*DL, Addr);
+ // Defer the query (and possible computation of) the dom tree to point of
+ // actual use. It's expected that most address matches don't actually need
+ // the domtree.
+ auto getDTFn = [this]() -> const DominatorTree & { return getDT(); };
+ AddressingModeCombiner AddrModes(*DL, Addr, getDTFn);
TypePromotionTransaction TPT(RemovedInsts);
TypePromotionTransaction::ConstRestorationPt LastKnownGood =
TPT.getRestorationPoint();
@@ -5955,10 +5986,6 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
AddrModeInsts.clear();
std::pair<AssertingVH<GetElementPtrInst>, int64_t> LargeOffsetGEP(nullptr,
0);
- // Defer the query (and possible computation of) the dom tree to point of
- // actual use. It's expected that most address matches don't actually need
- // the domtree.
- auto getDTFn = [this]() -> const DominatorTree & { return getDT(); };
ExtAddrMode NewAddrMode = AddressingModeMatcher::Match(
V, AccessTy, AddrSpace, MemoryInst, AddrModeInsts, *TLI, *LI, getDTFn,
*TRI, InsertedInsts, PromotedInsts, TPT, LargeOffsetGEP, OptSize, PSI,
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-select-iv.ll b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-select-iv.ll
new file mode 100644
index 000000000000000..460af48dc4df0dd
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-select-iv.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes="require<profile-summary>,function(codegenprepare)" -mtriple=x86_64 < %s | FileCheck %s
+
+; Address sinking through a select may reuse an IV increment as the combined
+; index, but the increment is only guaranteed to dominate the memory
+; instruction, not the position where the new select is inserted. The
+; combination must be rejected in that case; otherwise the new select uses
+; %iv.next before its definition.
+; https://github.com/llvm/llvm-project/issues/226709
+
+define i64 @f(ptr %p, i1 %cond) {
+; CHECK-LABEL: define i64 @f(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT: [[A:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 [[IV]]
+; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[A]], i64 -8
+; CHECK-NEXT: [[C:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 -2
+; CHECK-NEXT: [[SEL:%.*]] = select i1 false, ptr [[B]], ptr [[C]]
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[SEL]], align 8
+; CHECK-NEXT: ret i64 [[V]]
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %a = getelementptr [8 x i8], ptr %p, i64 %iv
+ %b = getelementptr i8, ptr %a, i64 -8
+ %c = getelementptr [8 x i8], ptr %p, i64 -2
+ %sel = select i1 false, ptr %b, ptr %c
+ %iv.next = add i64 %iv, 1
+ br i1 %cond, label %exit, label %loop
+
+exit:
+ %v = load i64, ptr %sel, align 8
+ ret i64 %v
+}
>From aa9d17497a86b82c83e6ecd73b233dbe9419868f Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Thu, 1 Oct 2026 22:09:01 +0800
Subject: [PATCH 2/3] [CodeGenPrepare] Shorten comments
Assisted-by: Claude Opus 5.5
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index b2aa918cfe6fe26..d529694964a46e1 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -4207,8 +4207,7 @@ class AddressingModeCombiner {
/// Common value among addresses
Value *CommonValue = nullptr;
- /// Deferred getter for the dominator tree, so that it is only computed
- /// when it is actually needed.
+ /// Lazily computes the dominator tree.
const std::function<const DominatorTree &()> getDTFn;
public:
@@ -4398,12 +4397,10 @@ class AddressingModeCombiner {
return nullptr;
}
- // New selects are inserted at the original selects' positions, so their
- // operands must be available there. The addressing mode matcher only
- // guarantees that a combined field dominates the memory instruction (e.g.
- // when it reuses an IV increment), which may be defined after the original
- // select in the same block. Reject the combination if any new select would
- // use a value that does not dominate it.
+ // New selects are inserted at the original selects, but the matcher only
+ // guarantees that combined fields dominate the memory instruction (e.g. a
+ // reused IV increment). Give up if a new select uses a value that does not
+ // dominate it.
const DominatorTree &DT = getDTFn();
bool ValidSelects =
all_of(ST.newSelectNodes(), [&DT](const SelectInst *SI) {
>From c2b70f2b34c855b8c72ff69c7c18380b562dfda9 Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Fri, 2 Oct 2026 13:44:15 +0800
Subject: [PATCH 3/3] [CodeGenPrepare] Also check new phis, before MatchPhiSet
New phis can get a reused IV increment as an incoming value just like new
selects. Check that every use in the new phis and selects is dominated, and
do it before MatchPhiSet, which stops tracking the new phis it keeps, so
that rejecting the combination removes all of them.
Use a non-constant select condition in the test and add the phi cases.
Assisted-by: Claude Opus 5.5
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 30 ++--
.../X86/sink-addrmode-iv-dominance.ll | 150 ++++++++++++++++++
.../X86/sink-addrmode-select-iv.ll | 43 -----
3 files changed, 165 insertions(+), 58 deletions(-)
create mode 100644 llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-iv-dominance.ll
delete mode 100644 llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-select-iv.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index d529694964a46e1..d9521c7b7433a39 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -4390,25 +4390,25 @@ class AddressingModeCombiner {
return nullptr;
}
- // Now we'd like to match New Phi nodes to existed ones.
- unsigned PhiNotMatchedCount = 0;
- if (!MatchPhiSet(ST, AddrSinkNewPhis, PhiNotMatchedCount)) {
+ // New nodes are inserted at the original phis and selects, but the matcher
+ // only guarantees that combined fields dominate the memory instruction
+ // (e.g. a reused IV increment). Give up if a new node uses a value that
+ // does not dominate the use. Check before MatchPhiSet, which stops tracking
+ // the new phis it keeps.
+ const DominatorTree &DT = getDTFn();
+ auto UsesAreDominated = [&DT](const Instruction *I) {
+ return all_of(I->operands(),
+ [&DT](const Use &U) { return DT.dominates(U.get(), U); });
+ };
+ if (!all_of(ST.newPhiNodes(), UsesAreDominated) ||
+ !all_of(ST.newSelectNodes(), UsesAreDominated)) {
ST.destroyNewNodes(CommonType);
return nullptr;
}
- // New selects are inserted at the original selects, but the matcher only
- // guarantees that combined fields dominate the memory instruction (e.g. a
- // reused IV increment). Give up if a new select uses a value that does not
- // dominate it.
- const DominatorTree &DT = getDTFn();
- bool ValidSelects =
- all_of(ST.newSelectNodes(), [&DT](const SelectInst *SI) {
- return all_of(SI->operands(), [&DT, SI](const Value *Op) {
- return DT.dominates(Op, SI);
- });
- });
- if (!ValidSelects) {
+ // Now we'd like to match New Phi nodes to existed ones.
+ unsigned PhiNotMatchedCount = 0;
+ if (!MatchPhiSet(ST, AddrSinkNewPhis, PhiNotMatchedCount)) {
ST.destroyNewNodes(CommonType);
return nullptr;
}
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-iv-dominance.ll b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-iv-dominance.ll
new file mode 100644
index 000000000000000..46d093ca60030d5
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-iv-dominance.ll
@@ -0,0 +1,150 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes="require<profile-summary>,function(codegenprepare)" -mtriple=x86_64 -addr-sink-new-phis=true < %s | FileCheck %s
+
+; Address sinking may reuse an IV increment as the combined index, but the
+; increment is only known to dominate the memory instruction, not the new
+; phis and selects, which are inserted at the original ones. The combination
+; must be rejected in that case.
+; https://github.com/llvm/llvm-project/issues/226709
+
+define i64 @select_version(ptr %p, i1 %c0, i1 %c1) {
+; CHECK-LABEL: define i64 @select_version(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[C0:%.*]], i1 [[C1:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT: [[A:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 [[IV]]
+; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[A]], i64 -8
+; CHECK-NEXT: [[C:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 -2
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C0]], ptr [[B]], ptr [[C]]
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: br i1 [[C1]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[SEL]], align 8
+; CHECK-NEXT: ret i64 [[V]]
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %a = getelementptr [8 x i8], ptr %p, i64 %iv
+ %b = getelementptr i8, ptr %a, i64 -8
+ %c = getelementptr [8 x i8], ptr %p, i64 -2
+ %sel = select i1 %c0, ptr %b, ptr %c
+ %iv.next = add i64 %iv, 1
+ br i1 %c1, label %exit, label %loop
+
+exit:
+ %v = load i64, ptr %sel, align 8
+ ret i64 %v
+}
+
+; The new phi gets %iv.next as the incoming value from %if.then, where it is
+; not available yet.
+define i64 @phi_version(ptr %p, i1 %c0, i1 %c1) {
+; CHECK-LABEL: define i64 @phi_version(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[C0:%.*]], i1 [[C1:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ]
+; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK: [[IF_THEN]]:
+; CHECK-NEXT: [[A:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 [[IV]]
+; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[A]], i64 -8
+; CHECK-NEXT: br label %[[LATCH]]
+; CHECK: [[IF_ELSE]]:
+; CHECK-NEXT: [[C:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 -2
+; CHECK-NEXT: br label %[[LATCH]]
+; CHECK: [[LATCH]]:
+; CHECK-NEXT: [[PH:%.*]] = phi ptr [ [[B]], %[[IF_THEN]] ], [ [[C]], %[[IF_ELSE]] ]
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: br i1 [[C1]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[PH]], align 8
+; CHECK-NEXT: ret i64 [[V]]
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
+ br i1 %c0, label %if.then, label %if.else
+
+if.then:
+ %a = getelementptr [8 x i8], ptr %p, i64 %iv
+ %b = getelementptr i8, ptr %a, i64 -8
+ br label %latch
+
+if.else:
+ %c = getelementptr [8 x i8], ptr %p, i64 -2
+ br label %latch
+
+latch:
+ %ph = phi ptr [ %b, %if.then ], [ %c, %if.else ]
+ %iv.next = add i64 %iv, 1
+ br i1 %c1, label %exit, label %loop
+
+exit:
+ %v = load i64, ptr %ph, align 8
+ ret i64 %v
+}
+
+; A new phi and a new select are created together. When the combination is
+; rejected, both must be removed.
+define i64 @phi_and_select(ptr %p, i1 %c0, i1 %c1, i1 %c2) {
+; CHECK-LABEL: define i64 @phi_and_select(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ]
+; CHECK-NEXT: [[D0:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 [[IV]]
+; CHECK-NEXT: [[D:%.*]] = getelementptr i8, ptr [[D0]], i64 -8
+; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK: [[IF_THEN]]:
+; CHECK-NEXT: [[A:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 [[IV]]
+; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[A]], i64 -8
+; CHECK-NEXT: br label %[[LATCH]]
+; CHECK: [[IF_ELSE]]:
+; CHECK-NEXT: [[C:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 -2
+; CHECK-NEXT: br label %[[LATCH]]
+; CHECK: [[LATCH]]:
+; CHECK-NEXT: [[PH:%.*]] = phi ptr [ [[B]], %[[IF_THEN]] ], [ [[C]], %[[IF_ELSE]] ]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C1]], ptr [[PH]], ptr [[D]]
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: br i1 [[C2]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[SEL]], align 8
+; CHECK-NEXT: ret i64 [[V]]
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
+ %d0 = getelementptr [8 x i8], ptr %p, i64 %iv
+ %d = getelementptr i8, ptr %d0, i64 -8
+ br i1 %c0, label %if.then, label %if.else
+
+if.then:
+ %a = getelementptr [8 x i8], ptr %p, i64 %iv
+ %b = getelementptr i8, ptr %a, i64 -8
+ br label %latch
+
+if.else:
+ %c = getelementptr [8 x i8], ptr %p, i64 -2
+ br label %latch
+
+latch:
+ %ph = phi ptr [ %b, %if.then ], [ %c, %if.else ]
+ %sel = select i1 %c1, ptr %ph, ptr %d
+ %iv.next = add i64 %iv, 1
+ br i1 %c2, label %exit, label %loop
+
+exit:
+ %v = load i64, ptr %sel, align 8
+ ret i64 %v
+}
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-select-iv.ll b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-select-iv.ll
deleted file mode 100644
index 460af48dc4df0dd..000000000000000
--- a/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-select-iv.ll
+++ /dev/null
@@ -1,43 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -S -passes="require<profile-summary>,function(codegenprepare)" -mtriple=x86_64 < %s | FileCheck %s
-
-; Address sinking through a select may reuse an IV increment as the combined
-; index, but the increment is only guaranteed to dominate the memory
-; instruction, not the position where the new select is inserted. The
-; combination must be rejected in that case; otherwise the new select uses
-; %iv.next before its definition.
-; https://github.com/llvm/llvm-project/issues/226709
-
-define i64 @f(ptr %p, i1 %cond) {
-; CHECK-LABEL: define i64 @f(
-; CHECK-SAME: ptr [[P:%.*]], i1 [[COND:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: br label %[[LOOP:.*]]
-; CHECK: [[LOOP]]:
-; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT: [[A:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 [[IV]]
-; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[A]], i64 -8
-; CHECK-NEXT: [[C:%.*]] = getelementptr [8 x i8], ptr [[P]], i64 -2
-; CHECK-NEXT: [[SEL:%.*]] = select i1 false, ptr [[B]], ptr [[C]]
-; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
-; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]
-; CHECK: [[EXIT]]:
-; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[SEL]], align 8
-; CHECK-NEXT: ret i64 [[V]]
-;
-entry:
- br label %loop
-
-loop:
- %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
- %a = getelementptr [8 x i8], ptr %p, i64 %iv
- %b = getelementptr i8, ptr %a, i64 -8
- %c = getelementptr [8 x i8], ptr %p, i64 -2
- %sel = select i1 false, ptr %b, ptr %c
- %iv.next = add i64 %iv, 1
- br i1 %cond, label %exit, label %loop
-
-exit:
- %v = load i64, ptr %sel, align 8
- ret i64 %v
-}
More information about the llvm-commits
mailing list