diff options
Diffstat (limited to 'contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp | 254 |
1 files changed, 0 insertions, 254 deletions
diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp deleted file mode 100644 index 3d0d1ce..0000000 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp +++ /dev/null @@ -1,254 +0,0 @@ -//===-- DelaySlotFiller.cpp - MBlaze delay slot filler --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// A pass that attempts to fill instructions with delay slots. If no -// instructions can be moved into the delay slot then a NOP is placed there. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "delay-slot-filler" - -#include "MBlaze.h" -#include "MBlazeTargetMachine.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetInstrInfo.h" - -using namespace llvm; - -STATISTIC(FilledSlots, "Number of delay slots filled"); - -static cl::opt<bool> MBDisableDelaySlotFiller( - "disable-mblaze-delay-filler", - cl::init(false), - cl::desc("Disable the MBlaze delay slot filter."), - cl::Hidden); - -namespace { - struct Filler : public MachineFunctionPass { - - TargetMachine &TM; - const TargetInstrInfo *TII; - - static char ID; - Filler(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } - - virtual const char *getPassName() const { - return "MBlaze Delay Slot Filler"; - } - - bool runOnMachineBasicBlock(MachineBasicBlock &MBB); - bool runOnMachineFunction(MachineFunction &F) { - bool Changed = false; - for (MachineFunction::iterator FI = F.begin(), FE = F.end(); - FI != FE; ++FI) - Changed |= runOnMachineBasicBlock(*FI); - return Changed; - } - - }; - char Filler::ID = 0; -} // end of anonymous namespace - -static bool hasImmInstruction(MachineBasicBlock::iterator &candidate) { - // Any instruction with an immediate mode operand greater than - // 16-bits requires an implicit IMM instruction. - unsigned numOper = candidate->getNumOperands(); - for (unsigned op = 0; op < numOper; ++op) { - MachineOperand &mop = candidate->getOperand(op); - - // The operand requires more than 16-bits to represent. - if (mop.isImm() && (mop.getImm() < -0x8000 || mop.getImm() > 0x7fff)) - return true; - - // We must assume that unknown immediate values require more than - // 16-bits to represent. - if (mop.isGlobal() || mop.isSymbol() || mop.isJTI() || mop.isCPI()) - return true; - - // FIXME: we could probably check to see if the FP value happens - // to not need an IMM instruction. For now we just always - // assume that FP values do. - if (mop.isFPImm()) - return true; - } - - return false; -} - -static unsigned getLastRealOperand(MachineBasicBlock::iterator &instr) { - switch (instr->getOpcode()) { - default: return instr->getNumOperands(); - - // These instructions have a variable number of operands but the first two - // are the "real" operands that we care about during hazard detection. - case MBlaze::BRLID: - case MBlaze::BRALID: - case MBlaze::BRLD: - case MBlaze::BRALD: - return 2; - } -} - -static bool delayHasHazard(MachineBasicBlock::iterator &candidate, - MachineBasicBlock::iterator &slot) { - // Hazard check - MachineBasicBlock::iterator a = candidate; - MachineBasicBlock::iterator b = slot; - - // MBB layout:- - // candidate := a0 = operation(a1, a2) - // ...middle bit... - // slot := b0 = operation(b1, b2) - - // Possible hazards:-/ - // 1. a1 or a2 was written during the middle bit - // 2. a0 was read or written during the middle bit - // 3. a0 is one or more of {b0, b1, b2} - // 4. b0 is one or more of {a1, a2} - // 5. a accesses memory, and the middle bit - // contains a store operation. - bool a_is_memory = candidate->mayLoad() || candidate->mayStore(); - - // Determine the number of operands in the slot instruction and in the - // candidate instruction. - const unsigned aend = getLastRealOperand(a); - const unsigned bend = getLastRealOperand(b); - - // Check hazards type 1, 2 and 5 by scanning the middle bit - MachineBasicBlock::iterator m = a; - for (++m; m != b; ++m) { - for (unsigned aop = 0; aop<aend; ++aop) { - bool aop_is_reg = a->getOperand(aop).isReg(); - if (!aop_is_reg) continue; - - bool aop_is_def = a->getOperand(aop).isDef(); - unsigned aop_reg = a->getOperand(aop).getReg(); - - const unsigned mend = getLastRealOperand(m); - for (unsigned mop = 0; mop<mend; ++mop) { - bool mop_is_reg = m->getOperand(mop).isReg(); - if (!mop_is_reg) continue; - - bool mop_is_def = m->getOperand(mop).isDef(); - unsigned mop_reg = m->getOperand(mop).getReg(); - - if (aop_is_def && (mop_reg == aop_reg)) - return true; // Hazard type 2, because aop = a0 - else if (mop_is_def && (mop_reg == aop_reg)) - return true; // Hazard type 1, because aop in {a1, a2} - } - } - - // Check hazard type 5 - if (a_is_memory && m->mayStore()) - return true; - } - - // Check hazard type 3 & 4 - for (unsigned aop = 0; aop<aend; ++aop) { - if (a->getOperand(aop).isReg()) { - unsigned aop_reg = a->getOperand(aop).getReg(); - - for (unsigned bop = 0; bop<bend; ++bop) { - if (b->getOperand(bop).isReg() && !b->getOperand(bop).isImplicit()) { - unsigned bop_reg = b->getOperand(bop).getReg(); - if (aop_reg == bop_reg) - return true; - } - } - } - } - - return false; -} - -static bool isDelayFiller(MachineBasicBlock &MBB, - MachineBasicBlock::iterator candidate) { - if (candidate == MBB.begin()) - return false; - - --candidate; - return (candidate->hasDelaySlot()); -} - -static bool hasUnknownSideEffects(MachineBasicBlock::iterator &I) { - if (!I->hasUnmodeledSideEffects()) - return false; - - unsigned op = I->getOpcode(); - if (op == MBlaze::ADDK || op == MBlaze::ADDIK || - op == MBlaze::ADDC || op == MBlaze::ADDIC || - op == MBlaze::ADDKC || op == MBlaze::ADDIKC || - op == MBlaze::RSUBK || op == MBlaze::RSUBIK || - op == MBlaze::RSUBC || op == MBlaze::RSUBIC || - op == MBlaze::RSUBKC || op == MBlaze::RSUBIKC) - return false; - - return true; -} - -static MachineBasicBlock::iterator -findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator slot) { - MachineBasicBlock::iterator I = slot; - while (true) { - if (I == MBB.begin()) - break; - - --I; - if (I->hasDelaySlot() || I->isBranch() || isDelayFiller(MBB,I) || - I->isCall() || I->isReturn() || I->isBarrier() || - hasUnknownSideEffects(I)) - break; - - if (hasImmInstruction(I) || delayHasHazard(I,slot)) - continue; - - return I; - } - - return MBB.end(); -} - -/// runOnMachineBasicBlock - Fill in delay slots for the given basic block. -/// Currently, we fill delay slots with NOPs. We assume there is only one -/// delay slot per delayed instruction. -bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { - bool Changed = false; - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) - if (I->hasDelaySlot()) { - MachineBasicBlock::iterator D = MBB.end(); - MachineBasicBlock::iterator J = I; - - if (!MBDisableDelaySlotFiller) - D = findDelayInstr(MBB,I); - - ++FilledSlots; - Changed = true; - - if (D == MBB.end()) - BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(MBlaze::NOP)); - else - MBB.splice(++J, &MBB, D); - } - return Changed; -} - -/// createMBlazeDelaySlotFillerPass - Returns a pass that fills in delay -/// slots in MBlaze MachineFunctions -FunctionPass *llvm::createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &tm) { - return new Filler(tm); -} - |