summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp')
-rw-r--r--contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp254
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);
-}
-
OpenPOWER on IntegriCloud