X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparc%2FDelaySlotFiller.cpp;h=c689b7f7201e207c3d56999f4f7d58b1b6fe1bc3;hb=39227c5849d4c0acbc228e54433c05833f2fea75;hp=5ec54a6a841d182ad4969619c0d2d44ca14447bd;hpb=1e06bcbd633175d75d13aaa5695ca0633ba86068;p=oota-llvm.git diff --git a/lib/Target/Sparc/DelaySlotFiller.cpp b/lib/Target/Sparc/DelaySlotFiller.cpp index 5ec54a6a841..c689b7f7201 100644 --- a/lib/Target/Sparc/DelaySlotFiller.cpp +++ b/lib/Target/Sparc/DelaySlotFiller.cpp @@ -12,12 +12,13 @@ // NOP is placed. //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "delay-slot-filler" #include "Sparc.h" +#include "SparcSubtarget.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" @@ -25,6 +26,8 @@ using namespace llvm; +#define DEBUG_TYPE "delay-slot-filler" + STATISTIC(FilledSlots, "Number of delay slots filled"); static cl::opt DisableDelaySlotFiller( @@ -39,28 +42,30 @@ namespace { /// layout, etc. /// TargetMachine &TM; - const TargetInstrInfo *TII; + const SparcSubtarget *Subtarget; static char ID; - Filler(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } + Filler(TargetMachine &tm) : MachineFunctionPass(ID), TM(tm) {} - virtual const char *getPassName() const { + const char *getPassName() const override { return "SPARC Delay Slot Filler"; } bool runOnMachineBasicBlock(MachineBasicBlock &MBB); - bool runOnMachineFunction(MachineFunction &F) { + bool runOnMachineFunction(MachineFunction &F) override { bool Changed = false; + Subtarget = &F.getSubtarget(); + + // This pass invalidates liveness information when it reorders + // instructions to fill delay slot. + F.getRegInfo().invalidateLiveness(); + for (MachineFunction::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) Changed |= runOnMachineBasicBlock(*FI); return Changed; } - bool isDelayFiller(MachineBasicBlock &MBB, - MachineBasicBlock::iterator candidate); - void insertCallDefsUses(MachineBasicBlock::iterator MI, SmallSet& RegDefs, SmallSet& RegUses); @@ -102,6 +107,8 @@ FunctionPass *llvm::createSparcDelaySlotFillerPass(TargetMachine &tm) { /// bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; + Subtarget = &MBB.getParent()->getSubtarget(); + const TargetInstrInfo *TII = Subtarget->getInstrInfo(); for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { MachineBasicBlock::iterator MI = I; @@ -115,6 +122,16 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { continue; } + // TODO: If we ever want to support v7, this needs to be extended + // to cover all floating point operations. + if (!Subtarget->isV9() && + (MI->getOpcode() == SP::FCMPS || MI->getOpcode() == SP::FCMPD + || MI->getOpcode() == SP::FCMPQ)) { + BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP)); + Changed = true; + continue; + } + // If MI has no delay slot, skip. if (!MI->hasDelaySlot()) continue; @@ -137,8 +154,12 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { MachineBasicBlock::iterator J = MI; ++J; // skip the delay filler. assert (J != MBB.end() && "MI needs a delay instruction."); - BuildMI(MBB, ++J, I->getDebugLoc(), + BuildMI(MBB, ++J, MI->getDebugLoc(), TII->get(SP::UNIMP)).addImm(structSize); + // Bundle the delay filler and unimp with the instruction. + MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), J); + } else { + MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), I); } } return Changed; @@ -156,7 +177,7 @@ Filler::findDelayInstr(MachineBasicBlock &MBB, if (slot == MBB.begin()) return MBB.end(); - if (slot->getOpcode() == SP::RET) + if (slot->getOpcode() == SP::RET || slot->getOpcode() == SP::TLS_CALL) return MBB.end(); if (slot->getOpcode() == SP::RETL) { @@ -166,7 +187,7 @@ Filler::findDelayInstr(MachineBasicBlock &MBB, if (J->getOpcode() == SP::RESTORErr || J->getOpcode() == SP::RESTOREri) { // change retl to ret. - slot->setDesc(TII->get(SP::RET)); + slot->setDesc(Subtarget->getInstrInfo()->get(SP::RET)); return J; } } @@ -191,12 +212,8 @@ Filler::findDelayInstr(MachineBasicBlock &MBB, if (I->isDebugValue()) continue; - - if (I->hasUnmodeledSideEffects() - || I->isInlineAsm() - || I->isLabel() - || I->hasDelaySlot() - || isDelayFiller(MBB, I)) + if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() || + I->hasDelaySlot() || I->isBundledWithSucc()) break; if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) { @@ -265,19 +282,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock::iterator MI, switch(MI->getOpcode()) { default: llvm_unreachable("Unknown opcode."); case SP::CALL: break; - case SP::JMPLrr: - case SP::JMPLri: + case SP::CALLrr: + case SP::CALLri: assert(MI->getNumOperands() >= 2); const MachineOperand &Reg = MI->getOperand(0); - assert(Reg.isReg() && "JMPL first operand is not a register."); - assert(Reg.isUse() && "JMPL first operand is not a use."); + assert(Reg.isReg() && "CALL first operand is not a register."); + assert(Reg.isUse() && "CALL first operand is not a use."); RegUses.insert(Reg.getReg()); const MachineOperand &RegOrImm = MI->getOperand(1); if (RegOrImm.isImm()) break; - assert(RegOrImm.isReg() && "JMPLrr second operand is not a register."); - assert(RegOrImm.isUse() && "JMPLrr second operand is not a use."); + assert(RegOrImm.isReg() && "CALLrr second operand is not a register."); + assert(RegOrImm.isUse() && "CALLrr second operand is not a use."); RegUses.insert(RegOrImm.getReg()); break; } @@ -312,25 +329,13 @@ void Filler::insertDefsUses(MachineBasicBlock::iterator MI, bool Filler::IsRegInSet(SmallSet& RegSet, unsigned Reg) { // Check Reg and all aliased Registers. - for (MCRegAliasIterator AI(Reg, TM.getRegisterInfo(), true); + for (MCRegAliasIterator AI(Reg, Subtarget->getRegisterInfo(), true); AI.isValid(); ++AI) if (RegSet.count(*AI)) return true; return false; } -// return true if the candidate is a delay filler. -bool Filler::isDelayFiller(MachineBasicBlock &MBB, - MachineBasicBlock::iterator candidate) -{ - if (candidate == MBB.begin()) - return false; - if (candidate->getOpcode() == SP::UNIMP) - return true; - --candidate; - return candidate->hasDelaySlot(); -} - bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize) { if (!I->isCall()) @@ -340,8 +345,9 @@ bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize) switch (I->getOpcode()) { default: llvm_unreachable("Unknown call opcode."); case SP::CALL: structSizeOpNum = 1; break; - case SP::JMPLrr: - case SP::JMPLri: structSizeOpNum = 2; break; + case SP::CALLrr: + case SP::CALLri: structSizeOpNum = 2; break; + case SP::TLS_CALL: return false; } const MachineOperand &MO = I->getOperand(structSizeOpNum); @@ -470,12 +476,14 @@ bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB, && MBBI->getOperand(1).getReg() == SP::G0 && MBBI->getOperand(2).getReg() == SP::G0); - MachineBasicBlock::iterator PrevInst = MBBI; --PrevInst; + MachineBasicBlock::iterator PrevInst = std::prev(MBBI); - // It cannot combine with a delay filler. - if (isDelayFiller(MBB, PrevInst)) + // It cannot be combined with a bundled instruction. + if (PrevInst->isBundledWithSucc()) return false; + const TargetInstrInfo *TII = Subtarget->getInstrInfo(); + switch (PrevInst->getOpcode()) { default: break; case SP::ADDrr: