forked from OSchip/llvm-project
[TargetInstrInfo] Add new hook: AnalyzeBranchPredicate.
Summary: NFC: no one uses AnalyzeBranchPredicate yet. Add TargetInstrInfo::AnalyzeBranchPredicate and implement for x86. A later change adding support for page-fault based implicit null checks depends on this. Reviewers: reames, ab, atrick Reviewed By: atrick Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D10200 llvm-svn: 239742
This commit is contained in:
parent
b666ea369c
commit
6b34a46298
|
@ -387,6 +387,51 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Represents a predicate at the MachineFunction level. The control flow a
|
||||
/// MachineBranchPredicate represents is:
|
||||
///
|
||||
/// Reg <def>= LHS `Predicate` RHS == ConditionDef
|
||||
/// if Reg then goto TrueDest else goto FalseDest
|
||||
///
|
||||
struct MachineBranchPredicate {
|
||||
enum ComparePredicate {
|
||||
PRED_EQ, // True if two values are equal
|
||||
PRED_NE, // True if two values are not equal
|
||||
PRED_INVALID // Sentinel value
|
||||
};
|
||||
|
||||
ComparePredicate Predicate;
|
||||
MachineOperand LHS;
|
||||
MachineOperand RHS;
|
||||
MachineBasicBlock *TrueDest;
|
||||
MachineBasicBlock *FalseDest;
|
||||
MachineInstr *ConditionDef;
|
||||
|
||||
/// SingleUseCondition is true if ConditionDef is dead except for the
|
||||
/// branch(es) at the end of the basic block.
|
||||
///
|
||||
bool SingleUseCondition;
|
||||
|
||||
explicit MachineBranchPredicate()
|
||||
: Predicate(PRED_INVALID), LHS(MachineOperand::CreateImm(0)),
|
||||
RHS(MachineOperand::CreateImm(0)), TrueDest(nullptr),
|
||||
FalseDest(nullptr), ConditionDef(nullptr), SingleUseCondition(false) {
|
||||
}
|
||||
};
|
||||
|
||||
/// Analyze the branching code at the end of MBB and parse it into the
|
||||
/// MachineBranchPredicate structure if possible. Returns false on success
|
||||
/// and true on failure.
|
||||
///
|
||||
/// If AllowModify is true, then this routine is allowed to modify the basic
|
||||
/// block (e.g. delete instructions after the unconditional branch).
|
||||
///
|
||||
virtual bool AnalyzeBranchPredicate(MachineBasicBlock &MBB,
|
||||
MachineBranchPredicate &MBP,
|
||||
bool AllowModify = false) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Remove the branching code at the end of the specific MBB.
|
||||
/// This is only invoked in cases where AnalyzeBranch returns success. It
|
||||
/// returns the number of instructions that were removed.
|
||||
|
|
|
@ -3456,11 +3456,11 @@ bool X86InstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
|
|||
return !isPredicated(MI);
|
||||
}
|
||||
|
||||
bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const {
|
||||
bool X86InstrInfo::AnalyzeBranchImpl(
|
||||
MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
SmallVectorImpl<MachineInstr *> &CondBranches, bool AllowModify) const {
|
||||
|
||||
// Start from the bottom of the block and work up, examining the
|
||||
// terminator instructions.
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
|
@ -3558,6 +3558,7 @@ bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
|||
FBB = TBB;
|
||||
TBB = I->getOperand(0).getMBB();
|
||||
Cond.push_back(MachineOperand::CreateImm(BranchCode));
|
||||
CondBranches.push_back(I);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3595,11 +3596,90 @@ bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
|||
|
||||
// Update the MachineOperand.
|
||||
Cond[0].setImm(BranchCode);
|
||||
CondBranches.push_back(I);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const {
|
||||
SmallVector<MachineInstr *, 4> CondBranches;
|
||||
return AnalyzeBranchImpl(MBB, TBB, FBB, Cond, CondBranches, AllowModify);
|
||||
}
|
||||
|
||||
bool X86InstrInfo::AnalyzeBranchPredicate(MachineBasicBlock &MBB,
|
||||
MachineBranchPredicate &MBP,
|
||||
bool AllowModify) const {
|
||||
using namespace std::placeholders;
|
||||
|
||||
SmallVector<MachineOperand, 4> Cond;
|
||||
SmallVector<MachineInstr *, 4> CondBranches;
|
||||
if (AnalyzeBranchImpl(MBB, MBP.TrueDest, MBP.FalseDest, Cond, CondBranches,
|
||||
AllowModify))
|
||||
return true;
|
||||
|
||||
if (Cond.size() != 1)
|
||||
return true;
|
||||
|
||||
assert(MBP.TrueDest && "expected!");
|
||||
|
||||
if (!MBP.FalseDest)
|
||||
MBP.FalseDest = MBB.getNextNode();
|
||||
|
||||
const TargetRegisterInfo *TRI = &getRegisterInfo();
|
||||
|
||||
MachineInstr *ConditionDef = nullptr;
|
||||
bool SingleUseCondition = true;
|
||||
|
||||
for (auto I = std::next(MBB.rbegin()), E = MBB.rend(); I != E; ++I) {
|
||||
if (I->modifiesRegister(X86::EFLAGS, TRI)) {
|
||||
ConditionDef = &*I;
|
||||
break;
|
||||
}
|
||||
|
||||
if (I->readsRegister(X86::EFLAGS, TRI))
|
||||
SingleUseCondition = false;
|
||||
}
|
||||
|
||||
if (!ConditionDef)
|
||||
return true;
|
||||
|
||||
if (SingleUseCondition) {
|
||||
for (auto *Succ : MBB.successors())
|
||||
if (Succ->isLiveIn(X86::EFLAGS))
|
||||
SingleUseCondition = false;
|
||||
}
|
||||
|
||||
MBP.ConditionDef = ConditionDef;
|
||||
MBP.SingleUseCondition = SingleUseCondition;
|
||||
|
||||
// Currently we only recognize the simple pattern:
|
||||
//
|
||||
// test %reg, %reg
|
||||
// je %label
|
||||
//
|
||||
const unsigned TestOpcode =
|
||||
Subtarget.is64Bit() ? X86::TEST64rr : X86::TEST32rr;
|
||||
|
||||
if (ConditionDef->getOpcode() == TestOpcode &&
|
||||
ConditionDef->getNumOperands() == 3 &&
|
||||
ConditionDef->getOperand(0).isIdenticalTo(ConditionDef->getOperand(1)) &&
|
||||
(Cond[0].getImm() == X86::COND_NE || Cond[0].getImm() == X86::COND_E)) {
|
||||
MBP.LHS = ConditionDef->getOperand(0);
|
||||
MBP.RHS = MachineOperand::CreateImm(0);
|
||||
MBP.Predicate = Cond[0].getImm() == X86::COND_NE
|
||||
? MachineBranchPredicate::PRED_NE
|
||||
: MachineBranchPredicate::PRED_EQ;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned X86InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
unsigned Count = 0;
|
||||
|
|
|
@ -179,6 +179,12 @@ class X86InstrInfo final : public X86GenInstrInfo {
|
|||
|
||||
virtual void anchor();
|
||||
|
||||
bool AnalyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
SmallVectorImpl<MachineInstr *> &CondBranches,
|
||||
bool AllowModify) const;
|
||||
|
||||
public:
|
||||
explicit X86InstrInfo(X86Subtarget &STI);
|
||||
|
||||
|
@ -271,6 +277,10 @@ public:
|
|||
bool getMemOpBaseRegImmOfs(MachineInstr *LdSt, unsigned &BaseReg,
|
||||
unsigned &Offset,
|
||||
const TargetRegisterInfo *TRI) const override;
|
||||
bool AnalyzeBranchPredicate(MachineBasicBlock &MBB,
|
||||
TargetInstrInfo::MachineBranchPredicate &MBP,
|
||||
bool AllowModify = false) const override;
|
||||
|
||||
unsigned RemoveBranch(MachineBasicBlock &MBB) const override;
|
||||
unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
|
||||
|
|
Loading…
Reference in New Issue