[llvm] [SimplifyCFG] Fold pairs of entries in multiple-entry phi (PR #73674)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 29 04:49:02 PST 2023
https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/73674
>From f484fcbccb90db42573314aefec5583a1252fb95 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Nov 2023 21:21:41 +0800
Subject: [PATCH 1/3] [SimplifyCFG][NFC] Precommit tests for folding multiple
entry phi
---
.../SimplifyCFG/fold-multiple-entry-phi.ll | 226 ++++++++++++++++++
1 file changed, 226 insertions(+)
create mode 100644 llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
diff --git a/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll b/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
new file mode 100644
index 000000000000000..c86f20164ebc525
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
@@ -0,0 +1,226 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -two-entry-phi-node-folding-threshold=4 -phi-node-folding-threshold=0 < %s | FileCheck %s
+
+define i32 @three_entry_test(i32 %x, i32 %y, i1 %cond){
+; CHECK-LABEL: define i32 @three_entry_test(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[COND]], label [[END:%.*]], label [[THEN:%.*]]
+; CHECK: then:
+; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP]], label [[END]], label [[B:%.*]]
+; CHECK: b:
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: br label [[END]]
+; CHECK: end:
+; CHECK-NEXT: [[RET_0:%.*]] = phi i32 [ [[SUB]], [[THEN]] ], [ [[ADD]], [[B]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RET_0]]
+;
+entry:
+ br i1 %cond, label %if.then, label %then
+
+if.then:
+ br label %end
+
+then:
+ %sub = add i32 %x, -1
+ %cmp = icmp sgt i32 %x, %y
+ br i1 %cmp, label %end, label %b
+
+b:
+ %add = add i32 %x, 1
+ br label %end
+
+end:
+ %ret.0 = phi i32 [ 0, %if.then ], [ %sub, %then ], [ %add, %b ]
+ ret i32 %ret.0
+}
+
+define i32 @three_entry_test_diamond(i32 %x, i32 %y, i1 %cond){
+; CHECK-LABEL: define i32 @three_entry_test_diamond(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[COND]], label [[END:%.*]], label [[THEN:%.*]]
+; CHECK: then:
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP]], label [[B1:%.*]], label [[B2:%.*]]
+; CHECK: b1:
+; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT: br label [[END]]
+; CHECK: b2:
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: br label [[END]]
+; CHECK: end:
+; CHECK-NEXT: [[RET_0:%.*]] = phi i32 [ [[SUB]], [[B1]] ], [ [[ADD]], [[B2]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[RET_0]]
+;
+entry:
+ br i1 %cond, label %if.then, label %then
+
+if.then:
+ br label %end
+
+then:
+ %cmp = icmp sgt i32 %x, %y
+ br i1 %cmp, label %b1, label %b2
+
+b1:
+ %sub = add i32 %x, -1
+ br label %end
+
+b2:
+ %add = add i32 %x, 1
+ br label %end
+
+end:
+ %ret.0 = phi i32 [ 0, %if.then ], [ %sub, %b1 ], [ %add, %b2 ]
+ ret i32 %ret.0
+}
+
+
+
+define i32 @four_entry_test(i32 %x, i32 %y, i1 %cond, i1 %cond1){
+; CHECK-LABEL: define i32 @four_entry_test(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]], i1 [[COND1:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[THEN1:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: br i1 [[COND1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK: then:
+; CHECK-NEXT: br label [[END]]
+; CHECK: then1:
+; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP1]], label [[END]], label [[B:%.*]]
+; CHECK: b:
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: br label [[END]]
+; CHECK: end:
+; CHECK-NEXT: [[RET_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ 1, [[THEN]] ], [ [[SUB]], [[THEN1]] ], [ [[ADD]], [[B]] ]
+; CHECK-NEXT: ret i32 [[RET_0]]
+;
+entry:
+ br i1 %cond, label %if.then, label %then1
+
+if.then:
+ br i1 %cond1, label %then, label %end
+
+then:
+ br label %end
+
+then1:
+ %sub = add i32 %x, -1
+ %cmp1 = icmp sgt i32 %x, %y
+ br i1 %cmp1, label %end, label %b
+
+b:
+ %add = add i32 %x, 1
+ br label %end
+
+end:
+ %ret.0 = phi i32 [ 0, %if.then ], [1, %then], [ %sub, %then1 ], [ %add, %b ]
+ ret i32 %ret.0
+}
+
+declare i32 @dummy()
+
+define i32 @three_entry_test_multiple_dests_fail(i32 %x, i32 %y, i1 %cond, i1 %cond1){
+; CHECK-LABEL: define i32 @three_entry_test_multiple_dests_fail(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]], i1 [[COND1:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[COND]], label [[COMMON_RET:%.*]], label [[THEN:%.*]]
+; CHECK: then:
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP]], label [[B1:%.*]], label [[B2:%.*]]
+; CHECK: b1:
+; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT: br label [[COMMON_RET]]
+; CHECK: b2:
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: br i1 [[COND1]], label [[END:%.*]], label [[COMMON_RET]]
+; CHECK: common.ret:
+; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[CALL:%.*]], [[END]] ], [ [[SUB]], [[B1]] ], [ [[ADD]], [[B2]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
+; CHECK: end:
+; CHECK-NEXT: [[CALL]] = call i32 @dummy()
+; CHECK-NEXT: br label [[COMMON_RET]]
+;
+entry:
+ br i1 %cond, label %if.then, label %then
+
+if.then:
+ br label %end1
+
+then:
+ %cmp = icmp sgt i32 %x, %y
+ br i1 %cmp, label %b1, label %b2
+
+b1:
+ %sub = add i32 %x, -1
+ br label %end1
+
+b2:
+ %add = add i32 %x, 1
+ br i1 %cond1, label %end, label %end1
+
+end:
+ %call = call i32 @dummy()
+ ret i32 %call
+
+end1:
+ %ret.0 = phi i32 [ 0, %if.then ], [ %sub, %b1 ], [%add, %b2]
+ ret i32 %ret.0
+}
+
+declare i32 @dummy1()
+define i32 @three_entry_test_different_dest(i32 %x, i32 %y, i1 %cond, i1 %cond1){
+; CHECK-LABEL: define i32 @three_entry_test_different_dest(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]], i1 [[COND1:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[COND]], label [[END1:%.*]], label [[THEN:%.*]]
+; CHECK: then:
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: br i1 [[CMP]], label [[B1:%.*]], label [[B2:%.*]]
+; CHECK: b1:
+; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT: br label [[END1]]
+; CHECK: b2:
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: [[CALL:%.*]] = call i32 @dummy()
+; CHECK-NEXT: br label [[COMMON_RET:%.*]]
+; CHECK: common.ret:
+; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[CALL]], [[B2]] ], [ [[RET_0:%.*]], [[END1]] ]
+; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
+; CHECK: end1:
+; CHECK-NEXT: [[RET_0]] = phi i32 [ [[SUB]], [[B1]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[CALL1:%.*]] = call i32 @dummy1()
+; CHECK-NEXT: br label [[COMMON_RET]]
+;
+entry:
+ br i1 %cond, label %if.then, label %then
+
+if.then:
+ br label %end1
+
+then:
+ %cmp = icmp sgt i32 %x, %y
+ br i1 %cmp, label %b1, label %b2
+
+b1:
+ %sub = add i32 %x, -1
+ br label %end1
+
+b2:
+ %add = add i32 %x, 1
+ br label %end
+
+end:
+ %call = call i32 @dummy()
+ ret i32 %call
+
+end1:
+ %ret.0 = phi i32 [ 0, %if.then ], [ %sub, %b1 ]
+ %call1 = call i32 @dummy1()
+ ret i32 %ret.0
+}
>From be735d288e8a52620a4321e99585f7ef0dee72bf Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Nov 2023 22:37:54 +0800
Subject: [PATCH 2/3] [SimplifyCFG] Refactor logic of FoldTwoEntryPHINode
---
.../llvm/Transforms/Utils/BasicBlockUtils.h | 14 ++-
llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | 43 ++++++-
llvm/lib/Transforms/Utils/FlattenCFG.cpp | 4 +-
llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 105 ++++++++++++------
.../Transforms/SimplifyCFG/PhiEliminate2.ll | 33 +++---
5 files changed, 143 insertions(+), 56 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index e6dde450b7df9c8..998acbe9ab75da7 100644
--- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -595,9 +595,21 @@ void SplitBlockAndInsertForEachLane(
///
/// This does no checking to see if the true/false blocks have large or unsavory
/// instructions in them.
-BranchInst *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
+BranchInst *GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
BasicBlock *&IfFalse);
+/// Check whether BB is the dominant point of a if-region.
+/// If so, return the merge point of the if-region. Also, return by references
+/// the block that will be entered from if the condition is true, and the block
+/// that will be entered if the condition is false.
+///
+/// This does no checking to see if the true/false blocks have large or unsavory
+/// instructions in them.
+///
+/// NOTE: we assume that the terminator of DomBB is a conditional branch instruction.
+BasicBlock *GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
+ BasicBlock *&IfFalse);
+
// Split critical edges where the source of the edge is an indirectbr
// instruction. This isn't always possible, but we can handle some easy cases.
// This is useful because MI is unable to split such critical edges,
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 168998fbee114ab..d43a5f72846f72c 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -1727,7 +1727,7 @@ void llvm::SplitBlockAndInsertForEachLane(
}
}
-BranchInst *llvm::GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
+BranchInst *llvm::GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
BasicBlock *&IfFalse) {
PHINode *SomePHI = dyn_cast<PHINode>(BB->begin());
BasicBlock *Pred1 = nullptr;
@@ -1819,6 +1819,47 @@ BranchInst *llvm::GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
return BI;
}
+BasicBlock *llvm::GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
+ BasicBlock *&IfFalse) {
+ BranchInst* BI = cast<BranchInst>(DomBB->getTerminator());
+ BasicBlock *Succ1 = BI->getSuccessor(0);
+ BasicBlock *Succ2 = BI->getSuccessor(1);
+
+ if (!Succ1->getSinglePredecessor() || !Succ2->getSinglePredecessor() ||
+ Succ1 == Succ2 || Succ1 == DomBB || Succ2 == DomBB)
+ return nullptr;
+
+ // We can only handle branches. Other control flow will be lowered to
+ // branches if possible anyway.
+ BranchInst *Succ1Br = dyn_cast<BranchInst>(Succ1->getTerminator());
+ BranchInst *Succ2Br = dyn_cast<BranchInst>(Succ2->getTerminator());
+ if (!Succ1Br || !Succ2Br)
+ return nullptr;
+
+ if (Succ1->getSingleSuccessor() == Succ2) {
+ IfTrue = Succ1;
+ IfFalse = DomBB;
+ return Succ2;
+ }
+
+ if (Succ2->getSingleSuccessor() == Succ1) {
+ IfTrue = DomBB;
+ IfFalse = Succ2;
+ return Succ1;
+ }
+
+ auto *CommonDest = Succ1->getSingleSuccessor();
+ if (CommonDest && CommonDest != DomBB &&
+ CommonDest == Succ2->getSingleSuccessor()) {
+ IfTrue = Succ1;
+ IfFalse = Succ2;
+ return CommonDest;
+ }
+
+ // There may be other cases, but we just handle the trivial ones now.
+ return nullptr;
+}
+
// After creating a control flow hub, the operands of PHINodes in an outgoing
// block Out no longer match the predecessors of that block. Predecessors of Out
// that are incoming blocks to the hub are now replaced by just one edge from
diff --git a/llvm/lib/Transforms/Utils/FlattenCFG.cpp b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
index 1925b91c4da7ec1..4480202bae8e7db 100644
--- a/llvm/lib/Transforms/Utils/FlattenCFG.cpp
+++ b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
@@ -408,7 +408,7 @@ bool FlattenCFGOpt::CompareIfRegionBlock(BasicBlock *Block1, BasicBlock *Block2,
/// approach goes for the opposite case.
bool FlattenCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder) {
BasicBlock *IfTrue2, *IfFalse2;
- BranchInst *DomBI2 = GetIfCondition(BB, IfTrue2, IfFalse2);
+ BranchInst *DomBI2 = GetIfConditionFromMergePoint(BB, IfTrue2, IfFalse2);
if (!DomBI2)
return false;
Instruction *CInst2 = dyn_cast<Instruction>(DomBI2->getCondition());
@@ -420,7 +420,7 @@ bool FlattenCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder) {
return false;
BasicBlock *IfTrue1, *IfFalse1;
- BranchInst *DomBI1 = GetIfCondition(SecondEntryBlock, IfTrue1, IfFalse1);
+ BranchInst *DomBI1 = GetIfConditionFromMergePoint(SecondEntryBlock, IfTrue1, IfFalse1);
if (!DomBI1)
return false;
Instruction *CInst1 = dyn_cast<Instruction>(DomBI1->getCondition());
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index c09cf9c2325c405..a161d32aec761a1 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3403,35 +3403,37 @@ static bool FoldCondBranchOnValueKnownInPredecessor(BranchInst *BI,
return EverChanged;
}
-/// Given a BB that starts with the specified two-entry PHI node,
-/// see if we can eliminate it.
-static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
- DomTreeUpdater *DTU, const DataLayout &DL) {
- // Ok, this is a two entry PHI node. Check to see if this is a simple "if
- // statement", which has a very simple dominance structure. Basically, we
- // are trying to find the condition that is being branched on, which
- // subsequently causes this merge to happen. We really want control
- // dependence information for this check, but simplifycfg can't keep it up
- // to date, and this catches most of the cases we care about anyway.
- BasicBlock *BB = PN->getParent();
-
- BasicBlock *IfTrue, *IfFalse;
- BranchInst *DomBI = GetIfCondition(BB, IfTrue, IfFalse);
- if (!DomBI)
+// Fold phis in BB based on if-else information.
+static bool FoldPHIOfIfRegion(BasicBlock *BB, BasicBlock *DomBlock,
+ BasicBlock *IfTrue, BasicBlock *IfFalse,
+ const TargetTransformInfo &TTI,
+ DomTreeUpdater *DTU, const DataLayout &DL) {
+ assert(isa<BranchInst>(DomBlock->getTerminator()));
+
+ if (BB->phis().empty())
return false;
+
+ PHINode *PN = &*BB->phis().begin();
+
+ BranchInst *DomBI = cast<BranchInst>(DomBlock->getTerminator());
Value *IfCond = DomBI->getCondition();
// Don't bother if the branch will be constant folded trivially.
if (isa<ConstantInt>(IfCond))
return false;
- BasicBlock *DomBlock = DomBI->getParent();
- SmallVector<BasicBlock *, 2> IfBlocks;
+ // Track BBs that jumps into phi unconditionally, to handle the cases where
+ // one of {IfTrue, IfFalse} is DomBlock.
+ SmallVector<BasicBlock *, 2> UncondEnterBlocks;
llvm::copy_if(
- PN->blocks(), std::back_inserter(IfBlocks), [](BasicBlock *IfBlock) {
+ SmallVector<BasicBlock *, 2>{IfTrue, IfFalse},
+ std::back_inserter(UncondEnterBlocks), [](BasicBlock *IfBlock) {
return cast<BranchInst>(IfBlock->getTerminator())->isUnconditional();
});
- assert((IfBlocks.size() == 1 || IfBlocks.size() == 2) &&
- "Will have either one or two blocks to speculate.");
+
+ // NOTE: Keep the order of BBs the same as the order in phi.
+ llvm::sort(UncondEnterBlocks, [PN](BasicBlock *B1, BasicBlock *B2) {
+ return PN->getBasicBlockIndex(B1) < PN->getBasicBlockIndex(B2);
+ });
// If the branch is non-unpredictable, see if we either predictably jump to
// the merge bb (if we have only a single 'then' block), or if we predictably
@@ -3446,7 +3448,7 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
BranchProbability::getBranchProbability(TWeight, TWeight + FWeight);
BranchProbability Likely = TTI.getPredictableBranchThreshold();
BranchProbability BIFalseProb = BITrueProb.getCompl();
- if (IfBlocks.size() == 1) {
+ if (UncondEnterBlocks.size() == 1) {
BranchProbability BIBBProb =
DomBI->getSuccessor(0) == BB ? BITrueProb : BIFalseProb;
if (BIBBProb >= Likely)
@@ -3492,10 +3494,10 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
continue;
}
- if (!dominatesMergePoint(PN->getIncomingValue(0), BB, AggressiveInsts,
- Cost, Budget, TTI) ||
- !dominatesMergePoint(PN->getIncomingValue(1), BB, AggressiveInsts,
- Cost, Budget, TTI))
+ if (!dominatesMergePoint(PN->getIncomingValueForBlock(IfTrue), BB,
+ AggressiveInsts, Cost, Budget, TTI) ||
+ !dominatesMergePoint(PN->getIncomingValueForBlock(IfFalse), BB,
+ AggressiveInsts, Cost, Budget, TTI))
return Changed;
}
@@ -3525,18 +3527,21 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
m_CombineOr(m_Select(m_Value(), m_ImmConstant(), m_Value()),
m_Select(m_Value(), m_Value(), m_ImmConstant()))));
};
+
+ Value *TrueVal = PN->getIncomingValueForBlock(IfTrue);
+ Value *FalseVal = PN->getIncomingValueForBlock(IfFalse);
+
if (PN->getType()->isIntegerTy(1) &&
- (IsBinOpOrAnd(PN->getIncomingValue(0)) ||
- IsBinOpOrAnd(PN->getIncomingValue(1)) || IsBinOpOrAnd(IfCond)) &&
- !CanHoistNotFromBothValues(PN->getIncomingValue(0),
- PN->getIncomingValue(1)))
+ (IsBinOpOrAnd(TrueVal) || IsBinOpOrAnd(FalseVal) ||
+ IsBinOpOrAnd(IfCond)) &&
+ !CanHoistNotFromBothValues(TrueVal, FalseVal))
return Changed;
// If all PHI nodes are promotable, check to make sure that all instructions
// in the predecessor blocks can be promoted as well. If not, we won't be able
// to get rid of the control flow, so it's not worth promoting to select
// instructions.
- for (BasicBlock *IfBlock : IfBlocks)
+ for (BasicBlock *IfBlock : UncondEnterBlocks)
for (BasicBlock::iterator I = IfBlock->begin(); !I->isTerminator(); ++I)
if (!AggressiveInsts.count(&*I) && !I->isDebugOrPseudoInst()) {
// This is not an aggressive instruction that we can promote.
@@ -3546,7 +3551,7 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
}
// If either of the blocks has it's address taken, we can't do this fold.
- if (any_of(IfBlocks,
+ if (any_of(UncondEnterBlocks,
[](BasicBlock *IfBlock) { return IfBlock->hasAddressTaken(); }))
return Changed;
@@ -3559,8 +3564,8 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
// Move all 'aggressive' instructions, which are defined in the
// conditional parts of the if's up to the dominating block.
- for (BasicBlock *IfBlock : IfBlocks)
- hoistAllInstructionsInto(DomBlock, DomBI, IfBlock);
+ for (BasicBlock *IfBlock : UncondEnterBlocks)
+ hoistAllInstructionsInto(DomBlock, DomBI, IfBlock);
IRBuilder<NoFolder> Builder(DomBI);
// Propagate fast-math-flags from phi nodes to replacement selects.
@@ -3574,12 +3579,18 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
Value *FalseVal = PN->getIncomingValueForBlock(IfFalse);
Value *Sel = Builder.CreateSelect(IfCond, TrueVal, FalseVal, "", DomBI);
- PN->replaceAllUsesWith(Sel);
- Sel->takeName(PN);
- PN->eraseFromParent();
+ if (PN->getNumIncomingValues() == 2) {
+ PN->replaceAllUsesWith(Sel);
+ Sel->takeName(PN);
+ PN->eraseFromParent();
+ } else {
+ PN->removeIncomingValue(IfTrue);
+ PN->removeIncomingValue(IfFalse);
+ PN->addIncoming(Sel, DomBlock);
+ }
}
- // At this point, all IfBlocks are empty, so our if statement
+ // At this point, all UncondEnterBlocks are empty, so our if statement
// has been flattened. Change DomBlock to jump directly to our new block to
// avoid other simplifycfg's kicking in on the diamond.
Builder.CreateBr(BB);
@@ -3598,6 +3609,25 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
return true;
}
+/// Given a BB that starts with the specified two-entry PHI node,
+/// see if we can eliminate it.
+static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
+ DomTreeUpdater *DTU, const DataLayout &DL) {
+ // Ok, this is a two entry PHI node. Check to see if this is a simple "if
+ // statement", which has a very simple dominance structure. Basically, we
+ // are trying to find the condition that is being branched on, which
+ // subsequently causes this merge to happen. We really want control
+ // dependence information for this check, but simplifycfg can't keep it up
+ // to date, and this catches most of the cases we care about anyway.
+ BasicBlock *BB = PN->getParent();
+ BasicBlock *IfTrue, *IfFalse;
+ BranchInst *DomBI = GetIfConditionFromMergePoint(BB, IfTrue, IfFalse);
+ if (!DomBI)
+ return false;
+ BasicBlock *DomBlock = DomBI->getParent();
+ return FoldPHIOfIfRegion(BB, DomBlock, IfTrue, IfFalse, TTI, DTU, DL);
+}
+
static Value *createLogicalOp(IRBuilderBase &Builder,
Instruction::BinaryOps Opc, Value *LHS,
Value *RHS, const Twine &Name = "") {
@@ -7315,6 +7345,7 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
if (HoistCommon && hoistCommonCodeFromSuccessors(
BI->getParent(), !Options.HoistCommonInsts))
return requestResimplify();
+
} else {
// If Successor #1 has multiple preds, we may be able to conditionally
// execute Successor #0 if it branches to Successor #1.
diff --git a/llvm/test/Transforms/SimplifyCFG/PhiEliminate2.ll b/llvm/test/Transforms/SimplifyCFG/PhiEliminate2.ll
index 3b7cbcf1534ae42..ea2f2f1491c5289 100644
--- a/llvm/test/Transforms/SimplifyCFG/PhiEliminate2.ll
+++ b/llvm/test/Transforms/SimplifyCFG/PhiEliminate2.ll
@@ -1,29 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
; Use a select to make this a single BB.
; Also, make sure the profile metadata is propagated to the select (PR26636).
define i32 @FoldTwoEntryPHINode(i1 %C, i32 %V1, i32 %V2, i16 %V3) {
+; CHECK-LABEL: define i32 @FoldTwoEntryPHINode(
+; CHECK-SAME: i1 [[C:%.*]], i32 [[V1:%.*]], i32 [[V2:%.*]], i16 [[V3:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V5:%.*]] = sext i16 [[V3]] to i32
+; CHECK-NEXT: [[V4:%.*]] = or i32 [[V2]], [[V1]]
+; CHECK-NEXT: [[V6:%.*]] = select i1 [[C]], i32 [[V4]], i32 [[V5]], !prof [[PROF0:![0-9]+]], !unpredictable !1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @FoldTwoEntryPHINode(i1 false, i32 0, i32 0, i16 0)
+; CHECK-NEXT: ret i32 [[V1]]
+;
entry:
- br i1 %C, label %then, label %else, !prof !0, !unpredictable !1
+ br i1 %C, label %then, label %else, !prof !0, !unpredictable !1
then:
- %V4 = or i32 %V2, %V1
- br label %Cont
+ %V4 = or i32 %V2, %V1
+ br label %Cont
else:
- %V5 = sext i16 %V3 to i32
- br label %Cont
+ %V5 = sext i16 %V3 to i32
+ br label %Cont
Cont:
- %V6 = phi i32 [ %V5, %else ], [ %V4, %then ]
- call i32 @FoldTwoEntryPHINode( i1 false, i32 0, i32 0, i16 0 )
- ret i32 %V1
+ %V6 = phi i32 [ %V5, %else ], [ %V4, %then ]
+ call i32 @FoldTwoEntryPHINode( i1 false, i32 0, i32 0, i16 0 )
+ ret i32 %V1
-; CHECK-LABEL: @FoldTwoEntryPHINode(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: %V5 = sext i16 %V3 to i32
-; CHECK-NEXT: %V4 = or i32 %V2, %V1
-; CHECK-NEXT: %V6 = select i1 %C, i32 %V4, i32 %V5, !prof !0, !unpredictable !1
-; CHECK-NEXT: %0 = call i32 @FoldTwoEntryPHINode(i1 false, i32 0, i32 0, i16 0)
-; CHECK-NEXT: ret i32 %V1
}
!0 = !{!"branch_weights", i32 3, i32 5}
>From 92911d3920b64a49f90bdae0b9d10f3c78e3abf1 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Wed, 29 Nov 2023 01:31:30 +0800
Subject: [PATCH 3/3] [SimplifyCFG] Fold pairs of entries in multiple-entry phi
---
.../llvm/Transforms/Utils/BasicBlockUtils.h | 5 +-
llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | 21 +--
llvm/lib/Transforms/Utils/FlattenCFG.cpp | 3 +-
llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 43 ++++--
.../CodeGen/ARM/2013-05-05-IfConvertBug.ll | 51 +++----
.../SimplifyCFG/X86/sink-common-code.ll | 20 +--
.../SimplifyCFG/X86/switch_to_lookup_table.ll | 139 ++++++++----------
.../SimplifyCFG/fold-multiple-entry-phi.ll | 32 ++--
8 files changed, 155 insertions(+), 159 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 998acbe9ab75da7..588028cdff929db 100644
--- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -596,7 +596,7 @@ void SplitBlockAndInsertForEachLane(
/// This does no checking to see if the true/false blocks have large or unsavory
/// instructions in them.
BranchInst *GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
- BasicBlock *&IfFalse);
+ BasicBlock *&IfFalse);
/// Check whether BB is the dominant point of a if-region.
/// If so, return the merge point of the if-region. Also, return by references
@@ -606,7 +606,8 @@ BranchInst *GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
/// This does no checking to see if the true/false blocks have large or unsavory
/// instructions in them.
///
-/// NOTE: we assume that the terminator of DomBB is a conditional branch instruction.
+/// NOTE: we assume that the terminator of DomBB is a conditional branch
+/// instruction.
BasicBlock *GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
BasicBlock *&IfFalse);
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index d43a5f72846f72c..9145c2dacc2f622 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -1727,8 +1727,9 @@ void llvm::SplitBlockAndInsertForEachLane(
}
}
-BranchInst *llvm::GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
- BasicBlock *&IfFalse) {
+BranchInst *llvm::GetIfConditionFromMergePoint(BasicBlock *BB,
+ BasicBlock *&IfTrue,
+ BasicBlock *&IfFalse) {
PHINode *SomePHI = dyn_cast<PHINode>(BB->begin());
BasicBlock *Pred1 = nullptr;
BasicBlock *Pred2 = nullptr;
@@ -1821,7 +1822,7 @@ BranchInst *llvm::GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTr
BasicBlock *llvm::GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
BasicBlock *&IfFalse) {
- BranchInst* BI = cast<BranchInst>(DomBB->getTerminator());
+ BranchInst *BI = cast<BranchInst>(DomBB->getTerminator());
BasicBlock *Succ1 = BI->getSuccessor(0);
BasicBlock *Succ2 = BI->getSuccessor(1);
@@ -1829,13 +1830,6 @@ BasicBlock *llvm::GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
Succ1 == Succ2 || Succ1 == DomBB || Succ2 == DomBB)
return nullptr;
- // We can only handle branches. Other control flow will be lowered to
- // branches if possible anyway.
- BranchInst *Succ1Br = dyn_cast<BranchInst>(Succ1->getTerminator());
- BranchInst *Succ2Br = dyn_cast<BranchInst>(Succ2->getTerminator());
- if (!Succ1Br || !Succ2Br)
- return nullptr;
-
if (Succ1->getSingleSuccessor() == Succ2) {
IfTrue = Succ1;
IfFalse = DomBB;
@@ -1848,6 +1842,13 @@ BasicBlock *llvm::GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
return Succ1;
}
+ // We can only handle branches. Other control flow will be lowered to
+ // branches if possible anyway.
+ BranchInst *Succ1Br = dyn_cast<BranchInst>(Succ1->getTerminator());
+ BranchInst *Succ2Br = dyn_cast<BranchInst>(Succ2->getTerminator());
+ if (!Succ1Br || !Succ2Br)
+ return nullptr;
+
auto *CommonDest = Succ1->getSingleSuccessor();
if (CommonDest && CommonDest != DomBB &&
CommonDest == Succ2->getSingleSuccessor()) {
diff --git a/llvm/lib/Transforms/Utils/FlattenCFG.cpp b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
index 4480202bae8e7db..08fbcef5cd91f64 100644
--- a/llvm/lib/Transforms/Utils/FlattenCFG.cpp
+++ b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
@@ -420,7 +420,8 @@ bool FlattenCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder) {
return false;
BasicBlock *IfTrue1, *IfFalse1;
- BranchInst *DomBI1 = GetIfConditionFromMergePoint(SecondEntryBlock, IfTrue1, IfFalse1);
+ BranchInst *DomBI1 =
+ GetIfConditionFromMergePoint(SecondEntryBlock, IfTrue1, IfFalse1);
if (!DomBI1)
return false;
Instruction *CInst1 = dyn_cast<Instruction>(DomBI1->getCondition());
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index a161d32aec761a1..a1d51d911f6a2be 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -237,11 +237,19 @@ struct ValueEqualityComparisonCase {
bool operator==(BasicBlock *RHSDest) const { return Dest == RHSDest; }
};
+struct IfRegion {
+ BasicBlock *DomBB;
+ BasicBlock *IfTrue;
+ BasicBlock *IfFalse;
+ BasicBlock *MergePoint;
+};
+
class SimplifyCFGOpt {
const TargetTransformInfo &TTI;
DomTreeUpdater *DTU;
const DataLayout &DL;
ArrayRef<WeakVH> LoopHeaders;
+ DenseMap<BasicBlock *, IfRegion> IfRegions; // Merge point -> If region
const SimplifyCFGOptions &Options;
bool Resimplify;
@@ -3422,7 +3430,7 @@ static bool FoldPHIOfIfRegion(BasicBlock *BB, BasicBlock *DomBlock,
return false;
// Track BBs that jumps into phi unconditionally, to handle the cases where
- // one of {IfTrue, IfFalse} is DomBlock.
+ // one of {IfTrue, IfFalse} is DomBlock.
SmallVector<BasicBlock *, 2> UncondEnterBlocks;
llvm::copy_if(
SmallVector<BasicBlock *, 2>{IfTrue, IfFalse},
@@ -3570,23 +3578,21 @@ static bool FoldPHIOfIfRegion(BasicBlock *BB, BasicBlock *DomBlock,
IRBuilder<NoFolder> Builder(DomBI);
// Propagate fast-math-flags from phi nodes to replacement selects.
IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
- while (PHINode *PN = dyn_cast<PHINode>(BB->begin())) {
+ for (PHINode &PN : make_early_inc_range(BB->phis())) {
if (isa<FPMathOperator>(PN))
- Builder.setFastMathFlags(PN->getFastMathFlags());
+ Builder.setFastMathFlags(PN.getFastMathFlags());
// Change the PHI node into a select instruction.
- Value *TrueVal = PN->getIncomingValueForBlock(IfTrue);
- Value *FalseVal = PN->getIncomingValueForBlock(IfFalse);
+ Value *TrueVal = PN.getIncomingValueForBlock(IfTrue);
+ Value *FalseVal = PN.getIncomingValueForBlock(IfFalse);
Value *Sel = Builder.CreateSelect(IfCond, TrueVal, FalseVal, "", DomBI);
- if (PN->getNumIncomingValues() == 2) {
- PN->replaceAllUsesWith(Sel);
- Sel->takeName(PN);
- PN->eraseFromParent();
+ if (PN.getNumIncomingValues() == 2) {
+ PN.replaceAllUsesWith(Sel);
+ Sel->takeName(&PN);
+ PN.eraseFromParent();
} else {
- PN->removeIncomingValue(IfTrue);
- PN->removeIncomingValue(IfFalse);
- PN->addIncoming(Sel, DomBlock);
+ PN.addIncoming(Sel, DomBlock);
}
}
@@ -7386,6 +7392,19 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
if (mergeConditionalStores(PBI, BI, DTU, DL, TTI))
return requestResimplify();
+ // Fold the merge-point phi of if-region.
+ BasicBlock *IfTrue;
+ BasicBlock *IfFalse;
+ if (Options.SpeculateBlocks)
+ if (BasicBlock *MergePoint = GetIfConditionFromDom(BB, IfTrue, IfFalse)) {
+ // Guarantee that the merge point is simplified before dominant point.
+ // FIXME: Prevent recursive calls.
+ if (simplifyOnce(MergePoint))
+ return requestResimplify();
+ if (FoldPHIOfIfRegion(MergePoint, BB, IfTrue, IfFalse, TTI, DTU, DL))
+ return requestResimplify();
+ }
+
return false;
}
diff --git a/llvm/test/CodeGen/ARM/2013-05-05-IfConvertBug.ll b/llvm/test/CodeGen/ARM/2013-05-05-IfConvertBug.ll
index 344bb15d2a8b8fa..d39807116371d87 100644
--- a/llvm/test/CodeGen/ARM/2013-05-05-IfConvertBug.ll
+++ b/llvm/test/CodeGen/ARM/2013-05-05-IfConvertBug.ll
@@ -309,16 +309,15 @@ define i32 @wrapDistance(i32 %tx, i32 %sx, i32 %w) {
; CHECK-NEXT: suble r0, r2, #1
; CHECK-NEXT: bxle lr
; CHECK-NEXT: LBB4_1: @ %if.else
-; CHECK-NEXT: subs r2, #120
+; CHECK-NEXT: subs r3, r1, r0
+; CHECK-NEXT: cmp r0, #120
+; CHECK-NEXT: sub.w r2, r2, #120
+; CHECK-NEXT: mov r0, r3
+; CHECK-NEXT: it lt
+; CHECK-NEXT: addlt r0, r1, #1
; CHECK-NEXT: cmp r2, r1
-; CHECK-NEXT: bge LBB4_3
-; CHECK-NEXT: @ %bb.2: @ %if.else
-; CHECK-NEXT: cmp r0, #119
-; CHECK-NEXT: itt le
-; CHECK-NEXT: addle r0, r1, #1
-; CHECK-NEXT: bxle lr
-; CHECK-NEXT: LBB4_3: @ %if.end5
-; CHECK-NEXT: subs r0, r1, r0
+; CHECK-NEXT: it ge
+; CHECK-NEXT: movge r0, r3
; CHECK-NEXT: bx lr
;
; CHECK-V8-LABEL: wrapDistance:
@@ -328,16 +327,15 @@ define i32 @wrapDistance(i32 %tx, i32 %sx, i32 %w) {
; CHECK-V8-NEXT: suble r0, r2, #1
; CHECK-V8-NEXT: bxle lr
; CHECK-V8-NEXT: .LBB4_1: @ %if.else
-; CHECK-V8-NEXT: subs r2, #120
+; CHECK-V8-NEXT: subs r3, r1, r0
+; CHECK-V8-NEXT: cmp r0, #120
+; CHECK-V8-NEXT: sub.w r2, r2, #120
+; CHECK-V8-NEXT: mov r0, r3
+; CHECK-V8-NEXT: it lt
+; CHECK-V8-NEXT: addlt r0, r1, #1
; CHECK-V8-NEXT: cmp r2, r1
-; CHECK-V8-NEXT: bge .LBB4_3
-; CHECK-V8-NEXT: @ %bb.2: @ %if.else
-; CHECK-V8-NEXT: cmp r0, #119
-; CHECK-V8-NEXT: itt le
-; CHECK-V8-NEXT: addle r0, r1, #1
-; CHECK-V8-NEXT: bxle lr
-; CHECK-V8-NEXT: .LBB4_3: @ %if.end5
-; CHECK-V8-NEXT: subs r0, r1, r0
+; CHECK-V8-NEXT: it ge
+; CHECK-V8-NEXT: movge r0, r3
; CHECK-V8-NEXT: bx lr
;
; CHECK-RESTRICT-IT-LABEL: wrapDistance:
@@ -348,17 +346,16 @@ define i32 @wrapDistance(i32 %tx, i32 %sx, i32 %w) {
; CHECK-RESTRICT-IT-NEXT: subs r0, r2, #1
; CHECK-RESTRICT-IT-NEXT: bx lr
; CHECK-RESTRICT-IT-NEXT: .LBB4_2: @ %if.else
+; CHECK-RESTRICT-IT-NEXT: subs r3, r1, r0
+; CHECK-RESTRICT-IT-NEXT: mov r12, r0
+; CHECK-RESTRICT-IT-NEXT: adds r0, r1, #1
+; CHECK-RESTRICT-IT-NEXT: cmp.w r12, #120
+; CHECK-RESTRICT-IT-NEXT: it ge
+; CHECK-RESTRICT-IT-NEXT: movge r0, r3
; CHECK-RESTRICT-IT-NEXT: subs r2, #120
; CHECK-RESTRICT-IT-NEXT: cmp r2, r1
-; CHECK-RESTRICT-IT-NEXT: bge .LBB4_5
-; CHECK-RESTRICT-IT-NEXT: @ %bb.3: @ %if.else
-; CHECK-RESTRICT-IT-NEXT: cmp r0, #119
-; CHECK-RESTRICT-IT-NEXT: bgt .LBB4_5
-; CHECK-RESTRICT-IT-NEXT: @ %bb.4: @ %if.then4
-; CHECK-RESTRICT-IT-NEXT: adds r0, r1, #1
-; CHECK-RESTRICT-IT-NEXT: bx lr
-; CHECK-RESTRICT-IT-NEXT: .LBB4_5: @ %if.end5
-; CHECK-RESTRICT-IT-NEXT: subs r0, r1, r0
+; CHECK-RESTRICT-IT-NEXT: it ge
+; CHECK-RESTRICT-IT-NEXT: movge r0, r3
; CHECK-RESTRICT-IT-NEXT: bx lr
entry:
%cmp = icmp slt i32 %sx, 60
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
index 26107965a1a8b6d..c3eab615afb2ae1 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
@@ -693,8 +693,8 @@ define zeroext i1 @test17(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
; CHECK-LABEL: @test17(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[IF_END:%.*]] [
-; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]]
-; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]]
+; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]]
+; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]]
; CHECK-NEXT: ]
; CHECK: if.then:
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
@@ -744,8 +744,8 @@ define zeroext i1 @test18(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
; CHECK-LABEL: @test18(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[IF_THEN3:%.*]] [
-; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]]
-; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]]
+; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]]
+; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]]
; CHECK-NEXT: ]
; CHECK: if.then:
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
@@ -1285,11 +1285,11 @@ define void @test_sink_void_calls(i32 %x) {
; CHECK-LABEL: @test_sink_void_calls(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [
-; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
-; CHECK-NEXT: i32 1, label [[BB1:%.*]]
-; CHECK-NEXT: i32 2, label [[BB2:%.*]]
-; CHECK-NEXT: i32 3, label [[BB3:%.*]]
-; CHECK-NEXT: i32 4, label [[BB4:%.*]]
+; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
+; CHECK-NEXT: i32 1, label [[BB1:%.*]]
+; CHECK-NEXT: i32 2, label [[BB2:%.*]]
+; CHECK-NEXT: i32 3, label [[BB3:%.*]]
+; CHECK-NEXT: i32 4, label [[BB4:%.*]]
; CHECK-NEXT: ]
; CHECK: bb1:
; CHECK-NEXT: br label [[RETURN]]
@@ -1563,7 +1563,7 @@ end:
define void @nontemporal(ptr %ptr, i1 %cond) {
; CHECK-LABEL: @nontemporal(
; CHECK-NEXT: entry:
-; CHECK-NEXT: store i64 0, ptr [[PTR:%.*]], align 8, !nontemporal !7
+; CHECK-NEXT: store i64 0, ptr [[PTR:%.*]], align 8, !nontemporal [[META7:![0-9]+]]
; CHECK-NEXT: ret void
;
entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
index 3873f0c0ae0bbd5..40a00eae79687a5 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -5,28 +5,20 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
target triple = "x86_64-unknown-linux-gnu"
; The table for @f
-; CHECK: @switch.table.f = private unnamed_addr constant [7 x i32] [i32 55, i32 123, i32 0, i32 -1, i32 27, i32 62, i32 1], align 4
; The char table for char
-; CHECK: @switch.table.char = private unnamed_addr constant [9 x i8] c"7{\00\FF\1B>\01!T", align 1
; The float table for @h
-; CHECK: @switch.table.h = private unnamed_addr constant [4 x float] [float 0x40091EB860000000, float 0x3FF3BE76C0000000, float 0x4012449BA0000000, float 0x4001AE1480000000], align 4
; The table for @foostring
-; CHECK: @switch.table.foostring = private unnamed_addr constant [4 x ptr] [ptr @.str, ptr @.str1, ptr @.str2, ptr @.str3], align 8
; The table for @earlyreturncrash
-; CHECK: @switch.table.earlyreturncrash = private unnamed_addr constant [4 x i32] [i32 42, i32 9, i32 88, i32 5], align 4
; The table for @large
-; CHECK: @switch.table.large = private unnamed_addr constant [199 x i32] [i32 1, i32 4, i32 9,
; The table for @cprop
-; CHECK: @switch.table.cprop = private unnamed_addr constant [7 x i32] [i32 5, i32 42, i32 126, i32 -452, i32 128, i32 6, i32 7], align 4
; The table for @unreachable_case
-; CHECK: @switch.table.unreachable_case = private unnamed_addr constant [9 x i32] [i32 0, i32 0, i32 0, i32 2, i32 -1, i32 1, i32 1, i32 1, i32 1], align 4
; A simple int-to-int selection switch.
; It is dense enough to be replaced by table lookup.
@@ -254,16 +246,15 @@ define i32 @crud(i8 zeroext %c) {
; CHECK: switch.early.test:
; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i8 [[C]], 34
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[SWITCH_TABLEIDX]], 59
-; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[LOR_END]]
-; CHECK: switch.lookup:
; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i8 [[SWITCH_TABLEIDX]] to i59
; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i59 [[SWITCH_CAST]], 1
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i59 -288230375765830623, [[SWITCH_SHIFTAMT]]
; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i59 [[SWITCH_DOWNSHIFT]] to i1
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_MASKED]], i1 false
; CHECK-NEXT: br label [[LOR_END]]
; CHECK: lor.end:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[SWITCH_MASKED]], [[SWITCH_LOOKUP]] ], [ false, [[SWITCH_EARLY_TEST]] ]
-; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP1]] to i32
+; CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[TMP1]], [[SWITCH_EARLY_TEST]] ]
+; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP2]] to i32
; CHECK-NEXT: ret i32 [[LOR_EXT]]
;
entry:
@@ -308,10 +299,10 @@ define i32 @overflow(i32 %type) {
; CHECK-LABEL: @overflow(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i32 [[TYPE:%.*]], label [[IF_END:%.*]] [
-; CHECK-NEXT: i32 3, label [[SW_BB3:%.*]]
-; CHECK-NEXT: i32 -2147483645, label [[SW_BB3]]
-; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
-; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]]
+; CHECK-NEXT: i32 3, label [[SW_BB3:%.*]]
+; CHECK-NEXT: i32 -2147483645, label [[SW_BB3]]
+; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]]
; CHECK-NEXT: ]
; CHECK: sw.bb1:
; CHECK-NEXT: br label [[IF_END]]
@@ -931,11 +922,11 @@ define i96 @illegaltype(i32 %c) {
; CHECK-LABEL: @illegaltype(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
-; CHECK-NEXT: i32 42, label [[RETURN:%.*]]
-; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]]
-; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]]
-; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]]
-; CHECK-NEXT: i32 46, label [[SW_BB4:%.*]]
+; CHECK-NEXT: i32 42, label [[RETURN:%.*]]
+; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]]
+; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]]
+; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]]
+; CHECK-NEXT: i32 46, label [[SW_BB4:%.*]]
; CHECK-NEXT: ]
; CHECK: sw.bb1:
; CHECK-NEXT: br label [[RETURN]]
@@ -1050,9 +1041,9 @@ define i32 @threecasesholes(i32 %c) {
; CHECK-LABEL: @threecasesholes(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
-; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
-; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
-; CHECK-NEXT: i32 3, label [[SW_BB2:%.*]]
+; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
+; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT: i32 3, label [[SW_BB2:%.*]]
; CHECK-NEXT: ]
; CHECK: sw.bb1:
; CHECK-NEXT: br label [[RETURN]]
@@ -1142,9 +1133,9 @@ define ptr @tls(i32 %x) {
; CHECK-LABEL: @tls(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [
-; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
-; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
-; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]]
+; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
+; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]]
; CHECK-NEXT: ]
; CHECK: sw.bb1:
; CHECK-NEXT: br label [[RETURN]]
@@ -1182,9 +1173,9 @@ define ptr @dllimport(i32 %x) {
; CHECK-LABEL: @dllimport(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [
-; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
-; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
-; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]]
+; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
+; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]]
; CHECK-NEXT: ]
; CHECK: sw.bb1:
; CHECK-NEXT: br label [[RETURN]]
@@ -1225,8 +1216,8 @@ define i8 @linearmap1(i32 %c) {
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul nsw i8 [[SWITCH_IDX_CAST]], -5
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i8 [[SWITCH_IDX_MULT]], 18
-; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT: ret i8 [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT: ret i8 [[TMP1]]
;
entry:
switch i32 %c, label %sw.default [
@@ -1252,8 +1243,8 @@ define i32 @linearmap2(i8 %c) {
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[SWITCH_TABLEIDX]], 4
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i8 [[SWITCH_TABLEIDX]] to i32
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_CAST]], 18
-; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 3
-; CHECK-NEXT: ret i32 [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 3
+; CHECK-NEXT: ret i32 [[TMP1]]
;
entry:
switch i8 %c, label %sw.default [
@@ -1279,8 +1270,8 @@ define i8 @linearmap3(i32 %c) {
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], 100
-; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_IDX_MULT]], i8 3
-; CHECK-NEXT: ret i8 [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_IDX_MULT]], i8 3
+; CHECK-NEXT: ret i8 [[TMP1]]
;
entry:
switch i32 %c, label %sw.default [
@@ -1305,8 +1296,8 @@ define i8 @linearmap4(i32 %c) {
; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], -2
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
-; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_IDX_CAST]], i8 3
-; CHECK-NEXT: ret i8 [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_IDX_CAST]], i8 3
+; CHECK-NEXT: ret i8 [[TMP1]]
;
entry:
switch i32 %c, label %sw.default [
@@ -1331,9 +1322,9 @@ define i32 @reuse_cmp1(i32 %x) {
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
; CHECK-NEXT: [[INVERTED_CMP:%.*]] = xor i1 [[TMP0]], true
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[X]], 10
-; CHECK-NEXT: [[R_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[R_0]], 0
-; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[INVERTED_CMP]], i32 100, i32 [[R_0]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[INVERTED_CMP]], i32 100, i32 [[TMP1]]
; CHECK-NEXT: ret i32 [[RETVAL_0]]
;
entry:
@@ -1399,9 +1390,9 @@ define i32 @no_reuse_cmp(i32 %x) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[X]], 10
-; CHECK-NEXT: [[R_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 12
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[R_0]], 0
-; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i32 [[R_0]], i32 100
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 12
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 100
; CHECK-NEXT: ret i32 [[RETVAL_0]]
;
entry:
@@ -1435,11 +1426,11 @@ define i32 @no_reuse_cmp2(i32 %x, i32 %y) {
; CHECK-NEXT: [[EC:%.*]] = icmp ne i32 [[Y:%.*]], 0
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[X]], 10
-; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
-; CHECK-NEXT: [[R_0:%.*]] = select i1 [[EC]], i32 [[SPEC_SELECT]], i32 100
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT: [[R_0:%.*]] = select i1 [[EC]], i32 [[TMP1]], i32 100
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[R_0]], 0
-; CHECK-NEXT: [[DOTR_0:%.*]] = select i1 [[CMP]], i32 100, i32 [[R_0]]
-; CHECK-NEXT: ret i32 [[DOTR_0]]
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i32 100, i32 [[R_0]]
+; CHECK-NEXT: ret i32 [[RETVAL_0]]
;
entry:
%ec = icmp ne i32 %y, 0
@@ -1476,11 +1467,11 @@ define void @pr20210(i8 %x, i1 %y) {
; CHECK-NEXT: br i1 [[Y:%.*]], label [[SW:%.*]], label [[INTERMEDIATE:%.*]]
; CHECK: sw:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[END:%.*]] [
-; CHECK-NEXT: i8 7, label [[INTERMEDIATE]]
-; CHECK-NEXT: i8 3, label [[INTERMEDIATE]]
-; CHECK-NEXT: i8 2, label [[INTERMEDIATE]]
-; CHECK-NEXT: i8 1, label [[INTERMEDIATE]]
-; CHECK-NEXT: i8 0, label [[INTERMEDIATE]]
+; CHECK-NEXT: i8 7, label [[INTERMEDIATE]]
+; CHECK-NEXT: i8 3, label [[INTERMEDIATE]]
+; CHECK-NEXT: i8 2, label [[INTERMEDIATE]]
+; CHECK-NEXT: i8 1, label [[INTERMEDIATE]]
+; CHECK-NEXT: i8 0, label [[INTERMEDIATE]]
; CHECK-NEXT: ]
; CHECK: intermediate:
; CHECK-NEXT: [[Z:%.*]] = zext i8 [[X]] to i32
@@ -1612,15 +1603,15 @@ define void @wineh_test(i64 %val) personality ptr @__CxxFrameHandler3 {
; CHECK-LABEL: @wineh_test(
; CHECK-NEXT: entry:
; CHECK-NEXT: invoke void @throw(i1 false)
-; CHECK-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CLEANUP1:%.*]]
+; CHECK-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CLEANUP1:%.*]]
; CHECK: unreachable:
; CHECK-NEXT: unreachable
; CHECK: cleanup1:
; CHECK-NEXT: [[CLEANUPPAD1:%.*]] = cleanuppad within none []
; CHECK-NEXT: switch i64 [[VAL:%.*]], label [[CLEANUPDONE2:%.*]] [
-; CHECK-NEXT: i64 0, label [[CLEANUPDONE1:%.*]]
-; CHECK-NEXT: i64 1, label [[CLEANUPDONE1]]
-; CHECK-NEXT: i64 6, label [[CLEANUPDONE1]]
+; CHECK-NEXT: i64 0, label [[CLEANUPDONE1:%.*]]
+; CHECK-NEXT: i64 1, label [[CLEANUPDONE1]]
+; CHECK-NEXT: i64 6, label [[CLEANUPDONE1]]
; CHECK-NEXT: ]
; CHECK: cleanupdone1:
; CHECK-NEXT: cleanupret from [[CLEANUPPAD1]] unwind label [[CLEANUP2:%.*]]
@@ -1670,8 +1661,8 @@ define i1 @use_x_as_index(i32 %x) {
; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i9 [[SWITCH_CAST]], 1
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i9 -234, [[SWITCH_SHIFTAMT]]
; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i9 [[SWITCH_DOWNSHIFT]] to i1
-; CHECK-NEXT: [[STOREMERGE:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_MASKED]], i1 false
-; CHECK-NEXT: ret i1 [[STOREMERGE]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_MASKED]], i1 false
+; CHECK-NEXT: ret i1 [[TMP1]]
;
entry:
switch i32 %x, label %sw.default [
@@ -1733,9 +1724,9 @@ define i32 @signed_overflow2(i8 %n) {
; CHECK-NEXT: start:
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2
; CHECK-NEXT: switch i2 [[TRUNC]], label [[BB1:%.*]] [
-; CHECK-NEXT: i2 1, label [[BB6:%.*]]
-; CHECK-NEXT: i2 -2, label [[BB4:%.*]]
-; CHECK-NEXT: i2 -1, label [[BB5:%.*]]
+; CHECK-NEXT: i2 1, label [[BB6:%.*]]
+; CHECK-NEXT: i2 -2, label [[BB4:%.*]]
+; CHECK-NEXT: i2 -1, label [[BB5:%.*]]
; CHECK-NEXT: ]
; CHECK: bb1:
; CHECK-NEXT: unreachable
@@ -1858,8 +1849,8 @@ define i32 @wrapped_on_index_sub(i8 %n) {
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul nsw i32 [[SWITCH_IDX_CAST]], 1111
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_MULT]], 1111
-; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
-; CHECK-NEXT: ret i32 [[DOTSROA_0_0]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT: ret i32 [[TMP1]]
;
start:
%trunc = trunc i8 %n to i3
@@ -1903,8 +1894,8 @@ define i32 @wrapped_on_index_sub_default(i8 %n) {
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul nsw i32 [[SWITCH_IDX_CAST]], 1111
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_MULT]], 1111
-; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
-; CHECK-NEXT: ret i32 [[DOTSROA_0_0]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT: ret i32 [[TMP1]]
;
start:
%trunc = trunc i8 %n to i3
@@ -1940,8 +1931,8 @@ define i8 @linearmap_inc_nsw(i32 %c) {
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul nsw i8 [[SWITCH_IDX_CAST]], 31
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i8 [[SWITCH_IDX_MULT]], 31
-; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT: ret i8 [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT: ret i8 [[TMP1]]
;
entry:
switch i32 %c, label %sw.default [
@@ -1967,8 +1958,8 @@ define i8 @linearmap_inc_wrapped(i32 %c) {
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], 32
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i8 [[SWITCH_IDX_MULT]], 32
-; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT: ret i8 [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT: ret i8 [[TMP1]]
;
entry:
switch i32 %c, label %sw.default [
@@ -1994,8 +1985,8 @@ define i8 @linearmap_dec_nsw(i32 %c) {
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul nsw i8 [[SWITCH_IDX_CAST]], -32
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i8 [[SWITCH_IDX_MULT]], -32
-; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT: ret i8 [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT: ret i8 [[TMP1]]
;
entry:
switch i32 %c, label %sw.default [
@@ -2021,8 +2012,8 @@ define i8 @linearmap_dec_wrapped(i32 %c) {
; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], -33
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i8 [[SWITCH_IDX_MULT]], -33
-; CHECK-NEXT: [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT: ret i8 [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT: ret i8 [[TMP1]]
;
entry:
switch i32 %c, label %sw.default [
diff --git a/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll b/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
index c86f20164ebc525..da333addf5af481 100644
--- a/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
+++ b/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
@@ -1,20 +1,15 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
-; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -two-entry-phi-node-folding-threshold=4 -phi-node-folding-threshold=0 < %s | FileCheck %s
+; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1< %s | FileCheck %s
define i32 @three_entry_test(i32 %x, i32 %y, i1 %cond){
; CHECK-LABEL: define i32 @three_entry_test(
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[COND]], label [[END:%.*]], label [[THEN:%.*]]
-; CHECK: then:
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
-; CHECK-NEXT: br i1 [[CMP]], label [[END]], label [[B:%.*]]
-; CHECK: b:
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1
-; CHECK-NEXT: br label [[END]]
-; CHECK: end:
-; CHECK-NEXT: [[RET_0:%.*]] = phi i32 [ [[SUB]], [[THEN]] ], [ [[ADD]], [[B]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[ADD]]
+; CHECK-NEXT: [[RET_0:%.*]] = select i1 [[COND]], i32 0, i32 [[SPEC_SELECT]]
; CHECK-NEXT: ret i32 [[RET_0]]
;
entry:
@@ -41,18 +36,11 @@ define i32 @three_entry_test_diamond(i32 %x, i32 %y, i1 %cond){
; CHECK-LABEL: define i32 @three_entry_test_diamond(
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[COND]], label [[END:%.*]], label [[THEN:%.*]]
-; CHECK: then:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
-; CHECK-NEXT: br i1 [[CMP]], label [[B1:%.*]], label [[B2:%.*]]
-; CHECK: b1:
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], -1
-; CHECK-NEXT: br label [[END]]
-; CHECK: b2:
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1
-; CHECK-NEXT: br label [[END]]
-; CHECK: end:
-; CHECK-NEXT: [[RET_0:%.*]] = phi i32 [ [[SUB]], [[B1]] ], [ [[ADD]], [[B2]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[ADD]]
+; CHECK-NEXT: [[RET_0:%.*]] = select i1 [[COND]], i32 0, i32 [[TMP0]]
; CHECK-NEXT: ret i32 [[RET_0]]
;
entry:
@@ -86,18 +74,16 @@ define i32 @four_entry_test(i32 %x, i32 %y, i1 %cond, i1 %cond1){
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[THEN1:%.*]]
; CHECK: if.then:
-; CHECK-NEXT: br i1 [[COND1]], label [[THEN:%.*]], label [[END:%.*]]
-; CHECK: then:
-; CHECK-NEXT: br label [[END]]
+; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND1]], i32 1, i32 0
+; CHECK-NEXT: br label [[END:%.*]]
; CHECK: then1:
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], -1
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
-; CHECK-NEXT: br i1 [[CMP1]], label [[END]], label [[B:%.*]]
-; CHECK: b:
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[CMP1]], i32 [[SUB]], i32 [[ADD]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
-; CHECK-NEXT: [[RET_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ 1, [[THEN]] ], [ [[SUB]], [[THEN1]] ], [ [[ADD]], [[B]] ]
+; CHECK-NEXT: [[RET_0:%.*]] = phi i32 [ [[SPEC_SELECT]], [[IF_THEN]] ], [ [[SPEC_SELECT1]], [[THEN1]] ]
; CHECK-NEXT: ret i32 [[RET_0]]
;
entry:
More information about the llvm-commits
mailing list