aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombinePHI.cpp
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.ru>2022-02-10 16:44:39 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:39 +0300
commite9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch)
tree64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombinePHI.cpp
parent2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff)
downloadydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombinePHI.cpp')
-rw-r--r--contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombinePHI.cpp438
1 files changed, 219 insertions, 219 deletions
diff --git a/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombinePHI.cpp b/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombinePHI.cpp
index e05dda3670..b211b08136 100644
--- a/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -13,14 +13,14 @@
#include "InstCombineInternal.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Transforms/InstCombine/InstCombiner.h"
+#include "llvm/Transforms/InstCombine/InstCombiner.h"
#include "llvm/Transforms/Utils/Local.h"
-
+
using namespace llvm;
using namespace llvm::PatternMatch;
@@ -30,16 +30,16 @@ static cl::opt<unsigned>
MaxNumPhis("instcombine-max-num-phis", cl::init(512),
cl::desc("Maximum number phis to handle in intptr/ptrint folding"));
-STATISTIC(NumPHIsOfInsertValues,
- "Number of phi-of-insertvalue turned into insertvalue-of-phis");
-STATISTIC(NumPHIsOfExtractValues,
- "Number of phi-of-extractvalue turned into extractvalue-of-phi");
-STATISTIC(NumPHICSEs, "Number of PHI's that got CSE'd");
-
+STATISTIC(NumPHIsOfInsertValues,
+ "Number of phi-of-insertvalue turned into insertvalue-of-phis");
+STATISTIC(NumPHIsOfExtractValues,
+ "Number of phi-of-extractvalue turned into extractvalue-of-phi");
+STATISTIC(NumPHICSEs, "Number of PHI's that got CSE'd");
+
/// The PHI arguments will be folded into a single operation with a PHI node
/// as input. The debug location of the single operation will be the merged
/// locations of the original PHI node arguments.
-void InstCombinerImpl::PHIArgMergedDebugLoc(Instruction *Inst, PHINode &PN) {
+void InstCombinerImpl::PHIArgMergedDebugLoc(Instruction *Inst, PHINode &PN) {
auto *FirstInst = cast<Instruction>(PN.getIncomingValue(0));
Inst->setDebugLoc(FirstInst->getDebugLoc());
// We do not expect a CallInst here, otherwise, N-way merging of DebugLoc
@@ -102,7 +102,7 @@ void InstCombinerImpl::PHIArgMergedDebugLoc(Instruction *Inst, PHINode &PN) {
// ptr_val_inc = ...
// ...
//
-Instruction *InstCombinerImpl::foldIntegerTypedPHI(PHINode &PN) {
+Instruction *InstCombinerImpl::foldIntegerTypedPHI(PHINode &PN) {
if (!PN.getType()->isIntegerTy())
return nullptr;
if (!PN.hasOneUse())
@@ -299,86 +299,86 @@ Instruction *InstCombinerImpl::foldIntegerTypedPHI(PHINode &PN) {
IntToPtr->getOperand(0)->getType());
}
-/// If we have something like phi [insertvalue(a,b,0), insertvalue(c,d,0)],
-/// turn this into a phi[a,c] and phi[b,d] and a single insertvalue.
-Instruction *
-InstCombinerImpl::foldPHIArgInsertValueInstructionIntoPHI(PHINode &PN) {
- auto *FirstIVI = cast<InsertValueInst>(PN.getIncomingValue(0));
-
- // Scan to see if all operands are `insertvalue`'s with the same indicies,
- // and all have a single use.
- for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
- auto *I = dyn_cast<InsertValueInst>(PN.getIncomingValue(i));
- if (!I || !I->hasOneUser() || I->getIndices() != FirstIVI->getIndices())
- return nullptr;
- }
-
- // For each operand of an `insertvalue`
- std::array<PHINode *, 2> NewOperands;
- for (int OpIdx : {0, 1}) {
- auto *&NewOperand = NewOperands[OpIdx];
- // Create a new PHI node to receive the values the operand has in each
- // incoming basic block.
- NewOperand = PHINode::Create(
- FirstIVI->getOperand(OpIdx)->getType(), PN.getNumIncomingValues(),
- FirstIVI->getOperand(OpIdx)->getName() + ".pn");
- // And populate each operand's PHI with said values.
- for (auto Incoming : zip(PN.blocks(), PN.incoming_values()))
- NewOperand->addIncoming(
- cast<InsertValueInst>(std::get<1>(Incoming))->getOperand(OpIdx),
- std::get<0>(Incoming));
- InsertNewInstBefore(NewOperand, PN);
- }
-
- // And finally, create `insertvalue` over the newly-formed PHI nodes.
- auto *NewIVI = InsertValueInst::Create(NewOperands[0], NewOperands[1],
- FirstIVI->getIndices(), PN.getName());
-
- PHIArgMergedDebugLoc(NewIVI, PN);
- ++NumPHIsOfInsertValues;
- return NewIVI;
-}
-
-/// If we have something like phi [extractvalue(a,0), extractvalue(b,0)],
-/// turn this into a phi[a,b] and a single extractvalue.
-Instruction *
-InstCombinerImpl::foldPHIArgExtractValueInstructionIntoPHI(PHINode &PN) {
- auto *FirstEVI = cast<ExtractValueInst>(PN.getIncomingValue(0));
-
- // Scan to see if all operands are `extractvalue`'s with the same indicies,
- // and all have a single use.
- for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
- auto *I = dyn_cast<ExtractValueInst>(PN.getIncomingValue(i));
- if (!I || !I->hasOneUser() || I->getIndices() != FirstEVI->getIndices() ||
- I->getAggregateOperand()->getType() !=
- FirstEVI->getAggregateOperand()->getType())
- return nullptr;
- }
-
- // Create a new PHI node to receive the values the aggregate operand has
- // in each incoming basic block.
- auto *NewAggregateOperand = PHINode::Create(
- FirstEVI->getAggregateOperand()->getType(), PN.getNumIncomingValues(),
- FirstEVI->getAggregateOperand()->getName() + ".pn");
- // And populate the PHI with said values.
- for (auto Incoming : zip(PN.blocks(), PN.incoming_values()))
- NewAggregateOperand->addIncoming(
- cast<ExtractValueInst>(std::get<1>(Incoming))->getAggregateOperand(),
- std::get<0>(Incoming));
- InsertNewInstBefore(NewAggregateOperand, PN);
-
- // And finally, create `extractvalue` over the newly-formed PHI nodes.
- auto *NewEVI = ExtractValueInst::Create(NewAggregateOperand,
- FirstEVI->getIndices(), PN.getName());
-
- PHIArgMergedDebugLoc(NewEVI, PN);
- ++NumPHIsOfExtractValues;
- return NewEVI;
-}
-
+/// If we have something like phi [insertvalue(a,b,0), insertvalue(c,d,0)],
+/// turn this into a phi[a,c] and phi[b,d] and a single insertvalue.
+Instruction *
+InstCombinerImpl::foldPHIArgInsertValueInstructionIntoPHI(PHINode &PN) {
+ auto *FirstIVI = cast<InsertValueInst>(PN.getIncomingValue(0));
+
+ // Scan to see if all operands are `insertvalue`'s with the same indicies,
+ // and all have a single use.
+ for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
+ auto *I = dyn_cast<InsertValueInst>(PN.getIncomingValue(i));
+ if (!I || !I->hasOneUser() || I->getIndices() != FirstIVI->getIndices())
+ return nullptr;
+ }
+
+ // For each operand of an `insertvalue`
+ std::array<PHINode *, 2> NewOperands;
+ for (int OpIdx : {0, 1}) {
+ auto *&NewOperand = NewOperands[OpIdx];
+ // Create a new PHI node to receive the values the operand has in each
+ // incoming basic block.
+ NewOperand = PHINode::Create(
+ FirstIVI->getOperand(OpIdx)->getType(), PN.getNumIncomingValues(),
+ FirstIVI->getOperand(OpIdx)->getName() + ".pn");
+ // And populate each operand's PHI with said values.
+ for (auto Incoming : zip(PN.blocks(), PN.incoming_values()))
+ NewOperand->addIncoming(
+ cast<InsertValueInst>(std::get<1>(Incoming))->getOperand(OpIdx),
+ std::get<0>(Incoming));
+ InsertNewInstBefore(NewOperand, PN);
+ }
+
+ // And finally, create `insertvalue` over the newly-formed PHI nodes.
+ auto *NewIVI = InsertValueInst::Create(NewOperands[0], NewOperands[1],
+ FirstIVI->getIndices(), PN.getName());
+
+ PHIArgMergedDebugLoc(NewIVI, PN);
+ ++NumPHIsOfInsertValues;
+ return NewIVI;
+}
+
+/// If we have something like phi [extractvalue(a,0), extractvalue(b,0)],
+/// turn this into a phi[a,b] and a single extractvalue.
+Instruction *
+InstCombinerImpl::foldPHIArgExtractValueInstructionIntoPHI(PHINode &PN) {
+ auto *FirstEVI = cast<ExtractValueInst>(PN.getIncomingValue(0));
+
+ // Scan to see if all operands are `extractvalue`'s with the same indicies,
+ // and all have a single use.
+ for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
+ auto *I = dyn_cast<ExtractValueInst>(PN.getIncomingValue(i));
+ if (!I || !I->hasOneUser() || I->getIndices() != FirstEVI->getIndices() ||
+ I->getAggregateOperand()->getType() !=
+ FirstEVI->getAggregateOperand()->getType())
+ return nullptr;
+ }
+
+ // Create a new PHI node to receive the values the aggregate operand has
+ // in each incoming basic block.
+ auto *NewAggregateOperand = PHINode::Create(
+ FirstEVI->getAggregateOperand()->getType(), PN.getNumIncomingValues(),
+ FirstEVI->getAggregateOperand()->getName() + ".pn");
+ // And populate the PHI with said values.
+ for (auto Incoming : zip(PN.blocks(), PN.incoming_values()))
+ NewAggregateOperand->addIncoming(
+ cast<ExtractValueInst>(std::get<1>(Incoming))->getAggregateOperand(),
+ std::get<0>(Incoming));
+ InsertNewInstBefore(NewAggregateOperand, PN);
+
+ // And finally, create `extractvalue` over the newly-formed PHI nodes.
+ auto *NewEVI = ExtractValueInst::Create(NewAggregateOperand,
+ FirstEVI->getIndices(), PN.getName());
+
+ PHIArgMergedDebugLoc(NewEVI, PN);
+ ++NumPHIsOfExtractValues;
+ return NewEVI;
+}
+
/// If we have something like phi [add (a,b), add(a,c)] and if a/b/c and the
-/// adds all have a single user, turn this into a phi and a single binop.
-Instruction *InstCombinerImpl::foldPHIArgBinOpIntoPHI(PHINode &PN) {
+/// adds all have a single user, turn this into a phi and a single binop.
+Instruction *InstCombinerImpl::foldPHIArgBinOpIntoPHI(PHINode &PN) {
Instruction *FirstInst = cast<Instruction>(PN.getIncomingValue(0));
assert(isa<BinaryOperator>(FirstInst) || isa<CmpInst>(FirstInst));
unsigned Opc = FirstInst->getOpcode();
@@ -388,10 +388,10 @@ Instruction *InstCombinerImpl::foldPHIArgBinOpIntoPHI(PHINode &PN) {
Type *LHSType = LHSVal->getType();
Type *RHSType = RHSVal->getType();
- // Scan to see if all operands are the same opcode, and all have one user.
+ // Scan to see if all operands are the same opcode, and all have one user.
for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
Instruction *I = dyn_cast<Instruction>(PN.getIncomingValue(i));
- if (!I || I->getOpcode() != Opc || !I->hasOneUser() ||
+ if (!I || I->getOpcode() != Opc || !I->hasOneUser() ||
// Verify type of the LHS matches so we don't fold cmp's of different
// types.
I->getOperand(0)->getType() != LHSType ||
@@ -471,7 +471,7 @@ Instruction *InstCombinerImpl::foldPHIArgBinOpIntoPHI(PHINode &PN) {
return NewBinOp;
}
-Instruction *InstCombinerImpl::foldPHIArgGEPIntoPHI(PHINode &PN) {
+Instruction *InstCombinerImpl::foldPHIArgGEPIntoPHI(PHINode &PN) {
GetElementPtrInst *FirstInst =cast<GetElementPtrInst>(PN.getIncomingValue(0));
SmallVector<Value*, 16> FixedOperands(FirstInst->op_begin(),
@@ -487,12 +487,12 @@ Instruction *InstCombinerImpl::foldPHIArgGEPIntoPHI(PHINode &PN) {
bool AllInBounds = true;
- // Scan to see if all operands are the same opcode, and all have one user.
+ // Scan to see if all operands are the same opcode, and all have one user.
for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
- GetElementPtrInst *GEP =
- dyn_cast<GetElementPtrInst>(PN.getIncomingValue(i));
- if (!GEP || !GEP->hasOneUser() || GEP->getType() != FirstInst->getType() ||
- GEP->getNumOperands() != FirstInst->getNumOperands())
+ GetElementPtrInst *GEP =
+ dyn_cast<GetElementPtrInst>(PN.getIncomingValue(i));
+ if (!GEP || !GEP->hasOneUser() || GEP->getType() != FirstInst->getType() ||
+ GEP->getNumOperands() != FirstInst->getNumOperands())
return nullptr;
AllInBounds &= GEP->isInBounds();
@@ -592,14 +592,14 @@ static bool isSafeAndProfitableToSinkLoad(LoadInst *L) {
BasicBlock::iterator BBI = L->getIterator(), E = L->getParent()->end();
for (++BBI; BBI != E; ++BBI)
- if (BBI->mayWriteToMemory()) {
- // Calls that only access inaccessible memory do not block sinking the
- // load.
- if (auto *CB = dyn_cast<CallBase>(BBI))
- if (CB->onlyAccessesInaccessibleMemory())
- continue;
+ if (BBI->mayWriteToMemory()) {
+ // Calls that only access inaccessible memory do not block sinking the
+ // load.
+ if (auto *CB = dyn_cast<CallBase>(BBI))
+ if (CB->onlyAccessesInaccessibleMemory())
+ continue;
return false;
- }
+ }
// Check for non-address taken alloca. If not address-taken already, it isn't
// profitable to do this xform.
@@ -632,7 +632,7 @@ static bool isSafeAndProfitableToSinkLoad(LoadInst *L) {
return true;
}
-Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) {
+Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) {
LoadInst *FirstLI = cast<LoadInst>(PN.getIncomingValue(0));
// FIXME: This is overconservative; this transform is allowed in some cases
@@ -665,7 +665,7 @@ Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) {
// Check to see if all arguments are the same operation.
for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) {
LoadInst *LI = dyn_cast<LoadInst>(PN.getIncomingValue(i));
- if (!LI || !LI->hasOneUser())
+ if (!LI || !LI->hasOneUser())
return nullptr;
// We can't sink the load if the loaded value could be modified between
@@ -746,7 +746,7 @@ Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) {
/// TODO: This function could handle other cast types, but then it might
/// require special-casing a cast from the 'i1' type. See the comment in
/// FoldPHIArgOpIntoPHI() about pessimizing illegal integer types.
-Instruction *InstCombinerImpl::foldPHIArgZextsIntoPHI(PHINode &Phi) {
+Instruction *InstCombinerImpl::foldPHIArgZextsIntoPHI(PHINode &Phi) {
// We cannot create a new instruction after the PHI if the terminator is an
// EHPad because there is no valid insertion point.
if (Instruction *TI = Phi.getParent()->getTerminator())
@@ -778,8 +778,8 @@ Instruction *InstCombinerImpl::foldPHIArgZextsIntoPHI(PHINode &Phi) {
unsigned NumConsts = 0;
for (Value *V : Phi.incoming_values()) {
if (auto *Zext = dyn_cast<ZExtInst>(V)) {
- // All zexts must be identical and have one user.
- if (Zext->getSrcTy() != NarrowType || !Zext->hasOneUser())
+ // All zexts must be identical and have one user.
+ if (Zext->getSrcTy() != NarrowType || !Zext->hasOneUser())
return nullptr;
NewIncoming.push_back(Zext->getOperand(0));
NumZexts++;
@@ -820,7 +820,7 @@ Instruction *InstCombinerImpl::foldPHIArgZextsIntoPHI(PHINode &Phi) {
/// If all operands to a PHI node are the same "unary" operator and they all are
/// only used by the PHI, PHI together their inputs, and do the operation once,
/// to the result of the PHI.
-Instruction *InstCombinerImpl::foldPHIArgOpIntoPHI(PHINode &PN) {
+Instruction *InstCombinerImpl::foldPHIArgOpIntoPHI(PHINode &PN) {
// We cannot create a new instruction after the PHI if the terminator is an
// EHPad because there is no valid insertion point.
if (Instruction *TI = PN.getParent()->getTerminator())
@@ -830,13 +830,13 @@ Instruction *InstCombinerImpl::foldPHIArgOpIntoPHI(PHINode &PN) {
Instruction *FirstInst = cast<Instruction>(PN.getIncomingValue(0));
if (isa<GetElementPtrInst>(FirstInst))
- return foldPHIArgGEPIntoPHI(PN);
+ return foldPHIArgGEPIntoPHI(PN);
if (isa<LoadInst>(FirstInst))
- return foldPHIArgLoadIntoPHI(PN);
- if (isa<InsertValueInst>(FirstInst))
- return foldPHIArgInsertValueInstructionIntoPHI(PN);
- if (isa<ExtractValueInst>(FirstInst))
- return foldPHIArgExtractValueInstructionIntoPHI(PN);
+ return foldPHIArgLoadIntoPHI(PN);
+ if (isa<InsertValueInst>(FirstInst))
+ return foldPHIArgInsertValueInstructionIntoPHI(PN);
+ if (isa<ExtractValueInst>(FirstInst))
+ return foldPHIArgExtractValueInstructionIntoPHI(PN);
// Scan the instruction, looking for input operations that can be folded away.
// If all input operands to the phi are the same instruction (e.g. a cast from
@@ -859,7 +859,7 @@ Instruction *InstCombinerImpl::foldPHIArgOpIntoPHI(PHINode &PN) {
// otherwise call FoldPHIArgBinOpIntoPHI.
ConstantOp = dyn_cast<Constant>(FirstInst->getOperand(1));
if (!ConstantOp)
- return foldPHIArgBinOpIntoPHI(PN);
+ return foldPHIArgBinOpIntoPHI(PN);
} else {
return nullptr; // Cannot fold this operation.
}
@@ -867,7 +867,7 @@ Instruction *InstCombinerImpl::foldPHIArgOpIntoPHI(PHINode &PN) {
// Check to see if all arguments are the same operation.
for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) {
Instruction *I = dyn_cast<Instruction>(PN.getIncomingValue(i));
- if (!I || !I->hasOneUser() || !I->isSameOperationAs(FirstInst))
+ if (!I || !I->hasOneUser() || !I->isSameOperationAs(FirstInst))
return nullptr;
if (CastSrcTy) {
if (I->getOperand(0)->getType() != CastSrcTy)
@@ -1019,7 +1019,7 @@ struct LoweredPHIRecord {
LoweredPHIRecord(PHINode *pn, unsigned Sh)
: PN(pn), Shift(Sh), Width(0) {}
};
-} // namespace
+} // namespace
namespace llvm {
template<>
@@ -1040,7 +1040,7 @@ namespace llvm {
LHS.Width == RHS.Width;
}
};
-} // namespace llvm
+} // namespace llvm
/// This is an integer PHI and we know that it has an illegal type: see if it is
@@ -1051,7 +1051,7 @@ namespace llvm {
/// TODO: The user of the trunc may be an bitcast to float/double/vector or an
/// inttoptr. We should produce new PHIs in the right type.
///
-Instruction *InstCombinerImpl::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
+Instruction *InstCombinerImpl::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
// PHIUsers - Keep track of all of the truncated values extracted from a set
// of PHIs, along with their offset. These are the things we want to rewrite.
SmallVector<PHIUsageRecord, 16> PHIUsers;
@@ -1225,85 +1225,85 @@ Instruction *InstCombinerImpl::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
return replaceInstUsesWith(FirstPhi, Undef);
}
-static Value *SimplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
- const DominatorTree &DT) {
- // Simplify the following patterns:
- // if (cond)
- // / \
- // ... ...
- // \ /
- // phi [true] [false]
- if (!PN.getType()->isIntegerTy(1))
- return nullptr;
-
- if (PN.getNumOperands() != 2)
- return nullptr;
-
- // Make sure all inputs are constants.
- if (!all_of(PN.operands(), [](Value *V) { return isa<ConstantInt>(V); }))
- return nullptr;
-
- BasicBlock *BB = PN.getParent();
- // Do not bother with unreachable instructions.
- if (!DT.isReachableFromEntry(BB))
- return nullptr;
-
- // Same inputs.
- if (PN.getOperand(0) == PN.getOperand(1))
- return PN.getOperand(0);
-
- BasicBlock *TruePred = nullptr, *FalsePred = nullptr;
- for (auto *Pred : predecessors(BB)) {
- auto *Input = cast<ConstantInt>(PN.getIncomingValueForBlock(Pred));
- if (Input->isAllOnesValue())
- TruePred = Pred;
- else
- FalsePred = Pred;
- }
- assert(TruePred && FalsePred && "Must be!");
-
- // Check which edge of the dominator dominates the true input. If it is the
- // false edge, we should invert the condition.
- auto *IDom = DT.getNode(BB)->getIDom()->getBlock();
- auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
- if (!BI || BI->isUnconditional())
- return nullptr;
-
- // Check that edges outgoing from the idom's terminators dominate respective
- // inputs of the Phi.
- BasicBlockEdge TrueOutEdge(IDom, BI->getSuccessor(0));
- BasicBlockEdge FalseOutEdge(IDom, BI->getSuccessor(1));
-
- BasicBlockEdge TrueIncEdge(TruePred, BB);
- BasicBlockEdge FalseIncEdge(FalsePred, BB);
-
- auto *Cond = BI->getCondition();
- if (DT.dominates(TrueOutEdge, TrueIncEdge) &&
- DT.dominates(FalseOutEdge, FalseIncEdge))
- // This Phi is actually equivalent to branching condition of IDom.
- return Cond;
- else if (DT.dominates(TrueOutEdge, FalseIncEdge) &&
- DT.dominates(FalseOutEdge, TrueIncEdge)) {
- // This Phi is actually opposite to branching condition of IDom. We invert
- // the condition that will potentially open up some opportunities for
- // sinking.
- auto InsertPt = BB->getFirstInsertionPt();
- if (InsertPt != BB->end()) {
- Self.Builder.SetInsertPoint(&*InsertPt);
- return Self.Builder.CreateNot(Cond);
- }
- }
-
- return nullptr;
-}
-
+static Value *SimplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
+ const DominatorTree &DT) {
+ // Simplify the following patterns:
+ // if (cond)
+ // / \
+ // ... ...
+ // \ /
+ // phi [true] [false]
+ if (!PN.getType()->isIntegerTy(1))
+ return nullptr;
+
+ if (PN.getNumOperands() != 2)
+ return nullptr;
+
+ // Make sure all inputs are constants.
+ if (!all_of(PN.operands(), [](Value *V) { return isa<ConstantInt>(V); }))
+ return nullptr;
+
+ BasicBlock *BB = PN.getParent();
+ // Do not bother with unreachable instructions.
+ if (!DT.isReachableFromEntry(BB))
+ return nullptr;
+
+ // Same inputs.
+ if (PN.getOperand(0) == PN.getOperand(1))
+ return PN.getOperand(0);
+
+ BasicBlock *TruePred = nullptr, *FalsePred = nullptr;
+ for (auto *Pred : predecessors(BB)) {
+ auto *Input = cast<ConstantInt>(PN.getIncomingValueForBlock(Pred));
+ if (Input->isAllOnesValue())
+ TruePred = Pred;
+ else
+ FalsePred = Pred;
+ }
+ assert(TruePred && FalsePred && "Must be!");
+
+ // Check which edge of the dominator dominates the true input. If it is the
+ // false edge, we should invert the condition.
+ auto *IDom = DT.getNode(BB)->getIDom()->getBlock();
+ auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
+ if (!BI || BI->isUnconditional())
+ return nullptr;
+
+ // Check that edges outgoing from the idom's terminators dominate respective
+ // inputs of the Phi.
+ BasicBlockEdge TrueOutEdge(IDom, BI->getSuccessor(0));
+ BasicBlockEdge FalseOutEdge(IDom, BI->getSuccessor(1));
+
+ BasicBlockEdge TrueIncEdge(TruePred, BB);
+ BasicBlockEdge FalseIncEdge(FalsePred, BB);
+
+ auto *Cond = BI->getCondition();
+ if (DT.dominates(TrueOutEdge, TrueIncEdge) &&
+ DT.dominates(FalseOutEdge, FalseIncEdge))
+ // This Phi is actually equivalent to branching condition of IDom.
+ return Cond;
+ else if (DT.dominates(TrueOutEdge, FalseIncEdge) &&
+ DT.dominates(FalseOutEdge, TrueIncEdge)) {
+ // This Phi is actually opposite to branching condition of IDom. We invert
+ // the condition that will potentially open up some opportunities for
+ // sinking.
+ auto InsertPt = BB->getFirstInsertionPt();
+ if (InsertPt != BB->end()) {
+ Self.Builder.SetInsertPoint(&*InsertPt);
+ return Self.Builder.CreateNot(Cond);
+ }
+ }
+
+ return nullptr;
+}
+
// PHINode simplification
//
-Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
+Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
if (Value *V = SimplifyInstruction(&PN, SQ.getWithInstruction(&PN)))
return replaceInstUsesWith(PN, V);
- if (Instruction *Result = foldPHIArgZextsIntoPHI(PN))
+ if (Instruction *Result = foldPHIArgZextsIntoPHI(PN))
return Result;
// If all PHI operands are the same operation, pull them through the PHI,
@@ -1311,16 +1311,16 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
if (isa<Instruction>(PN.getIncomingValue(0)) &&
isa<Instruction>(PN.getIncomingValue(1)) &&
cast<Instruction>(PN.getIncomingValue(0))->getOpcode() ==
- cast<Instruction>(PN.getIncomingValue(1))->getOpcode() &&
- PN.getIncomingValue(0)->hasOneUser())
- if (Instruction *Result = foldPHIArgOpIntoPHI(PN))
+ cast<Instruction>(PN.getIncomingValue(1))->getOpcode() &&
+ PN.getIncomingValue(0)->hasOneUser())
+ if (Instruction *Result = foldPHIArgOpIntoPHI(PN))
return Result;
// If this is a trivial cycle in the PHI node graph, remove it. Basically, if
// this PHI only has a single use (a PHI), and if that PHI only has one use (a
// PHI)... break the cycle.
if (PN.hasOneUse()) {
- if (Instruction *Result = foldIntegerTypedPHI(PN))
+ if (Instruction *Result = foldIntegerTypedPHI(PN))
return Result;
Instruction *PHIUser = cast<Instruction>(PN.user_back());
@@ -1433,21 +1433,21 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
}
}
- // Is there an identical PHI node in this basic block?
- for (PHINode &IdenticalPN : PN.getParent()->phis()) {
- // Ignore the PHI node itself.
- if (&IdenticalPN == &PN)
- continue;
- // Note that even though we've just canonicalized this PHI, due to the
- // worklist visitation order, there are no guarantess that *every* PHI
- // has been canonicalized, so we can't just compare operands ranges.
- if (!PN.isIdenticalToWhenDefined(&IdenticalPN))
- continue;
- // Just use that PHI instead then.
- ++NumPHICSEs;
- return replaceInstUsesWith(PN, &IdenticalPN);
- }
-
+ // Is there an identical PHI node in this basic block?
+ for (PHINode &IdenticalPN : PN.getParent()->phis()) {
+ // Ignore the PHI node itself.
+ if (&IdenticalPN == &PN)
+ continue;
+ // Note that even though we've just canonicalized this PHI, due to the
+ // worklist visitation order, there are no guarantess that *every* PHI
+ // has been canonicalized, so we can't just compare operands ranges.
+ if (!PN.isIdenticalToWhenDefined(&IdenticalPN))
+ continue;
+ // Just use that PHI instead then.
+ ++NumPHICSEs;
+ return replaceInstUsesWith(PN, &IdenticalPN);
+ }
+
// If this is an integer PHI and we know that it has an illegal type, see if
// it is only used by trunc or trunc(lshr) operations. If so, we split the
// PHI into the various pieces being extracted. This sort of thing is
@@ -1457,9 +1457,9 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
if (Instruction *Res = SliceUpIllegalIntegerPHI(PN))
return Res;
- // Ultimately, try to replace this Phi with a dominating condition.
- if (auto *V = SimplifyUsingControlFlow(*this, PN, DT))
- return replaceInstUsesWith(PN, V);
-
+ // Ultimately, try to replace this Phi with a dominating condition.
+ if (auto *V = SimplifyUsingControlFlow(*this, PN, DT))
+ return replaceInstUsesWith(PN, V);
+
return nullptr;
}