mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-23 12:08:25 +00:00
Add branch hinting for SPU.
The implemented algorithm is overly simplistic (just speculate all branches are taken)- this is work in progress. llvm-svn: 126651
This commit is contained in:
parent
195d2036d0
commit
cc5b703c81
@ -182,6 +182,10 @@ namespace {
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
}
|
||||
|
||||
void printHBROperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
}
|
||||
|
||||
void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
// Used to generate a ".-<target>", but it turns out that the assembler
|
||||
// really wants the target.
|
||||
@ -279,6 +283,9 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) {
|
||||
}
|
||||
O << *Mang->getSymbol(MO.getGlobal());
|
||||
return;
|
||||
case MachineOperand::MO_MCSymbol:
|
||||
O << *(MO.getMCSymbol());
|
||||
return;
|
||||
default:
|
||||
O << "<unknown operand type: " << MO.getType() << ">";
|
||||
return;
|
||||
|
@ -296,3 +296,25 @@ class Pseudo<dag OOL, dag IOL, string asmstr, list<dag> pattern>
|
||||
let Pattern = pattern;
|
||||
let Inst{31-0} = 0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Branch hint formats
|
||||
//===----------------------------------------------------------------------===//
|
||||
// For hbrr and hbra
|
||||
class HBI16Form<bits<7> opcode, dag IOL, string asmstr>
|
||||
: Instruction {
|
||||
field bits<32> Inst;
|
||||
bits<16>i16;
|
||||
bits<9>RO;
|
||||
|
||||
let Namespace = "SPU";
|
||||
let InOperandList = IOL;
|
||||
let OutOperandList = (outs); //no output
|
||||
let AsmString = asmstr;
|
||||
let Itinerary = BranchHints;
|
||||
|
||||
let Inst{0-6} = opcode;
|
||||
let Inst{7-8} = RO{8-7};
|
||||
let Inst{9-24} = i16;
|
||||
let Inst{25-31} = RO{6-0};
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -281,9 +282,20 @@ SPUInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
||||
return true;
|
||||
}
|
||||
|
||||
// search MBB for branch hint labels and branch hit ops
|
||||
static void removeHBR( MachineBasicBlock &MBB) {
|
||||
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I){
|
||||
if (I->getOpcode() == SPU::HBRA ||
|
||||
I->getOpcode() == SPU::HBR_LABEL){
|
||||
I=MBB.erase(I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
SPUInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
removeHBR(MBB);
|
||||
if (I == MBB.begin())
|
||||
return 0;
|
||||
--I;
|
||||
@ -314,6 +326,23 @@ SPUInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/** Find the optimal position for a hint branch instruction in a basic block.
|
||||
* This should take into account:
|
||||
* -the branch hint delays
|
||||
* -congestion of the memory bus
|
||||
* -dual-issue scheduling (i.e. avoid insertion of nops)
|
||||
* Current implementation is rather simplistic.
|
||||
*/
|
||||
static MachineBasicBlock::iterator findHBRPosition(MachineBasicBlock &MBB)
|
||||
{
|
||||
MachineBasicBlock::iterator J = MBB.end();
|
||||
for( int i=0; i<8; i++) {
|
||||
if( J == MBB.begin() ) return J;
|
||||
J--;
|
||||
}
|
||||
return J;
|
||||
}
|
||||
|
||||
unsigned
|
||||
SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
@ -324,32 +353,61 @@ SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
||||
"SPU branch conditions have two components!");
|
||||
|
||||
MachineInstrBuilder MIB;
|
||||
//TODO: make a more accurate algorithm.
|
||||
bool haveHBR = MBB.size()>8;
|
||||
|
||||
removeHBR(MBB);
|
||||
MCSymbol *branchLabel = MBB.getParent()->getContext().CreateTempSymbol();
|
||||
// Add a label just before the branch
|
||||
if (haveHBR)
|
||||
MIB = BuildMI(&MBB, DL, get(SPU::HBR_LABEL)).addSym(branchLabel);
|
||||
|
||||
// One-way branch.
|
||||
if (FBB == 0) {
|
||||
if (Cond.empty()) {
|
||||
// Unconditional branch
|
||||
MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(SPU::BR));
|
||||
MIB = BuildMI(&MBB, DL, get(SPU::BR));
|
||||
MIB.addMBB(TBB);
|
||||
|
||||
DEBUG(errs() << "Inserted one-way uncond branch: ");
|
||||
DEBUG((*MIB).dump());
|
||||
|
||||
// basic blocks have just one branch so it is safe to add the hint a its
|
||||
if (haveHBR) {
|
||||
MIB = BuildMI( MBB, findHBRPosition(MBB), DL, get(SPU::HBRA));
|
||||
MIB.addSym(branchLabel);
|
||||
MIB.addMBB(TBB);
|
||||
}
|
||||
} else {
|
||||
// Conditional branch
|
||||
MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
|
||||
MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
|
||||
MIB.addReg(Cond[1].getReg()).addMBB(TBB);
|
||||
|
||||
if (haveHBR) {
|
||||
MIB = BuildMI(MBB, findHBRPosition(MBB), DL, get(SPU::HBRA));
|
||||
MIB.addSym(branchLabel);
|
||||
MIB.addMBB(TBB);
|
||||
}
|
||||
|
||||
DEBUG(errs() << "Inserted one-way cond branch: ");
|
||||
DEBUG((*MIB).dump());
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
|
||||
MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
|
||||
MachineInstrBuilder MIB2 = BuildMI(&MBB, DL, get(SPU::BR));
|
||||
|
||||
// Two-way Conditional Branch.
|
||||
MIB.addReg(Cond[1].getReg()).addMBB(TBB);
|
||||
MIB2.addMBB(FBB);
|
||||
|
||||
if (haveHBR) {
|
||||
MIB = BuildMI( MBB, findHBRPosition(MBB), DL, get(SPU::HBRA));
|
||||
MIB.addSym(branchLabel);
|
||||
MIB.addMBB(FBB);
|
||||
}
|
||||
|
||||
DEBUG(errs() << "Inserted conditional branch: ");
|
||||
DEBUG((*MIB).dump());
|
||||
DEBUG(errs() << "part 2: ");
|
||||
|
@ -28,6 +28,8 @@ let hasCtrlDep = 1, Defs = [R1], Uses = [R1] in {
|
||||
def ADJCALLSTACKUP : Pseudo<(outs), (ins u16imm_i32:$amt),
|
||||
"${:comment} ADJCALLSTACKUP",
|
||||
[(callseq_end timm:$amt)]>;
|
||||
def HBR_LABEL : Pseudo<(outs), (ins hbrtarget:$targ),
|
||||
"$targ:\t${:comment}branch hint target",[ ]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -4208,8 +4210,8 @@ def : Pat<(fabs (v4f32 VECREG:$rA)),
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Hint for branch instructions:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* def HBR : SPUInstr<(outs), (ins), "hbr\t" */
|
||||
def HBRA :
|
||||
HBI16Form<0b0001001,(ins hbrtarget:$brinst, brtarget:$btarg), "hbra\t$brinst, $btarg">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Execution, Load NOP (execute NOPs belong in even pipeline, load NOPs belong
|
||||
|
Loading…
Reference in New Issue
Block a user