forked from OSchip/llvm-project
Support generating machine instructions for Phi nodes (based on x86, but with
modifications for 1 LLVM BB --> many MBBs). Fix store operand order: make it always be Base, Offset, SrcReg (think "[ Base + Offset ] = SrcReg"). Rewrite visitBranchInst() to be even dumber (but working) -- give up on the branch fallthrough trick, for the time being. Make visitSetCondInst() work. llvm-svn: 14208
This commit is contained in:
parent
a067fb3e6b
commit
c4ee938f55
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "SparcV8.h"
|
#include "SparcV8.h"
|
||||||
#include "SparcV8InstrInfo.h"
|
#include "SparcV8InstrInfo.h"
|
||||||
|
#include "Support/Debug.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/IntrinsicLowering.h"
|
#include "llvm/IntrinsicLowering.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
@ -92,6 +93,12 @@ namespace {
|
||||||
|
|
||||||
void LoadArgumentsToVirtualRegs(Function *F);
|
void LoadArgumentsToVirtualRegs(Function *F);
|
||||||
|
|
||||||
|
/// SelectPHINodes - Insert machine code to generate phis. This is tricky
|
||||||
|
/// because we have to generate our sources into the source basic blocks,
|
||||||
|
/// not the current one.
|
||||||
|
///
|
||||||
|
void SelectPHINodes();
|
||||||
|
|
||||||
/// copyConstantToRegister - Output the instructions required to put the
|
/// copyConstantToRegister - Output the instructions required to put the
|
||||||
/// specified constant into the specified register.
|
/// specified constant into the specified register.
|
||||||
///
|
///
|
||||||
|
@ -303,6 +310,102 @@ void V8ISel::LoadArgumentsToVirtualRegs (Function *F) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V8ISel::SelectPHINodes() {
|
||||||
|
const TargetInstrInfo &TII = *TM.getInstrInfo();
|
||||||
|
const Function &LF = *F->getFunction(); // The LLVM function...
|
||||||
|
for (Function::const_iterator I = LF.begin(), E = LF.end(); I != E; ++I) {
|
||||||
|
const BasicBlock *BB = I;
|
||||||
|
MachineBasicBlock &MBB = *MBBMap[I];
|
||||||
|
|
||||||
|
// Loop over all of the PHI nodes in the LLVM basic block...
|
||||||
|
MachineBasicBlock::iterator PHIInsertPoint = MBB.begin();
|
||||||
|
for (BasicBlock::const_iterator I = BB->begin();
|
||||||
|
PHINode *PN = const_cast<PHINode*>(dyn_cast<PHINode>(I)); ++I) {
|
||||||
|
|
||||||
|
// Create a new machine instr PHI node, and insert it.
|
||||||
|
unsigned PHIReg = getReg(*PN);
|
||||||
|
MachineInstr *PhiMI = BuildMI(MBB, PHIInsertPoint,
|
||||||
|
V8::PHI, PN->getNumOperands(), PHIReg);
|
||||||
|
|
||||||
|
MachineInstr *LongPhiMI = 0;
|
||||||
|
if (PN->getType() == Type::LongTy || PN->getType() == Type::ULongTy)
|
||||||
|
LongPhiMI = BuildMI(MBB, PHIInsertPoint,
|
||||||
|
V8::PHI, PN->getNumOperands(), PHIReg+1);
|
||||||
|
|
||||||
|
// PHIValues - Map of blocks to incoming virtual registers. We use this
|
||||||
|
// so that we only initialize one incoming value for a particular block,
|
||||||
|
// even if the block has multiple entries in the PHI node.
|
||||||
|
//
|
||||||
|
std::map<MachineBasicBlock*, unsigned> PHIValues;
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
||||||
|
MachineBasicBlock *PredMBB = 0;
|
||||||
|
for (MachineBasicBlock::pred_iterator PI = MBB.pred_begin (),
|
||||||
|
PE = MBB.pred_end (); PI != PE; ++PI)
|
||||||
|
if (PN->getIncomingBlock(i) == (*PI)->getBasicBlock()) {
|
||||||
|
PredMBB = *PI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert (PredMBB && "Couldn't find incoming machine-cfg edge for phi");
|
||||||
|
|
||||||
|
unsigned ValReg;
|
||||||
|
std::map<MachineBasicBlock*, unsigned>::iterator EntryIt =
|
||||||
|
PHIValues.lower_bound(PredMBB);
|
||||||
|
|
||||||
|
if (EntryIt != PHIValues.end() && EntryIt->first == PredMBB) {
|
||||||
|
// We already inserted an initialization of the register for this
|
||||||
|
// predecessor. Recycle it.
|
||||||
|
ValReg = EntryIt->second;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Get the incoming value into a virtual register.
|
||||||
|
//
|
||||||
|
Value *Val = PN->getIncomingValue(i);
|
||||||
|
|
||||||
|
// If this is a constant or GlobalValue, we may have to insert code
|
||||||
|
// into the basic block to compute it into a virtual register.
|
||||||
|
if ((isa<Constant>(Val) && !isa<ConstantExpr>(Val)) ||
|
||||||
|
isa<GlobalValue>(Val)) {
|
||||||
|
// Simple constants get emitted at the end of the basic block,
|
||||||
|
// before any terminator instructions. We "know" that the code to
|
||||||
|
// move a constant into a register will never clobber any flags.
|
||||||
|
ValReg = getReg(Val, PredMBB, PredMBB->getFirstTerminator());
|
||||||
|
} else {
|
||||||
|
// Because we don't want to clobber any values which might be in
|
||||||
|
// physical registers with the computation of this constant (which
|
||||||
|
// might be arbitrarily complex if it is a constant expression),
|
||||||
|
// just insert the computation at the top of the basic block.
|
||||||
|
MachineBasicBlock::iterator PI = PredMBB->begin();
|
||||||
|
|
||||||
|
// Skip over any PHI nodes though!
|
||||||
|
while (PI != PredMBB->end() && PI->getOpcode() == V8::PHI)
|
||||||
|
++PI;
|
||||||
|
|
||||||
|
ValReg = getReg(Val, PredMBB, PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember that we inserted a value for this PHI for this predecessor
|
||||||
|
PHIValues.insert(EntryIt, std::make_pair(PredMBB, ValReg));
|
||||||
|
}
|
||||||
|
|
||||||
|
PhiMI->addRegOperand(ValReg);
|
||||||
|
PhiMI->addMachineBasicBlockOperand(PredMBB);
|
||||||
|
if (LongPhiMI) {
|
||||||
|
LongPhiMI->addRegOperand(ValReg+1);
|
||||||
|
LongPhiMI->addMachineBasicBlockOperand(PredMBB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we emitted all of the incoming values for the PHI node, make
|
||||||
|
// sure to reposition the InsertPoint after the PHI that we just added.
|
||||||
|
// This is needed because we might have inserted a constant into this
|
||||||
|
// block, right after the PHI's which is before the old insert point!
|
||||||
|
PHIInsertPoint = LongPhiMI ? LongPhiMI : PhiMI;
|
||||||
|
++PHIInsertPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool V8ISel::runOnFunction(Function &Fn) {
|
bool V8ISel::runOnFunction(Function &Fn) {
|
||||||
// First pass over the function, lower any unknown intrinsic functions
|
// First pass over the function, lower any unknown intrinsic functions
|
||||||
// with the IntrinsicLowering class.
|
// with the IntrinsicLowering class.
|
||||||
|
@ -327,7 +430,7 @@ bool V8ISel::runOnFunction(Function &Fn) {
|
||||||
visit(Fn);
|
visit(Fn);
|
||||||
|
|
||||||
// Select the PHI nodes
|
// Select the PHI nodes
|
||||||
//SelectPHINodes();
|
SelectPHINodes();
|
||||||
|
|
||||||
RegMap.clear();
|
RegMap.clear();
|
||||||
MBBMap.clear();
|
MBBMap.clear();
|
||||||
|
@ -421,16 +524,16 @@ void V8ISel::visitStoreInst(StoreInst &I) {
|
||||||
unsigned PtrReg = getReg (I.getOperand (1));
|
unsigned PtrReg = getReg (I.getOperand (1));
|
||||||
switch (getClassB (SrcVal->getType ())) {
|
switch (getClassB (SrcVal->getType ())) {
|
||||||
case cByte:
|
case cByte:
|
||||||
BuildMI (BB, V8::STBrm, 1, SrcReg).addReg (PtrReg).addSImm(0);
|
BuildMI (BB, V8::STBrm, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
|
||||||
return;
|
return;
|
||||||
case cShort:
|
case cShort:
|
||||||
BuildMI (BB, V8::STHrm, 1, SrcReg).addReg (PtrReg).addSImm(0);
|
BuildMI (BB, V8::STHrm, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
|
||||||
return;
|
return;
|
||||||
case cInt:
|
case cInt:
|
||||||
BuildMI (BB, V8::STrm, 1, SrcReg).addReg (PtrReg).addSImm(0);
|
BuildMI (BB, V8::STrm, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
|
||||||
return;
|
return;
|
||||||
case cLong:
|
case cLong:
|
||||||
BuildMI (BB, V8::STDrm, 1, SrcReg).addReg (PtrReg).addSImm(0);
|
BuildMI (BB, V8::STDrm, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
std::cerr << "Store instruction not handled: " << I;
|
std::cerr << "Store instruction not handled: " << I;
|
||||||
|
@ -499,32 +602,22 @@ static inline BasicBlock *getBlockAfter(BasicBlock *BB) {
|
||||||
/// visitBranchInst - Handles conditional and unconditional branches.
|
/// visitBranchInst - Handles conditional and unconditional branches.
|
||||||
///
|
///
|
||||||
void V8ISel::visitBranchInst(BranchInst &I) {
|
void V8ISel::visitBranchInst(BranchInst &I) {
|
||||||
// Update machine-CFG edges
|
|
||||||
BB->addSuccessor (MBBMap[I.getSuccessor(0)]);
|
|
||||||
if (I.isConditional())
|
|
||||||
BB->addSuccessor (MBBMap[I.getSuccessor(1)]);
|
|
||||||
|
|
||||||
BasicBlock *NextBB = getBlockAfter(I.getParent()); // BB after current one
|
|
||||||
|
|
||||||
BasicBlock *takenSucc = I.getSuccessor (0);
|
BasicBlock *takenSucc = I.getSuccessor (0);
|
||||||
if (!I.isConditional()) { // Unconditional branch?
|
MachineBasicBlock *takenSuccMBB = MBBMap[takenSucc];
|
||||||
if (I.getSuccessor(0) != NextBB)
|
BB->addSuccessor (takenSuccMBB);
|
||||||
BuildMI (BB, V8::BA, 1).addMBB (MBBMap[takenSucc]);
|
if (I.isConditional()) { // conditional branch
|
||||||
return;
|
BasicBlock *notTakenSucc = I.getSuccessor (1);
|
||||||
}
|
MachineBasicBlock *notTakenSuccMBB = MBBMap[notTakenSucc];
|
||||||
|
BB->addSuccessor (notTakenSuccMBB);
|
||||||
|
|
||||||
unsigned CondReg = getReg (I.getCondition ());
|
// CondReg=(<condition>);
|
||||||
BasicBlock *notTakenSucc = I.getSuccessor (1);
|
// If (CondReg==0) goto notTakenSuccMBB;
|
||||||
// Set Z condition code if CondReg was false
|
unsigned CondReg = getReg (I.getCondition ());
|
||||||
BuildMI (BB, V8::CMPri, 2).addSImm (0).addReg (CondReg);
|
BuildMI (BB, V8::CMPri, 2).addSImm (0).addReg (CondReg);
|
||||||
if (notTakenSucc == NextBB) {
|
BuildMI (BB, V8::BE, 1).addMBB (notTakenSuccMBB);
|
||||||
if (takenSucc != NextBB)
|
|
||||||
BuildMI (BB, V8::BNE, 1).addMBB (MBBMap[takenSucc]);
|
|
||||||
} else {
|
|
||||||
BuildMI (BB, V8::BE, 1).addMBB (MBBMap[notTakenSucc]);
|
|
||||||
if (takenSucc != NextBB)
|
|
||||||
BuildMI (BB, V8::BA, 1).addMBB (MBBMap[takenSucc]);
|
|
||||||
}
|
}
|
||||||
|
// goto takenSuccMBB;
|
||||||
|
BuildMI (BB, V8::BA, 1).addMBB (takenSuccMBB);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emitGEPOperation - Common code shared between visitGetElementPtrInst and
|
/// emitGEPOperation - Common code shared between visitGetElementPtrInst and
|
||||||
|
@ -714,29 +807,62 @@ void V8ISel::visitSetCondInst(Instruction &I) {
|
||||||
V8::BLEU, V8::BLE, // setle = bleu ble
|
V8::BLEU, V8::BLE, // setle = bleu ble
|
||||||
V8::BCC, V8::BGE // setge = bcc bge
|
V8::BCC, V8::BGE // setge = bcc bge
|
||||||
};
|
};
|
||||||
unsigned Opcode = OpcodeTab[BranchIdx + (Ty->isSigned() ? 1 : 0)];
|
unsigned Opcode = OpcodeTab[2*BranchIdx + (Ty->isSigned() ? 1 : 0)];
|
||||||
MachineBasicBlock *Copy1MBB, *Copy0MBB, *CopyCondMBB;
|
|
||||||
MachineBasicBlock::iterator IP;
|
MachineBasicBlock *thisMBB = BB;
|
||||||
#if 0
|
const BasicBlock *LLVM_BB = BB->getBasicBlock ();
|
||||||
// Cond. Branch from BB --> either Copy1MBB or Copy0MBB --> CopyCondMBB
|
// thisMBB:
|
||||||
// Then once we're done with the SetCC, BB = CopyCondMBB.
|
// ...
|
||||||
BasicBlock *LLVM_BB = BB.getBasicBlock ();
|
// subcc %reg0, %reg1, %g0
|
||||||
unsigned Cond0Reg = makeAnotherReg (I.getType ());
|
// bCC copy1MBB
|
||||||
unsigned Cond1Reg = makeAnotherReg (I.getType ());
|
// ba copy0MBB
|
||||||
F->getBasicBlockList ().push_back (Copy1MBB = new MachineBasicBlock (LLVM_BB));
|
|
||||||
F->getBasicBlockList ().push_back (Copy0MBB = new MachineBasicBlock (LLVM_BB));
|
// FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB)
|
||||||
F->getBasicBlockList ().push_back (CopyCondMBB = new MachineBasicBlock (LLVM_BB));
|
// if we could insert other, non-terminator instructions after the
|
||||||
BuildMI (BB, Opcode, 1).addMBB (Copy1MBB);
|
// bCC. But MBB->getFirstTerminator() can't understand this.
|
||||||
BuildMI (BB, V8::BA, 1).addMBB (Copy0MBB);
|
MachineBasicBlock *copy1MBB = new MachineBasicBlock (LLVM_BB);
|
||||||
IP = Copy1MBB->begin ();
|
F->getBasicBlockList ().push_back (copy1MBB);
|
||||||
BuildMI (*Copy1MBB, IP, V8::ORri, 2, Cond1Reg).addZImm (1).addReg (V8::G0);
|
BuildMI (BB, Opcode, 1).addMBB (copy1MBB);
|
||||||
BuildMI (*Copy1MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
|
MachineBasicBlock *copy0MBB = new MachineBasicBlock (LLVM_BB);
|
||||||
IP = Copy0MBB->begin ();
|
F->getBasicBlockList ().push_back (copy0MBB);
|
||||||
BuildMI (*Copy0MBB, IP, V8::ORri, 2, Cond0Reg).addZImm (0).addReg (V8::G0);
|
BuildMI (BB, V8::BA, 1).addMBB (copy0MBB);
|
||||||
BuildMI (*Copy0MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
|
// Update machine-CFG edges
|
||||||
// What should go in CopyCondMBB: PHI, then OR to copy cond. reg to DestReg
|
BB->addSuccessor (copy1MBB);
|
||||||
#endif
|
BB->addSuccessor (copy0MBB);
|
||||||
visitInstruction(I);
|
|
||||||
|
// copy0MBB:
|
||||||
|
// %FalseValue = or %G0, 0
|
||||||
|
// ba sinkMBB
|
||||||
|
BB = copy0MBB;
|
||||||
|
unsigned FalseValue = makeAnotherReg (I.getType ());
|
||||||
|
BuildMI (BB, V8::ORri, 2, FalseValue).addReg (V8::G0).addZImm (0);
|
||||||
|
MachineBasicBlock *sinkMBB = new MachineBasicBlock (LLVM_BB);
|
||||||
|
F->getBasicBlockList ().push_back (sinkMBB);
|
||||||
|
BuildMI (BB, V8::BA, 1).addMBB (sinkMBB);
|
||||||
|
// Update machine-CFG edges
|
||||||
|
BB->addSuccessor (sinkMBB);
|
||||||
|
|
||||||
|
DEBUG (std::cerr << "thisMBB is at " << (void*)thisMBB << "\n");
|
||||||
|
DEBUG (std::cerr << "copy1MBB is at " << (void*)copy1MBB << "\n");
|
||||||
|
DEBUG (std::cerr << "copy0MBB is at " << (void*)copy0MBB << "\n");
|
||||||
|
DEBUG (std::cerr << "sinkMBB is at " << (void*)sinkMBB << "\n");
|
||||||
|
|
||||||
|
// copy1MBB:
|
||||||
|
// %TrueValue = or %G0, 1
|
||||||
|
// ba sinkMBB
|
||||||
|
BB = copy1MBB;
|
||||||
|
unsigned TrueValue = makeAnotherReg (I.getType ());
|
||||||
|
BuildMI (BB, V8::ORri, 2, TrueValue).addReg (V8::G0).addZImm (1);
|
||||||
|
BuildMI (BB, V8::BA, 1).addMBB (sinkMBB);
|
||||||
|
// Update machine-CFG edges
|
||||||
|
BB->addSuccessor (sinkMBB);
|
||||||
|
|
||||||
|
// sinkMBB:
|
||||||
|
// %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, copy1MBB ]
|
||||||
|
// ...
|
||||||
|
BB = sinkMBB;
|
||||||
|
BuildMI (BB, V8::PHI, 4, DestReg).addReg (FalseValue)
|
||||||
|
.addMBB (copy0MBB).addReg (TrueValue).addMBB (copy1MBB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue