[Sparc] Bundle instruction with delay slow and its filler. Now, we can use -verify-machineinstrs with SPARC backend.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199014 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Venkatraman Govindaraju
2014-01-11 19:38:03 +00:00
parent ca179f4de8
commit 8104690370
3 changed files with 23 additions and 24 deletions

View File

@@ -19,6 +19,7 @@
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
@@ -55,15 +56,17 @@ namespace {
bool runOnMachineBasicBlock(MachineBasicBlock &MBB); bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
bool runOnMachineFunction(MachineFunction &F) { bool runOnMachineFunction(MachineFunction &F) {
bool Changed = false; bool Changed = false;
// 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(); for (MachineFunction::iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI) FI != FE; ++FI)
Changed |= runOnMachineBasicBlock(*FI); Changed |= runOnMachineBasicBlock(*FI);
return Changed; return Changed;
} }
bool isDelayFiller(MachineBasicBlock &MBB,
MachineBasicBlock::iterator candidate);
void insertCallDefsUses(MachineBasicBlock::iterator MI, void insertCallDefsUses(MachineBasicBlock::iterator MI,
SmallSet<unsigned, 32>& RegDefs, SmallSet<unsigned, 32>& RegDefs,
SmallSet<unsigned, 32>& RegUses); SmallSet<unsigned, 32>& RegUses);
@@ -152,6 +155,10 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
assert (J != MBB.end() && "MI needs a delay instruction."); assert (J != MBB.end() && "MI needs a delay instruction.");
BuildMI(MBB, ++J, MI->getDebugLoc(), BuildMI(MBB, ++J, MI->getDebugLoc(),
TII->get(SP::UNIMP)).addImm(structSize); 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; return Changed;
@@ -209,7 +216,7 @@ Filler::findDelayInstr(MachineBasicBlock &MBB,
|| I->isInlineAsm() || I->isInlineAsm()
|| I->isLabel() || I->isLabel()
|| I->hasDelaySlot() || I->hasDelaySlot()
|| isDelayFiller(MBB, I)) || I->isBundledWithSucc())
break; break;
if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) { if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) {
@@ -332,18 +339,6 @@ bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg)
return false; 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) bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
{ {
if (!I->isCall()) if (!I->isCall())
@@ -484,10 +479,10 @@ bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,
&& MBBI->getOperand(1).getReg() == SP::G0 && MBBI->getOperand(1).getReg() == SP::G0
&& MBBI->getOperand(2).getReg() == SP::G0); && MBBI->getOperand(2).getReg() == SP::G0);
MachineBasicBlock::iterator PrevInst = MBBI; --PrevInst; MachineBasicBlock::iterator PrevInst = llvm::prior(MBBI);
// It cannot combine with a delay filler. // It cannot be combined with a bundled instruction.
if (isDelayFiller(MBB, PrevInst)) if (PrevInst->isBundledWithSucc())
return false; return false;
const TargetInstrInfo *TII = TM.getInstrInfo(); const TargetInstrInfo *TII = TM.getInstrInfo();

View File

@@ -184,7 +184,6 @@ static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
{ {
MCInst TmpInst;
switch (MI->getOpcode()) { switch (MI->getOpcode()) {
default: break; default: break;
@@ -195,8 +194,13 @@ void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext); LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext);
return; return;
} }
LowerSparcMachineInstrToMCInst(MI, TmpInst, *this); MachineBasicBlock::const_instr_iterator I = MI;
OutStreamer.EmitInstruction(TmpInst); MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
do {
MCInst TmpInst;
LowerSparcMachineInstrToMCInst(I, TmpInst, *this);
OutStreamer.EmitInstruction(TmpInst);
} while ((++I != E) && I->isInsideBundle()); // Delay slot check.
} }
void SparcAsmPrinter::EmitFunctionBodyStart() { void SparcAsmPrinter::EmitFunctionBodyStart() {

View File

@@ -1,5 +1,5 @@
;RUN: llc -march=sparc < %s | FileCheck %s ;RUN: llc -march=sparc < %s -verify-machineinstrs | FileCheck %s
;RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=UNOPT ;RUN: llc -march=sparc -O0 < %s -verify-machineinstrs | FileCheck %s -check-prefix=UNOPT
define i32 @test(i32 %a) nounwind { define i32 @test(i32 %a) nounwind {