[llvm-branch-commits] [llvm] ca4ed1e - [PredicateInfo] Generalize processing of conditions
Nikita Popov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jan 20 11:45:33 PST 2021
Author: Nikita Popov
Date: 2021-01-20T20:40:41+01:00
New Revision: ca4ed1e7aeebe21dc3952f84b408805ab17ad63f
URL: https://github.com/llvm/llvm-project/commit/ca4ed1e7aeebe21dc3952f84b408805ab17ad63f
DIFF: https://github.com/llvm/llvm-project/commit/ca4ed1e7aeebe21dc3952f84b408805ab17ad63f.diff
LOG: [PredicateInfo] Generalize processing of conditions
Branch/assume conditions in PredicateInfo are currently handled in
a rather ad-hoc manner, with some arbitrary limitations. For example,
an `and` of two `icmp`s will be handled, but an `and` of an `icmp`
and some other condition will not. That also includes the case where
more than two conditions and and'ed together.
This patch makes the handling more general by looking through and/ors
up to a limit and considering all kinds of conditions (though operands
will only be taken for cmps of course).
Differential Revision: https://reviews.llvm.org/D94447
Added:
Modified:
llvm/lib/Transforms/Utils/PredicateInfo.cpp
llvm/test/Transforms/NewGVN/assume-equal.ll
llvm/test/Transforms/SCCP/conditions-ranges.ll
llvm/test/Transforms/Util/PredicateInfo/condprop.ll
llvm/test/Transforms/Util/PredicateInfo/testandor.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
index d9bd77e999da..9b6f7d32054f 100644
--- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp
+++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
@@ -53,6 +53,10 @@ static cl::opt<bool> VerifyPredicateInfo(
DEBUG_COUNTER(RenameCounter, "predicateinfo-rename",
"Controls which variables are renamed with predicateinfo");
+// Maximum number of conditions considered for renaming for each branch/assume.
+// This limits renaming of deep and/or chains.
+static const unsigned MaxCondsPerBranch = 8;
+
namespace {
// Given a predicate info that is a type of branching terminator, get the
// branching block.
@@ -367,6 +371,13 @@ void PredicateInfoBuilder::convertUsesToDFSOrdered(
}
}
+bool shouldRename(Value *V) {
+ // Only want real values, not constants. Additionally, operands with one use
+ // are only being used in the comparison, which means they will not be useful
+ // for us to consider for predicateinfo.
+ return (isa<Instruction>(V) || isa<Argument>(V)) && !V->hasOneUse();
+}
+
// Collect relevant operations from Comparison that we may want to insert copies
// for.
void collectCmpOps(CmpInst *Comparison, SmallVectorImpl<Value *> &CmpOperands) {
@@ -374,15 +385,9 @@ void collectCmpOps(CmpInst *Comparison, SmallVectorImpl<Value *> &CmpOperands) {
auto *Op1 = Comparison->getOperand(1);
if (Op0 == Op1)
return;
- CmpOperands.push_back(Comparison);
- // Only want real values, not constants. Additionally, operands with one use
- // are only being used in the comparison, which means they will not be useful
- // for us to consider for predicateinfo.
- //
- if ((isa<Instruction>(Op0) || isa<Argument>(Op0)) && !Op0->hasOneUse())
- CmpOperands.push_back(Op0);
- if ((isa<Instruction>(Op1) || isa<Argument>(Op1)) && !Op1->hasOneUse())
- CmpOperands.push_back(Op1);
+
+ CmpOperands.push_back(Op0);
+ CmpOperands.push_back(Op1);
}
// Add Op, PB to the list of value infos for Op, and mark Op to be renamed.
@@ -400,38 +405,32 @@ void PredicateInfoBuilder::addInfoFor(SmallVectorImpl<Value *> &OpsToRename,
void PredicateInfoBuilder::processAssume(
IntrinsicInst *II, BasicBlock *AssumeBB,
SmallVectorImpl<Value *> &OpsToRename) {
- // See if we have a comparison we support
- SmallVector<Value *, 8> CmpOperands;
- SmallVector<Value *, 2> ConditionsToProcess;
- CmpInst::Predicate Pred;
- Value *Operand = II->getOperand(0);
- if (m_c_And(m_Cmp(Pred, m_Value(), m_Value()),
- m_Cmp(Pred, m_Value(), m_Value()))
- .match(II->getOperand(0))) {
- ConditionsToProcess.push_back(cast<BinaryOperator>(Operand)->getOperand(0));
- ConditionsToProcess.push_back(cast<BinaryOperator>(Operand)->getOperand(1));
- ConditionsToProcess.push_back(Operand);
- } else if (isa<CmpInst>(Operand)) {
-
- ConditionsToProcess.push_back(Operand);
- }
- for (auto Cond : ConditionsToProcess) {
- if (auto *Cmp = dyn_cast<CmpInst>(Cond)) {
- collectCmpOps(Cmp, CmpOperands);
- // Now add our copy infos for our operands
- for (auto *Op : CmpOperands) {
- auto *PA = new PredicateAssume(Op, II, Cmp);
- addInfoFor(OpsToRename, Op, PA);
+ SmallVector<Value *, 4> Worklist;
+ SmallPtrSet<Value *, 4> Visited;
+ Worklist.push_back(II->getOperand(0));
+ while (!Worklist.empty()) {
+ Value *Cond = Worklist.pop_back_val();
+ if (!Visited.insert(Cond).second)
+ continue;
+ if (Visited.size() > MaxCondsPerBranch)
+ break;
+
+ Value *Op0, *Op1;
+ if (match(Cond, m_And(m_Value(Op0), m_Value(Op1)))) {
+ Worklist.push_back(Op1);
+ Worklist.push_back(Op0);
+ }
+
+ SmallVector<Value *, 4> Values;
+ Values.push_back(Cond);
+ if (auto *Cmp = dyn_cast<CmpInst>(Cond))
+ collectCmpOps(Cmp, Values);
+
+ for (Value *V : Values) {
+ if (shouldRename(V)) {
+ auto *PA = new PredicateAssume(V, II, Cond);
+ addInfoFor(OpsToRename, V, PA);
}
- CmpOperands.clear();
- } else if (auto *BinOp = dyn_cast<BinaryOperator>(Cond)) {
- // Otherwise, it should be an AND.
- assert(BinOp->getOpcode() == Instruction::And &&
- "Should have been an AND");
- auto *PA = new PredicateAssume(BinOp, II, BinOp);
- addInfoFor(OpsToRename, BinOp, PA);
- } else {
- llvm_unreachable("Unknown type of condition");
}
}
}
@@ -443,68 +442,46 @@ void PredicateInfoBuilder::processBranch(
SmallVectorImpl<Value *> &OpsToRename) {
BasicBlock *FirstBB = BI->getSuccessor(0);
BasicBlock *SecondBB = BI->getSuccessor(1);
- SmallVector<BasicBlock *, 2> SuccsToProcess;
- SuccsToProcess.push_back(FirstBB);
- SuccsToProcess.push_back(SecondBB);
- SmallVector<Value *, 2> ConditionsToProcess;
-
- auto InsertHelper = [&](Value *Op, bool isAnd, bool isOr, Value *Cond) {
- for (auto *Succ : SuccsToProcess) {
- // Don't try to insert on a self-edge. This is mainly because we will
- // eliminate during renaming anyway.
- if (Succ == BranchBB)
- continue;
- bool TakenEdge = (Succ == FirstBB);
- // For and, only insert on the true edge
- // For or, only insert on the false edge
- if ((isAnd && !TakenEdge) || (isOr && TakenEdge))
+
+ for (BasicBlock *Succ : {FirstBB, SecondBB}) {
+ bool TakenEdge = Succ == FirstBB;
+ // Don't try to insert on a self-edge. This is mainly because we will
+ // eliminate during renaming anyway.
+ if (Succ == BranchBB)
+ continue;
+
+ SmallVector<Value *, 4> Worklist;
+ SmallPtrSet<Value *, 4> Visited;
+ Worklist.push_back(BI->getCondition());
+ while (!Worklist.empty()) {
+ Value *Cond = Worklist.pop_back_val();
+ if (!Visited.insert(Cond).second)
continue;
- PredicateBase *PB =
- new PredicateBranch(Op, BranchBB, Succ, Cond, TakenEdge);
- addInfoFor(OpsToRename, Op, PB);
- if (!Succ->getSinglePredecessor())
- EdgeUsesOnly.insert({BranchBB, Succ});
- }
- };
+ if (Visited.size() > MaxCondsPerBranch)
+ break;
+
+ Value *Op0, *Op1;
+ if (TakenEdge ? match(Cond, m_And(m_Value(Op0), m_Value(Op1)))
+ : match(Cond, m_Or(m_Value(Op0), m_Value(Op1)))) {
+ Worklist.push_back(Op1);
+ Worklist.push_back(Op0);
+ }
- // Match combinations of conditions.
- CmpInst::Predicate Pred;
- bool isAnd = false;
- bool isOr = false;
- SmallVector<Value *, 8> CmpOperands;
- if (match(BI->getCondition(), m_And(m_Cmp(Pred, m_Value(), m_Value()),
- m_Cmp(Pred, m_Value(), m_Value()))) ||
- match(BI->getCondition(), m_Or(m_Cmp(Pred, m_Value(), m_Value()),
- m_Cmp(Pred, m_Value(), m_Value())))) {
- auto *BinOp = cast<BinaryOperator>(BI->getCondition());
- if (BinOp->getOpcode() == Instruction::And)
- isAnd = true;
- else if (BinOp->getOpcode() == Instruction::Or)
- isOr = true;
- ConditionsToProcess.push_back(BinOp->getOperand(0));
- ConditionsToProcess.push_back(BinOp->getOperand(1));
- ConditionsToProcess.push_back(BI->getCondition());
- } else if (isa<CmpInst>(BI->getCondition())) {
- ConditionsToProcess.push_back(BI->getCondition());
- }
- for (auto Cond : ConditionsToProcess) {
- if (auto *Cmp = dyn_cast<CmpInst>(Cond)) {
- collectCmpOps(Cmp, CmpOperands);
- // Now add our copy infos for our operands
- for (auto *Op : CmpOperands)
- InsertHelper(Op, isAnd, isOr, Cmp);
- } else if (auto *BinOp = dyn_cast<BinaryOperator>(Cond)) {
- // This must be an AND or an OR.
- assert((BinOp->getOpcode() == Instruction::And ||
- BinOp->getOpcode() == Instruction::Or) &&
- "Should have been an AND or an OR");
- // The actual value of the binop is not subject to the same restrictions
- // as the comparison. It's either true or false on the true/false branch.
- InsertHelper(BinOp, false, false, BinOp);
- } else {
- llvm_unreachable("Unknown type of condition");
+ SmallVector<Value *, 4> Values;
+ Values.push_back(Cond);
+ if (auto *Cmp = dyn_cast<CmpInst>(Cond))
+ collectCmpOps(Cmp, Values);
+
+ for (Value *V : Values) {
+ if (shouldRename(V)) {
+ PredicateBase *PB =
+ new PredicateBranch(V, BranchBB, Succ, Cond, TakenEdge);
+ addInfoFor(OpsToRename, V, PB);
+ if (!Succ->getSinglePredecessor())
+ EdgeUsesOnly.insert({BranchBB, Succ});
+ }
+ }
}
- CmpOperands.clear();
}
}
// Process a block terminating switch, and place relevant operations to be
diff --git a/llvm/test/Transforms/NewGVN/assume-equal.ll b/llvm/test/Transforms/NewGVN/assume-equal.ll
index d67105fbf1a2..f0e4f25d17b7 100644
--- a/llvm/test/Transforms/NewGVN/assume-equal.ll
+++ b/llvm/test/Transforms/NewGVN/assume-equal.ll
@@ -106,7 +106,7 @@ define i32 @_Z1il(i32 %val, i1 %k) {
; CHECK-NEXT: br label [[NEXT:%.*]]
; CHECK: next:
; CHECK-NEXT: tail call void @llvm.assume(i1 [[K:%.*]])
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[K]])
+; CHECK-NEXT: tail call void @llvm.assume(i1 true)
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL:%.*]], 50
; CHECK-NEXT: br i1 [[CMP]], label [[NEXT]], label [[MEH:%.*]]
; CHECK: meh:
@@ -132,7 +132,7 @@ define i1 @_z1im(i32 %val, i1 %k, i1 %j) {
; CHECK-NEXT: br i1 [[J:%.*]], label [[NEXT:%.*]], label [[MEH:%.*]]
; CHECK: next:
; CHECK-NEXT: tail call void @llvm.assume(i1 [[K:%.*]])
-; CHECK-NEXT: tail call void @llvm.assume(i1 [[K]])
+; CHECK-NEXT: tail call void @llvm.assume(i1 true)
; CHECK-NEXT: br label [[MEH]]
; CHECK: meh:
; CHECK-NEXT: ret i1 [[K]]
diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll
index 65c3440a207c..2317242e5e6c 100644
--- a/llvm/test/Transforms/SCCP/conditions-ranges.ll
+++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll
@@ -966,8 +966,6 @@ true:
ret void
}
-; TODO: Currently only the information of the AND used as branch condition is
-; used.
define void @f18_conditions_chained_and(i32 %a, i32 %b) {
; CHECK-LABEL: @f18_conditions_chained_and(
; CHECK-NEXT: entry:
@@ -978,18 +976,12 @@ define void @f18_conditions_chained_and(i32 %a, i32 %b) {
; CHECK-NEXT: [[BC_2:%.*]] = and i1 [[BC]], [[B_LT]]
; CHECK-NEXT: br i1 [[BC_2]], label [[TRUE:%.*]], label [[FALSE:%.*]]
; CHECK: true:
-; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 0
-; CHECK-NEXT: call void @use(i1 [[F_1]])
-; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[A]], 20
-; CHECK-NEXT: call void @use(i1 [[F_2]])
-; CHECK-NEXT: [[F_3:%.*]] = icmp ugt i32 [[A]], 100
-; CHECK-NEXT: call void @use(i1 [[F_3]])
-; CHECK-NEXT: [[F_4:%.*]] = icmp ugt i32 [[B]], 100
-; CHECK-NEXT: call void @use(i1 [[F_4]])
-; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[A]], 100
-; CHECK-NEXT: call void @use(i1 [[T_1]])
-; CHECK-NEXT: [[T_2:%.*]] = icmp ne i32 [[A]], 20
-; CHECK-NEXT: call void @use(i1 [[T_2]])
+; CHECK-NEXT: call void @use(i1 false)
+; CHECK-NEXT: call void @use(i1 false)
+; CHECK-NEXT: call void @use(i1 false)
+; CHECK-NEXT: call void @use(i1 false)
+; CHECK-NEXT: call void @use(i1 true)
+; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21
; CHECK-NEXT: call void @use(i1 [[C_1]])
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21
diff --git a/llvm/test/Transforms/Util/PredicateInfo/condprop.ll b/llvm/test/Transforms/Util/PredicateInfo/condprop.ll
index 4f5f07878cd2..689326b6ca97 100644
--- a/llvm/test/Transforms/Util/PredicateInfo/condprop.ll
+++ b/llvm/test/Transforms/Util/PredicateInfo/condprop.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
+; RUN: opt -print-predicateinfo -disable-output < %s 2>&1 | FileCheck %s
@a = external global i32 ; <i32*> [#uses=7]
@@ -98,11 +98,11 @@ define void @test3(i32 %x, i32 %y) {
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK-NEXT: br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
; CHECK: both_zero:
; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
@@ -138,8 +138,8 @@ define void @test4(i1 %b, i32 %x) {
; CHECK-NEXT: i32 2, label [[CASE0]]
; CHECK-NEXT: i32 3, label [[CASE3]]
; CHECK-NEXT: i32 4, label [[DEFAULT:%.*]]
-; CHECK-NEXT: ] Edge: [label [[SW]],label %case1]
-; CHECK-NEXT: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X:%.*]])
+; CHECK-NEXT: ] Edge: [label [[SW]],label %case1], RenamedOp: [[X:%.*]] }
+; CHECK-NEXT: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK-NEXT: switch i32 [[X]], label [[DEFAULT]] [
; CHECK-NEXT: i32 0, label [[CASE0]]
; CHECK-NEXT: i32 1, label [[CASE1]]
diff --git a/llvm/test/Transforms/Util/PredicateInfo/testandor.ll b/llvm/test/Transforms/Util/PredicateInfo/testandor.ll
index a3d8e78b5283..8ce56ac02cbb 100644
--- a/llvm/test/Transforms/Util/PredicateInfo/testandor.ll
+++ b/llvm/test/Transforms/Util/PredicateInfo/testandor.ll
@@ -10,11 +10,11 @@ define void @testor(i32 %x, i32 %y) {
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]]
; CHECK: oneof:
; CHECK-NEXT: call void @foo(i1 [[XZ]])
@@ -54,11 +54,11 @@ define void @testand(i32 %x, i32 %y) {
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
@@ -98,11 +98,11 @@ define void @testandsame(i32 %x, i32 %y) {
; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0
; CHECK-NEXT: [[XLT:%.*]] = icmp slt i32 [[X]], 100
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XGT]], [[XLT]]
+; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XGT]])
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK: [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X_0]])
; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XLT]])
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[XGT_0]])
@@ -137,25 +137,25 @@ define void @testandassume(i32 %x, i32 %y) {
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
; CHECK-NEXT: call void @llvm.assume(i1 [[Z]])
-; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
-; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
-; CHECK: [[TMP4:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
-; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
+; CHECK: [[TMP1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
+; CHECK: [[TMP3:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
+; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP5]])
-; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP4]])
-; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP3]])
-; CHECK: [[DOT03:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP2]])
-; CHECK: [[DOT04:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP1]])
-; CHECK-NEXT: br i1 [[TMP1]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK: [[DOT01:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP4]])
+; CHECK: [[DOT02:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP3]])
+; CHECK: [[DOT03:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP2]])
+; CHECK: [[DOT04:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP1]])
+; CHECK-NEXT: br i1 [[TMP5]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
-; CHECK-NEXT: call void @foo(i1 [[DOT0]])
-; CHECK-NEXT: call void @foo(i1 [[DOT02]])
-; CHECK-NEXT: call void @bar(i32 [[DOT01]])
-; CHECK-NEXT: call void @bar(i32 [[DOT03]])
+; CHECK-NEXT: call void @foo(i1 [[DOT01]])
+; CHECK-NEXT: call void @foo(i1 [[DOT03]])
+; CHECK-NEXT: call void @bar(i32 [[DOT02]])
+; CHECK-NEXT: call void @bar(i32 [[DOT04]])
; CHECK-NEXT: ret void
; CHECK: nope:
-; CHECK-NEXT: call void @foo(i1 [[DOT04]])
+; CHECK-NEXT: call void @foo(i1 [[DOT0]])
; CHECK-NEXT: ret void
;
%xz = icmp eq i32 %x, 0
@@ -182,8 +182,9 @@ define void @testorassume(i32 %x, i32 %y) {
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
; CHECK-NEXT: call void @llvm.assume(i1 [[Z]])
-; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
-; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
+; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP1]])
+; CHECK-NEXT: br i1 [[TMP1]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
; CHECK-NEXT: call void @foo(i1 [[XZ]])
; CHECK-NEXT: call void @foo(i1 [[YZ]])
@@ -191,7 +192,7 @@ define void @testorassume(i32 %x, i32 %y) {
; CHECK-NEXT: call void @bar(i32 [[Y]])
; CHECK-NEXT: ret void
; CHECK: nope:
-; CHECK-NEXT: call void @foo(i1 [[Z_0]])
+; CHECK-NEXT: call void @foo(i1 [[DOT0]])
; CHECK-NEXT: ret void
;
%xz = icmp eq i32 %x, 0
@@ -214,18 +215,23 @@ define void @test_and_one_unknown_cond(i32 %x, i1 %c1) {
; CHECK-LABEL: @test_and_one_unknown_cond(
; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[A:%.*]] = and i1 [[C1:%.*]], [[C2]]
+; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
+; CHECK: [[A_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
+; CHECK: [[C1_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C1]])
+; CHECK: [[C2_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C2]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK-NEXT: br i1 [[A]], label [[BOTH:%.*]], label [[NOPE:%.*]]
; CHECK: both:
-; CHECK-NEXT: call void @bar(i32 [[X]])
-; CHECK-NEXT: call void @foo(i1 [[C1]])
-; CHECK-NEXT: call void @foo(i1 [[C2]])
-; CHECK-NEXT: call void @foo(i1 [[A]])
+; CHECK-NEXT: call void @bar(i32 [[X_0]])
+; CHECK-NEXT: call void @foo(i1 [[C1_0]])
+; CHECK-NEXT: call void @foo(i1 [[C2_0]])
+; CHECK-NEXT: call void @foo(i1 [[A_0]])
; CHECK-NEXT: ret void
; CHECK: nope:
; CHECK-NEXT: call void @bar(i32 [[X]])
; CHECK-NEXT: call void @foo(i1 [[C1]])
; CHECK-NEXT: call void @foo(i1 [[C2]])
-; CHECK-NEXT: call void @foo(i1 [[A]])
+; CHECK-NEXT: call void @foo(i1 [[A_1]])
; CHECK-NEXT: ret void
;
%c2 = icmp eq i32 %x, 0
@@ -251,18 +257,23 @@ define void @test_or_one_unknown_cond(i32 %x, i1 %c1) {
; CHECK-LABEL: @test_or_one_unknown_cond(
; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[A:%.*]] = or i1 [[C1:%.*]], [[C2]]
+; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
+; CHECK: [[A_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
+; CHECK: [[C1_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C1]])
+; CHECK: [[C2_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C2]])
+; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
; CHECK-NEXT: br i1 [[A]], label [[NOPE:%.*]], label [[BOTH_INVERTED:%.*]]
; CHECK: both_inverted:
-; CHECK-NEXT: call void @bar(i32 [[X]])
-; CHECK-NEXT: call void @foo(i1 [[C1]])
-; CHECK-NEXT: call void @foo(i1 [[C2]])
-; CHECK-NEXT: call void @foo(i1 [[A]])
+; CHECK-NEXT: call void @bar(i32 [[X_0]])
+; CHECK-NEXT: call void @foo(i1 [[C1_0]])
+; CHECK-NEXT: call void @foo(i1 [[C2_0]])
+; CHECK-NEXT: call void @foo(i1 [[A_1]])
; CHECK-NEXT: ret void
; CHECK: nope:
; CHECK-NEXT: call void @bar(i32 [[X]])
; CHECK-NEXT: call void @foo(i1 [[C1]])
; CHECK-NEXT: call void @foo(i1 [[C2]])
-; CHECK-NEXT: call void @foo(i1 [[A]])
+; CHECK-NEXT: call void @foo(i1 [[A_0]])
; CHECK-NEXT: ret void
;
%c2 = icmp eq i32 %x, 0
@@ -288,20 +299,26 @@ define void @test_and_chain(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @test_and_chain(
; CHECK-NEXT: [[AND1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[C:%.*]]
+; CHECK: [[AND2_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND2]])
+; CHECK: [[AND2_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND2]])
+; CHECK: [[AND1_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND1]])
+; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
+; CHECK: [[B_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[B]])
+; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C]])
; CHECK-NEXT: br i1 [[AND2]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
-; CHECK-NEXT: call void @foo(i1 [[A]])
-; CHECK-NEXT: call void @foo(i1 [[B]])
-; CHECK-NEXT: call void @foo(i1 [[C]])
-; CHECK-NEXT: call void @foo(i1 [[AND1]])
-; CHECK-NEXT: call void @foo(i1 [[AND2]])
+; CHECK-NEXT: call void @foo(i1 [[A_0]])
+; CHECK-NEXT: call void @foo(i1 [[B_0]])
+; CHECK-NEXT: call void @foo(i1 [[C_0]])
+; CHECK-NEXT: call void @foo(i1 [[AND1_0]])
+; CHECK-NEXT: call void @foo(i1 [[AND2_0]])
; CHECK-NEXT: ret void
; CHECK: else:
; CHECK-NEXT: call void @foo(i1 [[A]])
; CHECK-NEXT: call void @foo(i1 [[B]])
; CHECK-NEXT: call void @foo(i1 [[C]])
; CHECK-NEXT: call void @foo(i1 [[AND1]])
-; CHECK-NEXT: call void @foo(i1 [[AND2]])
+; CHECK-NEXT: call void @foo(i1 [[AND2_1]])
; CHECK-NEXT: ret void
;
%and1 = and i1 %a, %b
@@ -329,20 +346,26 @@ define void @test_or_chain(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @test_or_chain(
; CHECK-NEXT: [[OR1:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[C:%.*]]
+; CHECK: [[OR2_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR2]])
+; CHECK: [[OR2_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR2]])
+; CHECK: [[OR1_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR1]])
+; CHECK: [[A_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
+; CHECK: [[B_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[B]])
+; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C]])
; CHECK-NEXT: br i1 [[OR2]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A]])
; CHECK-NEXT: call void @foo(i1 [[B]])
; CHECK-NEXT: call void @foo(i1 [[C]])
; CHECK-NEXT: call void @foo(i1 [[OR1]])
-; CHECK-NEXT: call void @foo(i1 [[OR2]])
+; CHECK-NEXT: call void @foo(i1 [[OR2_0]])
; CHECK-NEXT: ret void
; CHECK: else:
-; CHECK-NEXT: call void @foo(i1 [[A]])
-; CHECK-NEXT: call void @foo(i1 [[B]])
-; CHECK-NEXT: call void @foo(i1 [[C]])
-; CHECK-NEXT: call void @foo(i1 [[OR1]])
-; CHECK-NEXT: call void @foo(i1 [[OR2]])
+; CHECK-NEXT: call void @foo(i1 [[A_0]])
+; CHECK-NEXT: call void @foo(i1 [[B_0]])
+; CHECK-NEXT: call void @foo(i1 [[C_0]])
+; CHECK-NEXT: call void @foo(i1 [[OR1_0]])
+; CHECK-NEXT: call void @foo(i1 [[OR2_1]])
; CHECK-NEXT: ret void
;
%or1 = or i1 %a, %b
@@ -370,20 +393,24 @@ define void @test_and_or_mixed(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @test_and_or_mixed(
; CHECK-NEXT: [[OR:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[AND:%.*]] = and i1 [[OR]], [[C:%.*]]
+; CHECK: [[AND_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND]])
+; CHECK: [[AND_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND]])
+; CHECK: [[OR_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR]])
+; CHECK: [[C_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C]])
; CHECK-NEXT: br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A]])
; CHECK-NEXT: call void @foo(i1 [[B]])
-; CHECK-NEXT: call void @foo(i1 [[C]])
-; CHECK-NEXT: call void @foo(i1 [[OR]])
-; CHECK-NEXT: call void @foo(i1 [[AND]])
+; CHECK-NEXT: call void @foo(i1 [[C_0]])
+; CHECK-NEXT: call void @foo(i1 [[OR_0]])
+; CHECK-NEXT: call void @foo(i1 [[AND_0]])
; CHECK-NEXT: ret void
; CHECK: else:
; CHECK-NEXT: call void @foo(i1 [[A]])
; CHECK-NEXT: call void @foo(i1 [[B]])
; CHECK-NEXT: call void @foo(i1 [[C]])
; CHECK-NEXT: call void @foo(i1 [[OR]])
-; CHECK-NEXT: call void @foo(i1 [[AND]])
+; CHECK-NEXT: call void @foo(i1 [[AND_1]])
; CHECK-NEXT: ret void
;
%or = or i1 %a, %b
@@ -423,31 +450,38 @@ define void @test_deep_and_chain(i1 %a1) {
; CHECK-NEXT: [[A13:%.*]] = and i1 [[A12]], true
; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], true
; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], true
+; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
+; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
+; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A14]])
+; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A13]])
+; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A12]])
+; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A11]])
+; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A10]])
+; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A9]])
+; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A8]])
; CHECK-NEXT: br i1 [[A15]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: call void @foo(i1 [[A2]])
; CHECK-NEXT: call void @foo(i1 [[A3]])
; CHECK-NEXT: call void @foo(i1 [[A4]])
-; CHECK-NEXT: call void @foo(i1 [[A4]])
; CHECK-NEXT: call void @foo(i1 [[A5]])
; CHECK-NEXT: call void @foo(i1 [[A6]])
; CHECK-NEXT: call void @foo(i1 [[A7]])
-; CHECK-NEXT: call void @foo(i1 [[A8]])
-; CHECK-NEXT: call void @foo(i1 [[A9]])
-; CHECK-NEXT: call void @foo(i1 [[A10]])
-; CHECK-NEXT: call void @foo(i1 [[A11]])
-; CHECK-NEXT: call void @foo(i1 [[A12]])
-; CHECK-NEXT: call void @foo(i1 [[A13]])
-; CHECK-NEXT: call void @foo(i1 [[A14]])
-; CHECK-NEXT: call void @foo(i1 [[A15]])
+; CHECK-NEXT: call void @foo(i1 [[A8_0]])
+; CHECK-NEXT: call void @foo(i1 [[A9_0]])
+; CHECK-NEXT: call void @foo(i1 [[A10_0]])
+; CHECK-NEXT: call void @foo(i1 [[A11_0]])
+; CHECK-NEXT: call void @foo(i1 [[A12_0]])
+; CHECK-NEXT: call void @foo(i1 [[A13_0]])
+; CHECK-NEXT: call void @foo(i1 [[A14_0]])
+; CHECK-NEXT: call void @foo(i1 [[A15_0]])
; CHECK-NEXT: ret void
; CHECK: else:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: call void @foo(i1 [[A2]])
; CHECK-NEXT: call void @foo(i1 [[A3]])
; CHECK-NEXT: call void @foo(i1 [[A4]])
-; CHECK-NEXT: call void @foo(i1 [[A4]])
; CHECK-NEXT: call void @foo(i1 [[A5]])
; CHECK-NEXT: call void @foo(i1 [[A6]])
; CHECK-NEXT: call void @foo(i1 [[A7]])
@@ -458,7 +492,7 @@ define void @test_deep_and_chain(i1 %a1) {
; CHECK-NEXT: call void @foo(i1 [[A12]])
; CHECK-NEXT: call void @foo(i1 [[A13]])
; CHECK-NEXT: call void @foo(i1 [[A14]])
-; CHECK-NEXT: call void @foo(i1 [[A15]])
+; CHECK-NEXT: call void @foo(i1 [[A15_1]])
; CHECK-NEXT: ret void
;
%a2 = and i1 %a1, true
@@ -482,7 +516,6 @@ if:
call void @foo(i1 %a2)
call void @foo(i1 %a3)
call void @foo(i1 %a4)
- call void @foo(i1 %a4)
call void @foo(i1 %a5)
call void @foo(i1 %a6)
call void @foo(i1 %a7)
@@ -501,7 +534,6 @@ else:
call void @foo(i1 %a2)
call void @foo(i1 %a3)
call void @foo(i1 %a4)
- call void @foo(i1 %a4)
call void @foo(i1 %a5)
call void @foo(i1 %a6)
call void @foo(i1 %a7)
@@ -532,31 +564,38 @@ define void @test_deep_and_tree(i1 %a1) {
; CHECK-NEXT: [[A13:%.*]] = and i1 [[A12]], [[A12]]
; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], [[A13]]
; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], [[A14]]
+; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
+; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
+; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A14]])
+; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A13]])
+; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A12]])
+; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A11]])
+; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A10]])
+; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A9]])
+; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A8]])
; CHECK-NEXT: br i1 [[A15]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: call void @foo(i1 [[A2]])
; CHECK-NEXT: call void @foo(i1 [[A3]])
; CHECK-NEXT: call void @foo(i1 [[A4]])
-; CHECK-NEXT: call void @foo(i1 [[A4]])
; CHECK-NEXT: call void @foo(i1 [[A5]])
; CHECK-NEXT: call void @foo(i1 [[A6]])
; CHECK-NEXT: call void @foo(i1 [[A7]])
-; CHECK-NEXT: call void @foo(i1 [[A8]])
-; CHECK-NEXT: call void @foo(i1 [[A9]])
-; CHECK-NEXT: call void @foo(i1 [[A10]])
-; CHECK-NEXT: call void @foo(i1 [[A11]])
-; CHECK-NEXT: call void @foo(i1 [[A12]])
-; CHECK-NEXT: call void @foo(i1 [[A13]])
-; CHECK-NEXT: call void @foo(i1 [[A14]])
-; CHECK-NEXT: call void @foo(i1 [[A15]])
+; CHECK-NEXT: call void @foo(i1 [[A8_0]])
+; CHECK-NEXT: call void @foo(i1 [[A9_0]])
+; CHECK-NEXT: call void @foo(i1 [[A10_0]])
+; CHECK-NEXT: call void @foo(i1 [[A11_0]])
+; CHECK-NEXT: call void @foo(i1 [[A12_0]])
+; CHECK-NEXT: call void @foo(i1 [[A13_0]])
+; CHECK-NEXT: call void @foo(i1 [[A14_0]])
+; CHECK-NEXT: call void @foo(i1 [[A15_0]])
; CHECK-NEXT: ret void
; CHECK: else:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: call void @foo(i1 [[A2]])
; CHECK-NEXT: call void @foo(i1 [[A3]])
; CHECK-NEXT: call void @foo(i1 [[A4]])
-; CHECK-NEXT: call void @foo(i1 [[A4]])
; CHECK-NEXT: call void @foo(i1 [[A5]])
; CHECK-NEXT: call void @foo(i1 [[A6]])
; CHECK-NEXT: call void @foo(i1 [[A7]])
@@ -567,7 +606,7 @@ define void @test_deep_and_tree(i1 %a1) {
; CHECK-NEXT: call void @foo(i1 [[A12]])
; CHECK-NEXT: call void @foo(i1 [[A13]])
; CHECK-NEXT: call void @foo(i1 [[A14]])
-; CHECK-NEXT: call void @foo(i1 [[A15]])
+; CHECK-NEXT: call void @foo(i1 [[A15_1]])
; CHECK-NEXT: ret void
;
%a2 = and i1 %a1, %a1
@@ -591,7 +630,6 @@ if:
call void @foo(i1 %a2)
call void @foo(i1 %a3)
call void @foo(i1 %a4)
- call void @foo(i1 %a4)
call void @foo(i1 %a5)
call void @foo(i1 %a6)
call void @foo(i1 %a7)
@@ -610,7 +648,6 @@ else:
call void @foo(i1 %a2)
call void @foo(i1 %a3)
call void @foo(i1 %a4)
- call void @foo(i1 %a4)
call void @foo(i1 %a5)
call void @foo(i1 %a6)
call void @foo(i1 %a7)
@@ -641,13 +678,21 @@ define void @test_deep_or_tree(i1 %a1) {
; CHECK-NEXT: [[A13:%.*]] = or i1 [[A12]], [[A12]]
; CHECK-NEXT: [[A14:%.*]] = or i1 [[A13]], [[A13]]
; CHECK-NEXT: [[A15:%.*]] = or i1 [[A14]], [[A14]]
+; CHECK: [[A15_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
+; CHECK: [[A15_1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
+; CHECK: [[A14_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A14]])
+; CHECK: [[A13_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A13]])
+; CHECK: [[A12_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A12]])
+; CHECK: [[A11_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A11]])
+; CHECK: [[A10_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A10]])
+; CHECK: [[A9_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A9]])
+; CHECK: [[A8_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A8]])
; CHECK-NEXT: br i1 [[A15]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: call void @foo(i1 [[A2]])
; CHECK-NEXT: call void @foo(i1 [[A3]])
; CHECK-NEXT: call void @foo(i1 [[A4]])
-; CHECK-NEXT: call void @foo(i1 [[A4]])
; CHECK-NEXT: call void @foo(i1 [[A5]])
; CHECK-NEXT: call void @foo(i1 [[A6]])
; CHECK-NEXT: call void @foo(i1 [[A7]])
@@ -658,25 +703,24 @@ define void @test_deep_or_tree(i1 %a1) {
; CHECK-NEXT: call void @foo(i1 [[A12]])
; CHECK-NEXT: call void @foo(i1 [[A13]])
; CHECK-NEXT: call void @foo(i1 [[A14]])
-; CHECK-NEXT: call void @foo(i1 [[A15]])
+; CHECK-NEXT: call void @foo(i1 [[A15_0]])
; CHECK-NEXT: ret void
; CHECK: else:
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: call void @foo(i1 [[A2]])
; CHECK-NEXT: call void @foo(i1 [[A3]])
; CHECK-NEXT: call void @foo(i1 [[A4]])
-; CHECK-NEXT: call void @foo(i1 [[A4]])
; CHECK-NEXT: call void @foo(i1 [[A5]])
; CHECK-NEXT: call void @foo(i1 [[A6]])
; CHECK-NEXT: call void @foo(i1 [[A7]])
-; CHECK-NEXT: call void @foo(i1 [[A8]])
-; CHECK-NEXT: call void @foo(i1 [[A9]])
-; CHECK-NEXT: call void @foo(i1 [[A10]])
-; CHECK-NEXT: call void @foo(i1 [[A11]])
-; CHECK-NEXT: call void @foo(i1 [[A12]])
-; CHECK-NEXT: call void @foo(i1 [[A13]])
-; CHECK-NEXT: call void @foo(i1 [[A14]])
-; CHECK-NEXT: call void @foo(i1 [[A15]])
+; CHECK-NEXT: call void @foo(i1 [[A8_0]])
+; CHECK-NEXT: call void @foo(i1 [[A9_0]])
+; CHECK-NEXT: call void @foo(i1 [[A10_0]])
+; CHECK-NEXT: call void @foo(i1 [[A11_0]])
+; CHECK-NEXT: call void @foo(i1 [[A12_0]])
+; CHECK-NEXT: call void @foo(i1 [[A13_0]])
+; CHECK-NEXT: call void @foo(i1 [[A14_0]])
+; CHECK-NEXT: call void @foo(i1 [[A15_1]])
; CHECK-NEXT: ret void
;
%a2 = or i1 %a1, %a1
@@ -700,7 +744,6 @@ if:
call void @foo(i1 %a2)
call void @foo(i1 %a3)
call void @foo(i1 %a4)
- call void @foo(i1 %a4)
call void @foo(i1 %a5)
call void @foo(i1 %a6)
call void @foo(i1 %a7)
@@ -719,7 +762,6 @@ else:
call void @foo(i1 %a2)
call void @foo(i1 %a3)
call void @foo(i1 %a4)
- call void @foo(i1 %a4)
call void @foo(i1 %a5)
call void @foo(i1 %a6)
call void @foo(i1 %a7)
@@ -739,11 +781,16 @@ define void @test_assume_and_chain(i1 %a, i1 %b, i1 %c) {
; CHECK-NEXT: [[AND1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[C:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[AND2]])
-; CHECK-NEXT: call void @foo(i1 [[A]])
-; CHECK-NEXT: call void @foo(i1 [[B]])
-; CHECK-NEXT: call void @foo(i1 [[C]])
-; CHECK-NEXT: call void @foo(i1 [[AND1]])
-; CHECK-NEXT: call void @foo(i1 [[AND2]])
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[C]])
+; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[B]])
+; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A]])
+; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND1]])
+; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[AND2]])
+; CHECK-NEXT: call void @foo(i1 [[TMP3]])
+; CHECK-NEXT: call void @foo(i1 [[TMP2]])
+; CHECK-NEXT: call void @foo(i1 [[TMP1]])
+; CHECK-NEXT: call void @foo(i1 [[TMP4]])
+; CHECK-NEXT: call void @foo(i1 [[TMP5]])
; CHECK-NEXT: ret void
;
%and1 = and i1 %a, %b
@@ -762,11 +809,12 @@ define void @test_assume_or_chain(i1 %a, i1 %b, i1 %c) {
; CHECK-NEXT: [[OR1:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[C:%.*]]
; CHECK-NEXT: call void @llvm.assume(i1 [[OR2]])
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[OR2]])
; CHECK-NEXT: call void @foo(i1 [[A]])
; CHECK-NEXT: call void @foo(i1 [[B]])
; CHECK-NEXT: call void @foo(i1 [[C]])
; CHECK-NEXT: call void @foo(i1 [[OR1]])
-; CHECK-NEXT: call void @foo(i1 [[OR2]])
+; CHECK-NEXT: call void @foo(i1 [[TMP1]])
; CHECK-NEXT: ret void
;
%or1 = or i1 %a, %b
@@ -797,22 +845,29 @@ define void @test_assume_deep_and_tree(i1 %a1) {
; CHECK-NEXT: [[A14:%.*]] = and i1 [[A13]], [[A13]]
; CHECK-NEXT: [[A15:%.*]] = and i1 [[A14]], [[A14]]
; CHECK-NEXT: call void @llvm.assume(i1 [[A15]])
+; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A8]])
+; CHECK: [[TMP2:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A9]])
+; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A10]])
+; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A11]])
+; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A12]])
+; CHECK: [[TMP6:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A13]])
+; CHECK: [[TMP7:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A14]])
+; CHECK: [[TMP8:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[A15]])
; CHECK-NEXT: call void @foo(i1 [[A1]])
; CHECK-NEXT: call void @foo(i1 [[A2]])
; CHECK-NEXT: call void @foo(i1 [[A3]])
; CHECK-NEXT: call void @foo(i1 [[A4]])
-; CHECK-NEXT: call void @foo(i1 [[A4]])
; CHECK-NEXT: call void @foo(i1 [[A5]])
; CHECK-NEXT: call void @foo(i1 [[A6]])
; CHECK-NEXT: call void @foo(i1 [[A7]])
-; CHECK-NEXT: call void @foo(i1 [[A8]])
-; CHECK-NEXT: call void @foo(i1 [[A9]])
-; CHECK-NEXT: call void @foo(i1 [[A10]])
-; CHECK-NEXT: call void @foo(i1 [[A11]])
-; CHECK-NEXT: call void @foo(i1 [[A12]])
-; CHECK-NEXT: call void @foo(i1 [[A13]])
-; CHECK-NEXT: call void @foo(i1 [[A14]])
-; CHECK-NEXT: call void @foo(i1 [[A15]])
+; CHECK-NEXT: call void @foo(i1 [[TMP1]])
+; CHECK-NEXT: call void @foo(i1 [[TMP2]])
+; CHECK-NEXT: call void @foo(i1 [[TMP3]])
+; CHECK-NEXT: call void @foo(i1 [[TMP4]])
+; CHECK-NEXT: call void @foo(i1 [[TMP5]])
+; CHECK-NEXT: call void @foo(i1 [[TMP6]])
+; CHECK-NEXT: call void @foo(i1 [[TMP7]])
+; CHECK-NEXT: call void @foo(i1 [[TMP8]])
; CHECK-NEXT: ret void
;
%a2 = and i1 %a1, %a1
@@ -834,7 +889,6 @@ define void @test_assume_deep_and_tree(i1 %a1) {
call void @foo(i1 %a2)
call void @foo(i1 %a3)
call void @foo(i1 %a4)
- call void @foo(i1 %a4)
call void @foo(i1 %a5)
call void @foo(i1 %a6)
call void @foo(i1 %a7)
More information about the llvm-branch-commits
mailing list