mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-12 07:37:34 +00:00
Minor tuning -- avoid a non-inlinable function call on every operand.
Also, reorder a couple of functions for inlining. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6635 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9783301b9d
commit
cf819454e4
@ -115,6 +115,7 @@ namespace {
|
||||
class PreSelection : public BasicBlockPass, public InstVisitor<PreSelection>
|
||||
{
|
||||
const TargetMachine ⌖
|
||||
const TargetInstrInfo &instrInfo;
|
||||
Function* function;
|
||||
|
||||
GlobalVariable* getGlobalForConstant(Constant* CV) {
|
||||
@ -123,7 +124,8 @@ namespace {
|
||||
}
|
||||
|
||||
public:
|
||||
PreSelection (const TargetMachine &T): target(T), function(NULL) {}
|
||||
PreSelection (const TargetMachine &T):
|
||||
target(T), instrInfo(T.getInstrInfo()), function(NULL) {}
|
||||
|
||||
// runOnBasicBlock - apply this pass to each BB
|
||||
bool runOnBasicBlock(BasicBlock &BB) {
|
||||
@ -237,6 +239,75 @@ static Instruction* DecomposeConstantExpr(ConstantExpr* CE,
|
||||
//------------------------------------------------------------------------------
|
||||
// Instruction visitor methods to perform instruction-specific operations
|
||||
//------------------------------------------------------------------------------
|
||||
inline void
|
||||
PreSelection::visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
|
||||
Instruction& insertBefore)
|
||||
{
|
||||
if (GetElementPtrInst* gep = getGlobalAddr(Op, insertBefore)) {
|
||||
I.setOperand(opNum, gep); // replace global operand
|
||||
return;
|
||||
}
|
||||
|
||||
Constant* CV = dyn_cast<Constant>(Op);
|
||||
if (CV == NULL)
|
||||
return;
|
||||
|
||||
if (ConstantExpr* CE = dyn_cast<ConstantExpr>(CV))
|
||||
{ // load-time constant: factor it out so we optimize as best we can
|
||||
Instruction* computeConst = DecomposeConstantExpr(CE, insertBefore);
|
||||
I.setOperand(opNum, computeConst); // replace expr operand with result
|
||||
}
|
||||
else if (instrInfo.ConstantTypeMustBeLoaded(CV))
|
||||
{ // load address of constant into a register, then load the constant
|
||||
GetElementPtrInst* gep = getGlobalAddr(getGlobalForConstant(CV),
|
||||
insertBefore);
|
||||
LoadInst* ldI = new LoadInst(gep, "loadConst", &insertBefore);
|
||||
I.setOperand(opNum, ldI); // replace operand with copy in v.reg.
|
||||
}
|
||||
else if (instrInfo.ConstantMayNotFitInImmedField(CV, &I))
|
||||
{ // put the constant into a virtual register using a cast
|
||||
CastInst* castI = new CastInst(CV, CV->getType(), "copyConst",
|
||||
&insertBefore);
|
||||
I.setOperand(opNum, castI); // replace operand with copy in v.reg.
|
||||
}
|
||||
}
|
||||
|
||||
// visitOperands() transforms individual operands of all instructions:
|
||||
// -- Load "large" int constants into a virtual register. What is large
|
||||
// depends on the type of instruction and on the target architecture.
|
||||
// -- For any constants that cannot be put in an immediate field,
|
||||
// load address into virtual register first, and then load the constant.
|
||||
//
|
||||
// firstOp and lastOp can be used to skip leading and trailing operands.
|
||||
// If lastOp is 0, it defaults to #operands or #incoming Phi values.
|
||||
//
|
||||
inline void
|
||||
PreSelection::visitOperands(Instruction &I, int firstOp, int lastOp)
|
||||
{
|
||||
// For any instruction other than PHI, copies go just before the instr.
|
||||
// For a PHI, operand copies must be before the terminator of the
|
||||
// appropriate predecessor basic block. Remaining logic is simple
|
||||
// so just handle PHIs and other instructions separately.
|
||||
//
|
||||
if (PHINode* phi = dyn_cast<PHINode>(&I))
|
||||
{
|
||||
if (lastOp == 0)
|
||||
lastOp = phi->getNumIncomingValues();
|
||||
for (unsigned i=firstOp, N=lastOp; i < N; ++i)
|
||||
this->visitOneOperand(I, phi->getIncomingValue(i),
|
||||
phi->getOperandNumForIncomingValue(i),
|
||||
* phi->getIncomingBlock(i)->getTerminator());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastOp == 0)
|
||||
lastOp = I.getNumOperands();
|
||||
for (unsigned i=firstOp, N=lastOp; i < N; ++i)
|
||||
this->visitOneOperand(I, I.getOperand(i), i, I);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Common work for *all* instructions. This needs to be called explicitly
|
||||
// by other visit<InstructionType> functions.
|
||||
@ -329,75 +400,6 @@ PreSelection::visitCallInst(CallInst &I)
|
||||
}
|
||||
|
||||
|
||||
// visitOperands() transforms individual operands of all instructions:
|
||||
// -- Load "large" int constants into a virtual register. What is large
|
||||
// depends on the type of instruction and on the target architecture.
|
||||
// -- For any constants that cannot be put in an immediate field,
|
||||
// load address into virtual register first, and then load the constant.
|
||||
//
|
||||
// firstOp and lastOp can be used to skip leading and trailing operands.
|
||||
// If lastOp is 0, it defaults to #operands or #incoming Phi values.
|
||||
//
|
||||
void
|
||||
PreSelection::visitOperands(Instruction &I, int firstOp, int lastOp)
|
||||
{
|
||||
// For any instruction other than PHI, copies go just before the instr.
|
||||
// For a PHI, operand copies must be before the terminator of the
|
||||
// appropriate predecessor basic block. Remaining logic is simple
|
||||
// so just handle PHIs and other instructions separately.
|
||||
//
|
||||
if (PHINode* phi = dyn_cast<PHINode>(&I))
|
||||
{
|
||||
if (lastOp == 0)
|
||||
lastOp = phi->getNumIncomingValues();
|
||||
for (unsigned i=firstOp, N=lastOp; i < N; ++i)
|
||||
this->visitOneOperand(I, phi->getIncomingValue(i),
|
||||
phi->getOperandNumForIncomingValue(i),
|
||||
* phi->getIncomingBlock(i)->getTerminator());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastOp == 0)
|
||||
lastOp = I.getNumOperands();
|
||||
for (unsigned i=firstOp, N=lastOp; i < N; ++i)
|
||||
this->visitOneOperand(I, I.getOperand(i), i, I);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PreSelection::visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
|
||||
Instruction& insertBefore)
|
||||
{
|
||||
if (GetElementPtrInst* gep = getGlobalAddr(Op, insertBefore)) {
|
||||
I.setOperand(opNum, gep); // replace global operand
|
||||
return;
|
||||
}
|
||||
|
||||
Constant* CV = dyn_cast<Constant>(Op);
|
||||
if (CV == NULL)
|
||||
return;
|
||||
|
||||
if (ConstantExpr* CE = dyn_cast<ConstantExpr>(CV))
|
||||
{ // load-time constant: factor it out so we optimize as best we can
|
||||
Instruction* computeConst = DecomposeConstantExpr(CE, insertBefore);
|
||||
I.setOperand(opNum, computeConst); // replace expr operand with result
|
||||
}
|
||||
else if (target.getInstrInfo().ConstantTypeMustBeLoaded(CV))
|
||||
{ // load address of constant into a register, then load the constant
|
||||
GetElementPtrInst* gep = getGlobalAddr(getGlobalForConstant(CV),
|
||||
insertBefore);
|
||||
LoadInst* ldI = new LoadInst(gep, "loadConst", &insertBefore);
|
||||
I.setOperand(opNum, ldI); // replace operand with copy in v.reg.
|
||||
}
|
||||
else if (target.getInstrInfo().ConstantMayNotFitInImmedField(CV, &I))
|
||||
{ // put the constant into a virtual register using a cast
|
||||
CastInst* castI = new CastInst(CV, CV->getType(), "copyConst",
|
||||
&insertBefore);
|
||||
I.setOperand(opNum, castI); // replace operand with copy in v.reg.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// createPreSelectionPass - Public entrypoint for pre-selection pass
|
||||
// and this file as a whole...
|
||||
|
Loading…
x
Reference in New Issue
Block a user