From: Wesley Peck Date: Sun, 21 Nov 2010 21:53:36 +0000 (+0000) Subject: Implement branch analysis in the MBlaze backend. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=46a928b864369ba9e1b8fc055d100c2fa0f97d16;p=oota-llvm.git Implement branch analysis in the MBlaze backend. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119951 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/lib/Target/MBlaze/MBlazeInstrInfo.cpp index 10bba972b0c..d7c11f2a699 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.cpp +++ b/lib/Target/MBlaze/MBlazeInstrInfo.cpp @@ -107,17 +107,134 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, //===----------------------------------------------------------------------===// // Branch Analysis //===----------------------------------------------------------------------===// +bool MBlazeInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &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 &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. diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.h b/lib/Target/MBlaze/MBlazeInstrInfo.h index af1842fc9d9..91392f92e4f 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.h +++ b/lib/Target/MBlaze/MBlazeInstrInfo.h @@ -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 &Cond, + bool AllowModify) const; virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl &Cond, DebugLoc DL) const; + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, diff --git a/test/CodeGen/MBlaze/brind.ll b/test/CodeGen/MBlaze/brind.ll index 4ec8605b653..9ec7f949256 100644 --- a/test/CodeGen/MBlaze/brind.ll +++ b/test/CodeGen/MBlaze/brind.ll @@ -68,5 +68,5 @@ finish: %tmp.8 = urem i32 %tmp.7, 5 br label %loop - ; CHECK: brid + ; CHECK: brd }