mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-30 15:45:26 +00:00
Implement branch analysis in the MBlaze backend.
llvm-svn: 119951
This commit is contained in:
parent
470c56eef5
commit
911abf2bc0
@ -107,17 +107,134 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Branch Analysis
|
||||
//===----------------------------------------------------------------------===//
|
||||
bool MBlazeInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const {
|
||||
// If the block has no terminators, it just falls into the block after it.
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
if (I == MBB.begin())
|
||||
return false;
|
||||
--I;
|
||||
while (I->isDebugValue()) {
|
||||
if (I == MBB.begin())
|
||||
return false;
|
||||
--I;
|
||||
}
|
||||
if (!isUnpredicatedTerminator(I))
|
||||
return false;
|
||||
|
||||
// Get the last instruction in the block.
|
||||
MachineInstr *LastInst = I;
|
||||
|
||||
// If there is only one terminator instruction, process it.
|
||||
unsigned LastOpc = LastInst->getOpcode();
|
||||
if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
|
||||
if (MBlaze::isUncondBranchOpcode(LastOpc)) {
|
||||
TBB = LastInst->getOperand(0).getMBB();
|
||||
return false;
|
||||
}
|
||||
if (MBlaze::isCondBranchOpcode(LastOpc)) {
|
||||
// Block ends with fall-through condbranch.
|
||||
TBB = LastInst->getOperand(1).getMBB();
|
||||
Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
|
||||
Cond.push_back(LastInst->getOperand(0));
|
||||
return false;
|
||||
}
|
||||
// Otherwise, don't know what this is.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the instruction before it if it's a terminator.
|
||||
MachineInstr *SecondLastInst = I;
|
||||
|
||||
// If there are three terminators, we don't know what sort of block this is.
|
||||
if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I))
|
||||
return true;
|
||||
|
||||
// If the block ends with something like BEQID then BRID, handle it.
|
||||
if (MBlaze::isCondBranchOpcode(SecondLastInst->getOpcode()) &&
|
||||
MBlaze::isUncondBranchOpcode(LastInst->getOpcode())) {
|
||||
TBB = SecondLastInst->getOperand(1).getMBB();
|
||||
Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode()));
|
||||
Cond.push_back(SecondLastInst->getOperand(0));
|
||||
FBB = LastInst->getOperand(0).getMBB();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the block ends with two unconditional branches, handle it.
|
||||
// The second one is not executed, so remove it.
|
||||
if (MBlaze::isUncondBranchOpcode(SecondLastInst->getOpcode()) &&
|
||||
MBlaze::isUncondBranchOpcode(LastInst->getOpcode())) {
|
||||
TBB = SecondLastInst->getOperand(0).getMBB();
|
||||
I = LastInst;
|
||||
if (AllowModify)
|
||||
I->eraseFromParent();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, can't handle this.
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned MBlazeInstrInfo::
|
||||
InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond,
|
||||
DebugLoc DL) const {
|
||||
// Can only insert uncond branches so far.
|
||||
assert(Cond.empty() && !FBB && TBB && "Can only handle uncond branches!");
|
||||
BuildMI(&MBB, DL, get(MBlaze::BRI)).addMBB(TBB);
|
||||
return 1;
|
||||
// Shouldn't be a fall through.
|
||||
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
||||
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
||||
"MBlaze branch conditions have two components!");
|
||||
|
||||
unsigned Opc = MBlaze::BRID;
|
||||
if (!Cond.empty())
|
||||
Opc = (unsigned)Cond[0].getImm();
|
||||
|
||||
if (FBB == 0) {
|
||||
if (Cond.empty()) // Unconditional branch
|
||||
BuildMI(&MBB, DL, get(Opc)).addMBB(TBB);
|
||||
else // Conditional branch
|
||||
BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()).addMBB(TBB);
|
||||
return 1;
|
||||
}
|
||||
|
||||
BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()).addMBB(TBB);
|
||||
BuildMI(&MBB, DL, get(MBlaze::BRID)).addMBB(FBB);
|
||||
return 2;
|
||||
}
|
||||
|
||||
unsigned MBlazeInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
if (I == MBB.begin()) return 0;
|
||||
--I;
|
||||
while (I->isDebugValue()) {
|
||||
if (I == MBB.begin())
|
||||
return 0;
|
||||
--I;
|
||||
}
|
||||
|
||||
if (!MBlaze::isUncondBranchOpcode(I->getOpcode()) &&
|
||||
!MBlaze::isCondBranchOpcode(I->getOpcode()))
|
||||
return 0;
|
||||
|
||||
// Remove the branch.
|
||||
I->eraseFromParent();
|
||||
|
||||
I = MBB.end();
|
||||
|
||||
if (I == MBB.begin()) return 1;
|
||||
--I;
|
||||
if (!MBlaze::isCondBranchOpcode(I->getOpcode()))
|
||||
return 1;
|
||||
|
||||
// Remove the branch.
|
||||
I->eraseFromParent();
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/// getGlobalBaseReg - Return a virtual register initialized with the
|
||||
/// the global base register value. Output instructions required to
|
||||
/// initialize the register in the function entry block, if necessary.
|
||||
|
@ -73,59 +73,92 @@ namespace MBlaze {
|
||||
FCOND_GT,
|
||||
|
||||
// Only integer conditions
|
||||
COND_E,
|
||||
COND_GZ,
|
||||
COND_GEZ,
|
||||
COND_LZ,
|
||||
COND_LEZ,
|
||||
COND_EQ,
|
||||
COND_GT,
|
||||
COND_GE,
|
||||
COND_LT,
|
||||
COND_LE,
|
||||
COND_NE,
|
||||
COND_INVALID
|
||||
};
|
||||
|
||||
// Turn condition code into conditional branch opcode.
|
||||
unsigned GetCondBranchFromCond(CondCode CC);
|
||||
inline static unsigned GetCondBranchFromCond(CondCode CC) {
|
||||
switch (CC) {
|
||||
default: llvm_unreachable("Unknown condition code");
|
||||
case COND_EQ: return MBlaze::BEQID;
|
||||
case COND_NE: return MBlaze::BNEID;
|
||||
case COND_GT: return MBlaze::BGTID;
|
||||
case COND_GE: return MBlaze::BGEID;
|
||||
case COND_LT: return MBlaze::BLTID;
|
||||
case COND_LE: return MBlaze::BLEID;
|
||||
}
|
||||
}
|
||||
|
||||
/// GetOppositeBranchCondition - Return the inverse of the specified cond,
|
||||
/// e.g. turning COND_E to COND_NE.
|
||||
CondCode GetOppositeBranchCondition(MBlaze::CondCode CC);
|
||||
// CondCode GetOppositeBranchCondition(MBlaze::CondCode CC);
|
||||
|
||||
/// MBlazeCCToString - Map each FP condition code to its string
|
||||
inline static const char *MBlazeFCCToString(MBlaze::CondCode CC)
|
||||
{
|
||||
inline static const char *MBlazeFCCToString(MBlaze::CondCode CC) {
|
||||
switch (CC) {
|
||||
default: llvm_unreachable("Unknown condition code");
|
||||
case FCOND_F:
|
||||
case FCOND_T: return "f";
|
||||
case FCOND_UN:
|
||||
case FCOND_OR: return "un";
|
||||
case FCOND_EQ:
|
||||
case FCOND_NEQ: return "eq";
|
||||
case FCOND_UEQ:
|
||||
case FCOND_OGL: return "ueq";
|
||||
case FCOND_OLT:
|
||||
case FCOND_UGE: return "olt";
|
||||
case FCOND_ULT:
|
||||
case FCOND_OGE: return "ult";
|
||||
case FCOND_OLE:
|
||||
case FCOND_UGT: return "ole";
|
||||
case FCOND_ULE:
|
||||
case FCOND_OGT: return "ule";
|
||||
case FCOND_SF:
|
||||
case FCOND_ST: return "sf";
|
||||
case FCOND_NGLE:
|
||||
case FCOND_GLE: return "ngle";
|
||||
case FCOND_SEQ:
|
||||
case FCOND_SNE: return "seq";
|
||||
case FCOND_NGL:
|
||||
case FCOND_GL: return "ngl";
|
||||
case FCOND_LT:
|
||||
case FCOND_NLT: return "lt";
|
||||
case FCOND_NGE:
|
||||
case FCOND_GE: return "ge";
|
||||
case FCOND_LE:
|
||||
case FCOND_NLE: return "nle";
|
||||
case FCOND_NGT:
|
||||
case FCOND_GT: return "gt";
|
||||
default: llvm_unreachable("Unknown condition code");
|
||||
case FCOND_F:
|
||||
case FCOND_T: return "f";
|
||||
case FCOND_UN:
|
||||
case FCOND_OR: return "un";
|
||||
case FCOND_EQ:
|
||||
case FCOND_NEQ: return "eq";
|
||||
case FCOND_UEQ:
|
||||
case FCOND_OGL: return "ueq";
|
||||
case FCOND_OLT:
|
||||
case FCOND_UGE: return "olt";
|
||||
case FCOND_ULT:
|
||||
case FCOND_OGE: return "ult";
|
||||
case FCOND_OLE:
|
||||
case FCOND_UGT: return "ole";
|
||||
case FCOND_ULE:
|
||||
case FCOND_OGT: return "ule";
|
||||
case FCOND_SF:
|
||||
case FCOND_ST: return "sf";
|
||||
case FCOND_NGLE:
|
||||
case FCOND_GLE: return "ngle";
|
||||
case FCOND_SEQ:
|
||||
case FCOND_SNE: return "seq";
|
||||
case FCOND_NGL:
|
||||
case FCOND_GL: return "ngl";
|
||||
case FCOND_LT:
|
||||
case FCOND_NLT: return "lt";
|
||||
case FCOND_NGE:
|
||||
case FCOND_GE: return "ge";
|
||||
case FCOND_LE:
|
||||
case FCOND_NLE: return "nle";
|
||||
case FCOND_NGT:
|
||||
case FCOND_GT: return "gt";
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool isUncondBranchOpcode(int Opc) {
|
||||
switch (Opc) {
|
||||
default: return false;
|
||||
case MBlaze::BRI:
|
||||
case MBlaze::BRAI:
|
||||
case MBlaze::BRID:
|
||||
case MBlaze::BRAID:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool isCondBranchOpcode(int Opc) {
|
||||
switch (Opc) {
|
||||
default: return false;
|
||||
case MBlaze::BEQI: case MBlaze::BEQID:
|
||||
case MBlaze::BNEI: case MBlaze::BNEID:
|
||||
case MBlaze::BGTI: case MBlaze::BGTID:
|
||||
case MBlaze::BGEI: case MBlaze::BGEID:
|
||||
case MBlaze::BLTI: case MBlaze::BLTID:
|
||||
case MBlaze::BLEI: case MBlaze::BLEID:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,10 +248,15 @@ public:
|
||||
int &FrameIndex) const;
|
||||
|
||||
/// Branch Analysis
|
||||
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const;
|
||||
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond,
|
||||
DebugLoc DL) const;
|
||||
virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const;
|
||||
virtual void copyPhysReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
|
@ -68,5 +68,5 @@ finish:
|
||||
%tmp.8 = urem i32 %tmp.7, 5
|
||||
|
||||
br label %loop
|
||||
; CHECK: brid
|
||||
; CHECK: brd
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user