Index: include/llvm/Target/TargetInstrInfo.h =================================================================== --- include/llvm/Target/TargetInstrInfo.h +++ include/llvm/Target/TargetInstrInfo.h @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/IR/Instructions.h" namespace llvm { @@ -386,6 +387,45 @@ return true; } + /// Represents a predicate at the MachineFunction level. The control flow a + /// MachineBranchPredicate represents is: + /// + /// Reg = LHS `Predicate` RHS == ConditionDef + /// if Reg then goto TrueDest else goto FalseDest + /// + struct MachineBranchPredicate { + CmpInst::Predicate 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(CmpInst::BAD_ICMP_PREDICATE), + 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. Index: lib/Target/X86/X86InstrInfo.h =================================================================== --- lib/Target/X86/X86InstrInfo.h +++ lib/Target/X86/X86InstrInfo.h @@ -166,6 +166,12 @@ virtual void anchor(); + bool AnalyzeBranchInner(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + SmallVectorImpl &CondBranches, + bool AllowModify) const; + public: explicit X86InstrInfo(X86Subtarget &STI); @@ -258,6 +264,10 @@ bool getMemOpBaseRegImmOfs(MachineInstr *LdSt, bool &IsLoadOp, 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, Index: lib/Target/X86/X86InstrInfo.cpp =================================================================== --- lib/Target/X86/X86InstrInfo.cpp +++ lib/Target/X86/X86InstrInfo.cpp @@ -3450,11 +3450,11 @@ return !isPredicated(MI); } -bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, - MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl &Cond, - bool AllowModify) const { +bool X86InstrInfo::AnalyzeBranchInner( + MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + SmallVectorImpl &CondBranches, bool AllowModify) const { + // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); @@ -3552,6 +3552,7 @@ FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(MachineOperand::CreateImm(BranchCode)); + CondBranches.push_back(I); continue; } @@ -3589,11 +3590,72 @@ // Update the MachineOperand. Cond[0].setImm(BranchCode); + CondBranches.push_back(I); } return false; } +bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + SmallVector CondBranches; + return AnalyzeBranchInner(MBB, TBB, FBB, Cond, CondBranches, AllowModify); +} + +bool X86InstrInfo::AnalyzeBranchPredicate(MachineBasicBlock &MBB, + MachineBranchPredicate &MBP, + bool AllowModify) const { + using namespace std::placeholders; + + SmallVector Cond; + SmallVector CondBranches; + if (AnalyzeBranchInner(MBB, MBP.TrueDest, MBP.FalseDest, Cond, CondBranches, + AllowModify)) + return true; + + assert(Cond.size() == 1 && MBP.TrueDest && "expected!"); + + if (!MBP.FalseDest) + MBP.FalseDest = MBB.getNextNode(); + + const TargetRegisterInfo *TRI = &getRegisterInfo(); + + auto DefFlagsI = std::find_if( + MBB.rbegin(), MBB.rend(), + std::bind(&MachineInstr::modifiesRegister, _1, X86::EFLAGS, TRI)); + + if (DefFlagsI == MBB.rend()) + return true; + + MBP.ConditionDef = &*DefFlagsI; + MBP.SingleUseCondition = CondBranches.size() == 1 && + CondBranches[0]->killsRegister(X86::EFLAGS, TRI); + + // Currently we only recognize the simple pattern: + // + // test %reg, %reg + // je %label + // + const unsigned TestOpCode = + Subtarget.is64Bit() ? X86::TEST64rr : X86::TEST32rr; + + if (DefFlagsI->getOpcode() == TestOpCode && + DefFlagsI->getNumOperands() == 3 && + DefFlagsI->getOperand(0).isIdenticalTo(DefFlagsI->getOperand(1)) && + (Cond[0].getImm() == X86::COND_NE || Cond[0].getImm() == X86::COND_E)) { + MBP.LHS = DefFlagsI->getOperand(0); + MBP.RHS = MachineOperand::CreateImm(0); + MBP.Predicate = + Cond[0].getImm() == X86::COND_NE ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ; + return false; + } + + return true; +} + unsigned X86InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { MachineBasicBlock::iterator I = MBB.end(); unsigned Count = 0;