mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[PatternMatch] Make m_Br more flexible, add matchers for BB values.
Currently m_Br only takes references to BasicBlock*, which limits its flexibility. For example, you have to declare a variable, even if you ignore the result or you have to have additional checks to make sure the matched BB matches an expected one. This patch adds m_BasicBlock and m_SpecificBB matchers, which can be used like the existing matchers for constants or values. I also had a look at the existing uses and updated a few. IMO it makes the code a bit more explicit. Reviewers: spatel, craig.topper, RKSimon, majnemer, lebedev.ri Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D68013 llvm-svn: 372885
This commit is contained in:
parent
51da1efb27
commit
bd3f6055e7
@ -88,6 +88,11 @@ inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
|
||||
/// Match an arbitrary Constant and ignore it.
|
||||
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
|
||||
|
||||
/// Match an arbitrary basic block value and ignore it.
|
||||
inline class_match<BasicBlock> m_BasicBlock() {
|
||||
return class_match<BasicBlock>();
|
||||
}
|
||||
|
||||
/// Inverting matcher
|
||||
template <typename Ty> struct match_unless {
|
||||
Ty M;
|
||||
@ -563,6 +568,12 @@ inline bind_ty<Constant> m_Constant(Constant *&C) { return C; }
|
||||
/// Match a ConstantFP, capturing the value if we match.
|
||||
inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; }
|
||||
|
||||
/// Match a basic block value, capturing it if we match.
|
||||
inline bind_ty<BasicBlock> m_BasicBlock(BasicBlock *&V) { return V; }
|
||||
inline bind_ty<const BasicBlock> m_BasicBlock(const BasicBlock *&V) {
|
||||
return V;
|
||||
}
|
||||
|
||||
/// Match a specified Value*.
|
||||
struct specificval_ty {
|
||||
const Value *Val;
|
||||
@ -656,6 +667,32 @@ inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); }
|
||||
/// ConstantInts wider than 64-bits.
|
||||
inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; }
|
||||
|
||||
/// Match a specified basic block value.
|
||||
struct specific_bbval {
|
||||
BasicBlock *Val;
|
||||
|
||||
specific_bbval(BasicBlock *Val) : Val(Val) {}
|
||||
|
||||
template <typename ITy> bool match(ITy *V) {
|
||||
const auto *BB = dyn_cast<BasicBlock>(V);
|
||||
return BB && BB == Val;
|
||||
}
|
||||
};
|
||||
|
||||
/// Match a specific basic block value.
|
||||
inline specific_bbval m_SpecificBB(BasicBlock *BB) {
|
||||
return specific_bbval(BB);
|
||||
}
|
||||
|
||||
/// A commutative-friendly version of m_Specific().
|
||||
inline deferredval_ty<BasicBlock> m_Deferred(BasicBlock *const &BB) {
|
||||
return BB;
|
||||
}
|
||||
inline deferredval_ty<const BasicBlock>
|
||||
m_Deferred(const BasicBlock *const &BB) {
|
||||
return BB;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Matcher for any binary operator.
|
||||
//
|
||||
@ -1345,19 +1382,23 @@ struct brc_match {
|
||||
|
||||
template <typename OpTy> bool match(OpTy *V) {
|
||||
if (auto *BI = dyn_cast<BranchInst>(V))
|
||||
if (BI->isConditional() && Cond.match(BI->getCondition())) {
|
||||
T = BI->getSuccessor(0);
|
||||
F = BI->getSuccessor(1);
|
||||
return true;
|
||||
}
|
||||
if (BI->isConditional() && Cond.match(BI->getCondition()))
|
||||
return T.match(BI->getSuccessor(0)) && F.match(BI->getSuccessor(1));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Cond_t>
|
||||
inline brc_match<Cond_t, BasicBlock *&, BasicBlock *&>
|
||||
inline brc_match<Cond_t, bind_ty<BasicBlock>, bind_ty<BasicBlock>>
|
||||
m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) {
|
||||
return brc_match<Cond_t, BasicBlock *&, BasicBlock *&>(C, T, F);
|
||||
return brc_match<Cond_t, bind_ty<BasicBlock>, bind_ty<BasicBlock>>(
|
||||
C, m_BasicBlock(T), m_BasicBlock(F));
|
||||
}
|
||||
|
||||
template <typename Cond_t, typename TrueBlock_t, typename FalseBlock_t>
|
||||
inline brc_match<Cond_t, TrueBlock_t, FalseBlock_t>
|
||||
m_Br(const Cond_t &C, const TrueBlock_t &T, const FalseBlock_t &F) {
|
||||
return brc_match<Cond_t, TrueBlock_t, FalseBlock_t>(C, T, F);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -2105,11 +2105,10 @@ SCEVExpander::getRelatedExistingExpansion(const SCEV *S, const Instruction *At,
|
||||
for (BasicBlock *BB : ExitingBlocks) {
|
||||
ICmpInst::Predicate Pred;
|
||||
Instruction *LHS, *RHS;
|
||||
BasicBlock *TrueBB, *FalseBB;
|
||||
|
||||
if (!match(BB->getTerminator(),
|
||||
m_Br(m_ICmp(Pred, m_Instruction(LHS), m_Instruction(RHS)),
|
||||
TrueBB, FalseBB)))
|
||||
m_BasicBlock(), m_BasicBlock())))
|
||||
continue;
|
||||
|
||||
if (SE.getSCEV(LHS) == S && SE.DT.dominates(LHS, At))
|
||||
|
@ -121,14 +121,13 @@ static bool foldGuardedRotateToFunnelShift(Instruction &I) {
|
||||
BasicBlock *GuardBB = Phi.getIncomingBlock(RotSrc == P1);
|
||||
BasicBlock *RotBB = Phi.getIncomingBlock(RotSrc != P1);
|
||||
Instruction *TermI = GuardBB->getTerminator();
|
||||
BasicBlock *TrueBB, *FalseBB;
|
||||
ICmpInst::Predicate Pred;
|
||||
if (!match(TermI, m_Br(m_ICmp(Pred, m_Specific(RotAmt), m_ZeroInt()), TrueBB,
|
||||
FalseBB)))
|
||||
BasicBlock *PhiBB = Phi.getParent();
|
||||
if (!match(TermI, m_Br(m_ICmp(Pred, m_Specific(RotAmt), m_ZeroInt()),
|
||||
m_SpecificBB(PhiBB), m_SpecificBB(RotBB))))
|
||||
return false;
|
||||
|
||||
BasicBlock *PhiBB = Phi.getParent();
|
||||
if (Pred != CmpInst::ICMP_EQ || TrueBB != PhiBB || FalseBB != RotBB)
|
||||
if (Pred != CmpInst::ICMP_EQ)
|
||||
return false;
|
||||
|
||||
// We matched a variation of this IR pattern:
|
||||
|
@ -2557,9 +2557,7 @@ Instruction *InstCombiner::visitReturnInst(ReturnInst &RI) {
|
||||
Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
|
||||
// Change br (not X), label True, label False to: br X, label False, True
|
||||
Value *X = nullptr;
|
||||
BasicBlock *TrueDest;
|
||||
BasicBlock *FalseDest;
|
||||
if (match(&BI, m_Br(m_Not(m_Value(X)), TrueDest, FalseDest)) &&
|
||||
if (match(&BI, m_Br(m_Not(m_Value(X)), m_BasicBlock(), m_BasicBlock())) &&
|
||||
!isa<Constant>(X)) {
|
||||
// Swap Destinations and condition...
|
||||
BI.setCondition(X);
|
||||
@ -2577,8 +2575,8 @@ Instruction *InstCombiner::visitBranchInst(BranchInst &BI) {
|
||||
|
||||
// Canonicalize, for example, icmp_ne -> icmp_eq or fcmp_one -> fcmp_oeq.
|
||||
CmpInst::Predicate Pred;
|
||||
if (match(&BI, m_Br(m_OneUse(m_Cmp(Pred, m_Value(), m_Value())), TrueDest,
|
||||
FalseDest)) &&
|
||||
if (match(&BI, m_Br(m_OneUse(m_Cmp(Pred, m_Value(), m_Value())),
|
||||
m_BasicBlock(), m_BasicBlock())) &&
|
||||
!isCanonicalPredicate(Pred)) {
|
||||
// Swap destinations and condition.
|
||||
CmpInst *Cond = cast<CmpInst>(BI.getCondition());
|
||||
|
@ -1045,6 +1045,34 @@ TEST_F(PatternMatchTest, FloatingPointFNeg) {
|
||||
EXPECT_FALSE(match(V3, m_FNeg(m_Value(Match))));
|
||||
}
|
||||
|
||||
TEST_F(PatternMatchTest, CondBranchTest) {
|
||||
BasicBlock *TrueBB = BasicBlock::Create(Ctx, "TrueBB", F);
|
||||
BasicBlock *FalseBB = BasicBlock::Create(Ctx, "FalseBB", F);
|
||||
Value *Br1 = IRB.CreateCondBr(IRB.getTrue(), TrueBB, FalseBB);
|
||||
|
||||
EXPECT_TRUE(match(Br1, m_Br(m_Value(), m_BasicBlock(), m_BasicBlock())));
|
||||
|
||||
BasicBlock *A, *B;
|
||||
EXPECT_TRUE(match(Br1, m_Br(m_Value(), m_BasicBlock(A), m_BasicBlock(B))));
|
||||
EXPECT_EQ(TrueBB, A);
|
||||
EXPECT_EQ(FalseBB, B);
|
||||
|
||||
EXPECT_FALSE(
|
||||
match(Br1, m_Br(m_Value(), m_SpecificBB(FalseBB), m_BasicBlock())));
|
||||
EXPECT_FALSE(
|
||||
match(Br1, m_Br(m_Value(), m_BasicBlock(), m_SpecificBB(TrueBB))));
|
||||
EXPECT_FALSE(
|
||||
match(Br1, m_Br(m_Value(), m_SpecificBB(FalseBB), m_BasicBlock(TrueBB))));
|
||||
EXPECT_TRUE(
|
||||
match(Br1, m_Br(m_Value(), m_SpecificBB(TrueBB), m_BasicBlock(FalseBB))));
|
||||
|
||||
// Check we can use m_Deferred with branches.
|
||||
EXPECT_FALSE(match(Br1, m_Br(m_Value(), m_BasicBlock(A), m_Deferred(A))));
|
||||
Value *Br2 = IRB.CreateCondBr(IRB.getTrue(), TrueBB, TrueBB);
|
||||
A = nullptr;
|
||||
EXPECT_TRUE(match(Br2, m_Br(m_Value(), m_BasicBlock(A), m_Deferred(A))));
|
||||
}
|
||||
|
||||
template <typename T> struct MutableConstTest : PatternMatchTest { };
|
||||
|
||||
typedef ::testing::Types<std::tuple<Value*, Instruction*>,
|
||||
|
Loading…
Reference in New Issue
Block a user