[ValueTracking] add helper function for testing implied condition; NFCI
We were duplicating code around the existing isImpliedCondition() that checks for a predecessor block/dominating condition, so make that a wrapper call. llvm-svn: 348088
This commit is contained in:
parent
204e4110e0
commit
7d82d37854
|
@ -610,6 +610,12 @@ class Value;
|
||||||
Optional<bool> isImpliedCondition(const Value *LHS, const Value *RHS,
|
Optional<bool> isImpliedCondition(const Value *LHS, const Value *RHS,
|
||||||
const DataLayout &DL, bool LHSIsTrue = true,
|
const DataLayout &DL, bool LHSIsTrue = true,
|
||||||
unsigned Depth = 0);
|
unsigned Depth = 0);
|
||||||
|
|
||||||
|
/// Return the boolean condition value in the context of the given instruction
|
||||||
|
/// if it is known based on dominating conditions.
|
||||||
|
Optional<bool> isImpliedByDomCondition(const Value *Cond,
|
||||||
|
const Instruction *ContextI,
|
||||||
|
const DataLayout &DL);
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_ANALYSIS_VALUETRACKING_H
|
#endif // LLVM_ANALYSIS_VALUETRACKING_H
|
||||||
|
|
|
@ -3924,42 +3924,6 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to determine the result of a select based on a dominating condition.
|
|
||||||
static Value *foldSelectWithDominatingCond(Value *Cond, Value *TV, Value *FV,
|
|
||||||
const SimplifyQuery &Q) {
|
|
||||||
// First, make sure that we have a select in a basic block.
|
|
||||||
// We don't know if we are called from some incomplete state.
|
|
||||||
if (!Q.CxtI || !Q.CxtI->getParent())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// TODO: This is a poor/cheap way to determine dominance. Should we use the
|
|
||||||
// dominator tree in the SimplifyQuery instead?
|
|
||||||
const BasicBlock *SelectBB = Q.CxtI->getParent();
|
|
||||||
const BasicBlock *PredBB = SelectBB->getSinglePredecessor();
|
|
||||||
if (!PredBB)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// We need a conditional branch in the predecessor.
|
|
||||||
Value *PredCond;
|
|
||||||
BasicBlock *TrueBB, *FalseBB;
|
|
||||||
if (!match(PredBB->getTerminator(), m_Br(m_Value(PredCond), TrueBB, FalseBB)))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// The branch should get simplified. Don't bother simplifying the select.
|
|
||||||
if (TrueBB == FalseBB)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
assert((TrueBB == SelectBB || FalseBB == SelectBB) &&
|
|
||||||
"Predecessor block does not point to successor?");
|
|
||||||
|
|
||||||
// Is the select condition implied by the predecessor condition?
|
|
||||||
bool CondIsTrue = TrueBB == SelectBB;
|
|
||||||
Optional<bool> Implied = isImpliedCondition(PredCond, Cond, Q.DL, CondIsTrue);
|
|
||||||
if (!Implied)
|
|
||||||
return nullptr;
|
|
||||||
return *Implied ? TV : FV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given operands for a SelectInst, see if we can fold the result.
|
/// Given operands for a SelectInst, see if we can fold the result.
|
||||||
/// If not, this returns null.
|
/// If not, this returns null.
|
||||||
static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||||
|
@ -4002,8 +3966,9 @@ static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||||
if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal))
|
if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal))
|
||||||
return V;
|
return V;
|
||||||
|
|
||||||
if (Value *V = foldSelectWithDominatingCond(Cond, TrueVal, FalseVal, Q))
|
Optional<bool> Imp = isImpliedByDomCondition(Cond, Q.CxtI, Q.DL);
|
||||||
return V;
|
if (Imp)
|
||||||
|
return *Imp ? TrueVal : FalseVal;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5378,3 +5378,35 @@ Optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS,
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<bool> llvm::isImpliedByDomCondition(const Value *Cond,
|
||||||
|
const Instruction *ContextI,
|
||||||
|
const DataLayout &DL) {
|
||||||
|
assert(Cond->getType()->isIntOrIntVectorTy(1) && "Condition must be bool");
|
||||||
|
if (!ContextI || !ContextI->getParent())
|
||||||
|
return None;
|
||||||
|
|
||||||
|
// TODO: This is a poor/cheap way to determine dominance. Should we use a
|
||||||
|
// dominator tree (eg, from a SimplifyQuery) instead?
|
||||||
|
const BasicBlock *ContextBB = ContextI->getParent();
|
||||||
|
const BasicBlock *PredBB = ContextBB->getSinglePredecessor();
|
||||||
|
if (!PredBB)
|
||||||
|
return None;
|
||||||
|
|
||||||
|
// We need a conditional branch in the predecessor.
|
||||||
|
Value *PredCond;
|
||||||
|
BasicBlock *TrueBB, *FalseBB;
|
||||||
|
if (!match(PredBB->getTerminator(), m_Br(m_Value(PredCond), TrueBB, FalseBB)))
|
||||||
|
return None;
|
||||||
|
|
||||||
|
// The branch should get simplified. Don't bother simplifying this condition.
|
||||||
|
if (TrueBB == FalseBB)
|
||||||
|
return None;
|
||||||
|
|
||||||
|
assert((TrueBB == ContextBB || FalseBB == ContextBB) &&
|
||||||
|
"Predecessor block does not point to successor?");
|
||||||
|
|
||||||
|
// Is this condition implied by the predecessor condition?
|
||||||
|
bool CondIsTrue = TrueBB == ContextBB;
|
||||||
|
return isImpliedCondition(PredCond, Cond, DL, CondIsTrue);
|
||||||
|
}
|
||||||
|
|
|
@ -5854,28 +5854,17 @@ bool SimplifyCFGOpt::SimplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
|
||||||
if (SimplifyBranchOnICmpChain(BI, Builder, DL))
|
if (SimplifyBranchOnICmpChain(BI, Builder, DL))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// If this basic block has a single dominating predecessor block and the
|
// If this basic block has dominating predecessor blocks and the dominating
|
||||||
// dominating block's condition implies BI's condition, we know the direction
|
// blocks' conditions imply BI's condition, we know the direction of BI.
|
||||||
// of the BI branch.
|
Optional<bool> Imp = isImpliedByDomCondition(BI->getCondition(), BI, DL);
|
||||||
if (BasicBlock *Dom = BB->getSinglePredecessor()) {
|
if (Imp) {
|
||||||
auto *PBI = dyn_cast_or_null<BranchInst>(Dom->getTerminator());
|
// Turn this into a branch on constant.
|
||||||
if (PBI && PBI->isConditional() &&
|
auto *OldCond = BI->getCondition();
|
||||||
PBI->getSuccessor(0) != PBI->getSuccessor(1)) {
|
ConstantInt *TorF = *Imp ? ConstantInt::getTrue(BB->getContext())
|
||||||
assert(PBI->getSuccessor(0) == BB || PBI->getSuccessor(1) == BB);
|
: ConstantInt::getFalse(BB->getContext());
|
||||||
bool CondIsTrue = PBI->getSuccessor(0) == BB;
|
BI->setCondition(TorF);
|
||||||
Optional<bool> Implication = isImpliedCondition(
|
RecursivelyDeleteTriviallyDeadInstructions(OldCond);
|
||||||
PBI->getCondition(), BI->getCondition(), DL, CondIsTrue);
|
return requestResimplify();
|
||||||
if (Implication) {
|
|
||||||
// Turn this into a branch on constant.
|
|
||||||
auto *OldCond = BI->getCondition();
|
|
||||||
ConstantInt *CI = *Implication
|
|
||||||
? ConstantInt::getTrue(BB->getContext())
|
|
||||||
: ConstantInt::getFalse(BB->getContext());
|
|
||||||
BI->setCondition(CI);
|
|
||||||
RecursivelyDeleteTriviallyDeadInstructions(OldCond);
|
|
||||||
return requestResimplify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this basic block is ONLY a compare and a branch, and if a predecessor
|
// If this basic block is ONLY a compare and a branch, and if a predecessor
|
||||||
|
|
Loading…
Reference in New Issue