mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-13 10:32:06 +00:00
Insert code to load constants used as Call or Return arguments.
Also, note return value of a Call as an "implicitUse". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@720 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a1d14f3555
commit
8557b226f3
@ -11,6 +11,7 @@
|
|||||||
//**************************************************************************/
|
//**************************************************************************/
|
||||||
|
|
||||||
#include "SparcInternals.h"
|
#include "SparcInternals.h"
|
||||||
|
#include "llvm/CodeGen/InstrSelectionSupport.h"
|
||||||
#include "llvm/CodeGen/MachineInstr.h"
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
#include "llvm/CodeGen/InstrForest.h"
|
#include "llvm/CodeGen/InstrForest.h"
|
||||||
#include "llvm/CodeGen/InstrSelection.h"
|
#include "llvm/CodeGen/InstrSelection.h"
|
||||||
@ -1027,8 +1028,6 @@ CreateIntSetInstruction(int64_t C, bool isSigned, Value* dest)
|
|||||||
// Create an instruction sequence to load a constant into a register.
|
// Create an instruction sequence to load a constant into a register.
|
||||||
// This always creates either one or two instructions.
|
// This always creates either one or two instructions.
|
||||||
// If two instructions are created, the second one is returned in getMinstr2
|
// If two instructions are created, the second one is returned in getMinstr2
|
||||||
// The implicit virtual register used to hold the constant is returned in
|
|
||||||
// tmpReg.
|
|
||||||
//
|
//
|
||||||
static MachineInstr*
|
static MachineInstr*
|
||||||
CreateLoadConstInstr(const TargetMachine &target,
|
CreateLoadConstInstr(const TargetMachine &target,
|
||||||
@ -1078,18 +1077,18 @@ CreateLoadConstInstr(const TargetMachine &target,
|
|||||||
// The constant actually has an integer value, so use a
|
// The constant actually has an integer value, so use a
|
||||||
// [set; int-to-float] sequence instead of a load instruction.
|
// [set; int-to-float] sequence instead of a load instruction.
|
||||||
//
|
//
|
||||||
TmpInstruction* tmpReg2 = NULL;
|
TmpInstruction* addrReg = NULL;
|
||||||
if (dval != 0.0)
|
if (dval != 0.0)
|
||||||
{ // First, create an integer constant of the same value as dval
|
{ // First, create an integer constant of the same value as dval
|
||||||
ConstPoolSInt* ival = ConstPoolSInt::get(Type::IntTy,
|
ConstPoolSInt* ival = ConstPoolSInt::get(Type::IntTy,
|
||||||
(int64_t) dval);
|
(int64_t) dval);
|
||||||
// Create another TmpInstruction for the hidden integer register
|
// Create another TmpInstruction for the hidden integer register
|
||||||
tmpReg2 = new TmpInstruction(Instruction::UserOp1, ival, NULL);
|
addrReg = new TmpInstruction(Instruction::UserOp1, ival, NULL);
|
||||||
vmInstr->getMachineInstrVec().addTempValue(tmpReg2);
|
vmInstr->getMachineInstrVec().addTempValue(addrReg);
|
||||||
|
|
||||||
// Create the `SET' instruction
|
// Create the `SET' instruction
|
||||||
minstr1 = CreateIntSetInstruction((int64_t)dval, true, tmpReg2);
|
minstr1 = CreateIntSetInstruction((int64_t)dval, true, addrReg);
|
||||||
tmpReg2->addMachineInstruction(minstr1);
|
addrReg->addMachineInstruction(minstr1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In which variable do we put the second instruction?
|
// In which variable do we put the second instruction?
|
||||||
@ -1102,7 +1101,7 @@ CreateLoadConstInstr(const TargetMachine &target,
|
|||||||
instr2->SetMachineOperand(0, target.getRegInfo().getZeroRegNum());
|
instr2->SetMachineOperand(0, target.getRegInfo().getZeroRegNum());
|
||||||
else
|
else
|
||||||
instr2->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
|
instr2->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
|
||||||
tmpReg2);
|
addrReg);
|
||||||
|
|
||||||
instr2->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
|
instr2->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
|
||||||
dest);
|
dest);
|
||||||
@ -1112,26 +1111,26 @@ CreateLoadConstInstr(const TargetMachine &target,
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Make an instruction sequence to load the constant, viz:
|
// Make an instruction sequence to load the constant, viz:
|
||||||
// SETSW <addr-of-constant>, tmpReg2
|
// SETSW <addr-of-constant>, addrReg
|
||||||
// LOAD /*addr*/ tmpReg2, /*offset*/ 0, dest
|
// LOAD /*addr*/ addrReg, /*offset*/ 0, dest
|
||||||
// set the offset field to 0.
|
// set the offset field to 0.
|
||||||
//
|
//
|
||||||
int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
|
int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
|
||||||
|
|
||||||
// Create another TmpInstruction for the hidden integer register
|
// Create another TmpInstruction for the hidden integer register
|
||||||
TmpInstruction* tmpReg2 =
|
TmpInstruction* addrReg =
|
||||||
new TmpInstruction(Instruction::UserOp1, val, NULL);
|
new TmpInstruction(Instruction::UserOp1, val, NULL);
|
||||||
vmInstr->getMachineInstrVec().addTempValue(tmpReg2);
|
vmInstr->getMachineInstrVec().addTempValue(addrReg);
|
||||||
|
|
||||||
minstr1 = new MachineInstr(SETUW);
|
minstr1 = new MachineInstr(SETUW);
|
||||||
minstr1->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp,val);
|
minstr1->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp,val);
|
||||||
minstr1->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
|
minstr1->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
|
||||||
tmpReg2);
|
addrReg);
|
||||||
tmpReg2->addMachineInstruction(minstr1);
|
addrReg->addMachineInstruction(minstr1);
|
||||||
|
|
||||||
getMinstr2 = new MachineInstr(ChooseLoadInstruction(val->getType()));
|
getMinstr2 = new MachineInstr(ChooseLoadInstruction(val->getType()));
|
||||||
getMinstr2->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
|
getMinstr2->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
|
||||||
tmpReg2);
|
addrReg);
|
||||||
getMinstr2->SetMachineOperand(1,MachineOperand::MO_SignExtendedImmed,
|
getMinstr2->SetMachineOperand(1,MachineOperand::MO_SignExtendedImmed,
|
||||||
zeroOffset);
|
zeroOffset);
|
||||||
getMinstr2->SetMachineOperand(2,MachineOperand::MO_VirtualRegister,
|
getMinstr2->SetMachineOperand(2,MachineOperand::MO_VirtualRegister,
|
||||||
@ -1143,6 +1142,35 @@ CreateLoadConstInstr(const TargetMachine &target,
|
|||||||
return minstr1;
|
return minstr1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TmpInstruction*
|
||||||
|
InsertCodeToLoadConstant(ConstPoolVal* opValue,
|
||||||
|
Instruction* vmInstr,
|
||||||
|
vector<MachineInstr*> loadConstVec,
|
||||||
|
TargetMachine& target)
|
||||||
|
{
|
||||||
|
// value is constant and must be loaded into a register.
|
||||||
|
// First, create a tmp virtual register (TmpInstruction)
|
||||||
|
// to hold the constant.
|
||||||
|
// This will replace the constant operand in `minstr'.
|
||||||
|
TmpInstruction* tmpReg =
|
||||||
|
new TmpInstruction(Instruction::UserOp1, opValue, NULL);
|
||||||
|
vmInstr->getMachineInstrVec().addTempValue(tmpReg);
|
||||||
|
|
||||||
|
MachineInstr *minstr1, *minstr2;
|
||||||
|
minstr1 = CreateLoadConstInstr(target, vmInstr,
|
||||||
|
opValue, tmpReg, minstr2);
|
||||||
|
|
||||||
|
loadConstVec.push_back(minstr1);
|
||||||
|
if (minstr2 != NULL)
|
||||||
|
loadConstVec.push_back(minstr2);
|
||||||
|
|
||||||
|
tmpReg->addMachineInstruction(loadConstVec.back());
|
||||||
|
|
||||||
|
return tmpReg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Special handling for constant operands:
|
// Special handling for constant operands:
|
||||||
// -- if the constant is 0, use the hardwired 0 register, if any;
|
// -- if the constant is 0, use the hardwired 0 register, if any;
|
||||||
// -- if the constant is of float or double type but has an integer value,
|
// -- if the constant is of float or double type but has an integer value,
|
||||||
@ -1157,9 +1185,9 @@ FixConstantOperands(const InstructionNode* vmInstrNode,
|
|||||||
unsigned numInstr,
|
unsigned numInstr,
|
||||||
TargetMachine& target)
|
TargetMachine& target)
|
||||||
{
|
{
|
||||||
static MachineInstr* loadConstVec[MAX_INSTR_PER_VMINSTR];
|
vector<MachineInstr*> loadConstVec;
|
||||||
|
loadConstVec.reserve(MAX_INSTR_PER_VMINSTR);
|
||||||
|
|
||||||
unsigned numNew = 0;
|
|
||||||
Instruction* vmInstr = vmInstrNode->getInstruction();
|
Instruction* vmInstr = vmInstrNode->getInstruction();
|
||||||
|
|
||||||
for (unsigned i=0; i < numInstr; i++)
|
for (unsigned i=0; i < numInstr; i++)
|
||||||
@ -1196,23 +1224,10 @@ FixConstantOperands(const InstructionNode* vmInstrNode,
|
|||||||
minstr->SetMachineOperand(op, machineRegNum);
|
minstr->SetMachineOperand(op, machineRegNum);
|
||||||
else if (opType == MachineOperand::MO_VirtualRegister)
|
else if (opType == MachineOperand::MO_VirtualRegister)
|
||||||
{
|
{
|
||||||
// value is constant and must be loaded into a register.
|
|
||||||
// First, create a tmp virtual register (TmpInstruction)
|
|
||||||
// to hold the constant.
|
|
||||||
// This will replace the constant operand in `minstr'.
|
|
||||||
TmpInstruction* tmpReg =
|
TmpInstruction* tmpReg =
|
||||||
new TmpInstruction(Instruction::UserOp1, opValue, NULL);
|
InsertCodeToLoadConstant((ConstPoolVal*) opValue,
|
||||||
vmInstr->getMachineInstrVec().addTempValue(tmpReg);
|
vmInstr, loadConstVec, target);
|
||||||
minstr->SetMachineOperand(op, opType, tmpReg);
|
minstr->SetMachineOperand(op, opType, tmpReg);
|
||||||
|
|
||||||
MachineInstr *minstr1, *minstr2;
|
|
||||||
minstr1 = CreateLoadConstInstr(target, vmInstr,
|
|
||||||
opValue, tmpReg, minstr2);
|
|
||||||
tmpReg->addMachineInstruction(minstr1);
|
|
||||||
|
|
||||||
loadConstVec[numNew++] = minstr1;
|
|
||||||
if (minstr2 != NULL)
|
|
||||||
loadConstVec[numNew++] = minstr2;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
minstr->SetMachineOperand(op, opType, immedValue);
|
minstr->SetMachineOperand(op, opType, immedValue);
|
||||||
@ -1220,6 +1235,39 @@ FixConstantOperands(const InstructionNode* vmInstrNode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Also, check for operands of the VM instruction that are implicit
|
||||||
|
// operands of the machine instruction. These include:
|
||||||
|
// -- arguments to a Call
|
||||||
|
// -- return value of a Return
|
||||||
|
//
|
||||||
|
// Any such operand that is a constant value needs to be fixed also.
|
||||||
|
// At least these instructions with implicit uses (viz., Call and Return)
|
||||||
|
// have no immediate fields, so the constant needs to be loaded into
|
||||||
|
// a register.
|
||||||
|
//
|
||||||
|
vector<Value*>& implUseVec = vmInstr->getMachineInstrVec().getImplicitUses();
|
||||||
|
if (implUseVec.size() > 0)
|
||||||
|
{
|
||||||
|
assert((vmInstr->getOpcode() == Instruction::Call ||
|
||||||
|
vmInstr->getOpcode() == Instruction::Ret)
|
||||||
|
&& "May need to check immediate fields for other instructions");
|
||||||
|
|
||||||
|
for (unsigned i=1, N=implUseVec.size(); i < N; ++i)
|
||||||
|
if (isa<ConstPoolVal>(implUseVec[i]))
|
||||||
|
{
|
||||||
|
TmpInstruction* tmpReg =
|
||||||
|
InsertCodeToLoadConstant((ConstPoolVal*) implUseVec[i],
|
||||||
|
vmInstr, loadConstVec, target);
|
||||||
|
implUseVec[i] = tmpReg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Finally, inserted the generated instructions in the vector
|
||||||
|
// to be returned.
|
||||||
|
//
|
||||||
|
unsigned numNew = loadConstVec.size();
|
||||||
if (numNew > 0)
|
if (numNew > 0)
|
||||||
{
|
{
|
||||||
// Insert the new instructions *before* the old ones by moving
|
// Insert the new instructions *before* the old ones by moving
|
||||||
@ -1376,7 +1424,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
|||||||
const Type* opType;
|
const Type* opType;
|
||||||
int nextRule;
|
int nextRule;
|
||||||
int forwardOperandNum = -1;
|
int forwardOperandNum = -1;
|
||||||
int64_t s0 = 0; // variables holding zero to avoid
|
int64_t s0=0, s8=8; // variables holding constants to avoid
|
||||||
uint64_t u0=0; // overloading ambiguities below
|
uint64_t u0=0; // overloading ambiguities below
|
||||||
|
|
||||||
mvec[0] = mvec[1] = mvec[2] = mvec[3] = NULL; // just for safety
|
mvec[0] = mvec[1] = mvec[2] = mvec[3] = NULL; // just for safety
|
||||||
@ -1420,7 +1468,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
|||||||
mvec[0] = new MachineInstr(RETURN);
|
mvec[0] = new MachineInstr(RETURN);
|
||||||
mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
|
mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
|
||||||
returnReg);
|
returnReg);
|
||||||
mvec[0]->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,s0);
|
mvec[0]->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,s8);
|
||||||
|
|
||||||
returnReg->addMachineInstruction(mvec[0]);
|
returnReg->addMachineInstruction(mvec[0]);
|
||||||
|
|
||||||
@ -2007,8 +2055,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
|||||||
// is available, replace this with a CALL instruction.
|
// is available, replace this with a CALL instruction.
|
||||||
// Mark both the indirection register and the return-address
|
// Mark both the indirection register and the return-address
|
||||||
// register as hidden virtual registers.
|
// register as hidden virtual registers.
|
||||||
// Also, mark the operands of the Call as implicit operands
|
// Also, mark the operands of the Call and the return value
|
||||||
// of the machine instruction.
|
// as implicit operands of the machine instruction.
|
||||||
{
|
{
|
||||||
CallInst *callInstr = cast<CallInst>(subtreeRoot->getInstruction());
|
CallInst *callInstr = cast<CallInst>(subtreeRoot->getInstruction());
|
||||||
Method* callee = callInstr->getCalledMethod();
|
Method* callee = callInstr->getCalledMethod();
|
||||||
@ -2019,12 +2067,19 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
|||||||
callInstr, NULL);
|
callInstr, NULL);
|
||||||
|
|
||||||
// Note temporary values and implicit uses in mvec
|
// Note temporary values and implicit uses in mvec
|
||||||
|
//
|
||||||
|
// WARNING: Operands 0..N-1 must go in slots 0..N-1 of implicitUses.
|
||||||
|
// The result value must go in slot N. This is assumed
|
||||||
|
// in register allocation.
|
||||||
|
//
|
||||||
callInstr->getMachineInstrVec().addTempValue(jmpAddrReg);
|
callInstr->getMachineInstrVec().addTempValue(jmpAddrReg);
|
||||||
callInstr->getMachineInstrVec().addTempValue(retAddrReg);
|
callInstr->getMachineInstrVec().addTempValue(retAddrReg);
|
||||||
for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
|
for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
|
||||||
if (callInstr->getOperand(i) != callee)
|
if (callInstr->getOperand(i) != callee)
|
||||||
callInstr->getMachineInstrVec().addImplicitUse(
|
callInstr->getMachineInstrVec().addImplicitUse(
|
||||||
callInstr->getOperand(i));
|
callInstr->getOperand(i));
|
||||||
|
if (callInstr->getCalledMethod()->getReturnType() == Type::VoidTy)
|
||||||
|
callInstr->getMachineInstrVec().addImplicitUse(callInstr);
|
||||||
|
|
||||||
// Generate the machine instruction and its operands
|
// Generate the machine instruction and its operands
|
||||||
mvec[0] = new MachineInstr(JMPL);
|
mvec[0] = new MachineInstr(JMPL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user