mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-29 14:40:39 +00:00
Record implicitRefs for each machine instruction instead of
each VM instruction. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@725 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8d0ffa553f
commit
a995e6086d
@ -234,13 +234,23 @@ MachineOperand::InitializeReg(unsigned int _regNum)
|
||||
// PREDICT-NOT-TAKEN: if 1: predict branch not taken.
|
||||
// Instead of creating 4 different opcodes for BNZ, we create a single
|
||||
// opcode and set bits in opCodeMask for each of these flags.
|
||||
//
|
||||
// There are 2 kinds of operands:
|
||||
//
|
||||
// (1) Explicit operands of the machine instruction in vector operands[]
|
||||
//
|
||||
// (2) "Implicit operands" are values implicitly used or defined by the
|
||||
// machine instruction, such as arguments to a CALL, return value of
|
||||
// a CALL (if any), and return value of a RETURN.
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class MachineInstr : public NonCopyable {
|
||||
private:
|
||||
MachineOpCode opCode;
|
||||
OpCodeMask opCodeMask; // extra bits for variants of an opcode
|
||||
MachineOpCode opCode;
|
||||
OpCodeMask opCodeMask; // extra bits for variants of an opcode
|
||||
vector<MachineOperand> operands;
|
||||
vector<Value*> implicitRefs; // values implicitly referenced by this
|
||||
vector<bool> implicitIsDef; // machine instruction (eg, call args)
|
||||
|
||||
public:
|
||||
typedef ValOpIterator<const MachineInstr, const Value> val_op_const_iterator;
|
||||
@ -254,20 +264,33 @@ public:
|
||||
OpCodeMask _opCodeMask = 0x0);
|
||||
inline ~MachineInstr () {}
|
||||
|
||||
const MachineOpCode getOpCode () const;
|
||||
const MachineOpCode getOpCode () const { return opCode; }
|
||||
|
||||
unsigned int getNumOperands () const;
|
||||
//
|
||||
// Information about explicit operands of the instruction
|
||||
//
|
||||
unsigned int getNumOperands () const { return operands.size(); }
|
||||
|
||||
bool operandIsDefined(unsigned int i) const;
|
||||
|
||||
const MachineOperand& getOperand (unsigned int i) const;
|
||||
MachineOperand& getOperand (unsigned int i);
|
||||
|
||||
bool operandIsDefined(unsigned int i) const;
|
||||
//
|
||||
// Information about implicit operands of the instruction
|
||||
//
|
||||
unsigned int getNumImplicitRefs() const{return implicitRefs.size();}
|
||||
|
||||
bool implicitRefIsDefined(unsigned int i) const;
|
||||
|
||||
const Value* getImplicitRef (unsigned int i) const;
|
||||
Value* getImplicitRef (unsigned int i);
|
||||
|
||||
//
|
||||
// Debugging support
|
||||
//
|
||||
void dump (unsigned int indent = 0) const;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
friend ostream& operator<<(ostream& os, const MachineInstr& minstr);
|
||||
@ -285,19 +308,15 @@ public:
|
||||
void SetMachineOperand(unsigned int i,
|
||||
unsigned int regNum,
|
||||
bool isDef=false);
|
||||
|
||||
void addImplicitRef (Value* val,
|
||||
bool isDef=false);
|
||||
|
||||
void setImplicitRef (unsigned int i,
|
||||
Value* val,
|
||||
bool isDef=false);
|
||||
};
|
||||
|
||||
inline const MachineOpCode
|
||||
MachineInstr::getOpCode() const
|
||||
{
|
||||
return opCode;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
MachineInstr::getNumOperands() const
|
||||
{
|
||||
return operands.size();
|
||||
}
|
||||
|
||||
inline MachineOperand&
|
||||
MachineInstr::getOperand(unsigned int i)
|
||||
@ -319,6 +338,45 @@ MachineInstr::operandIsDefined(unsigned int i) const
|
||||
return getOperand(i).opIsDef();
|
||||
}
|
||||
|
||||
inline bool
|
||||
MachineInstr::implicitRefIsDefined(unsigned int i) const
|
||||
{
|
||||
assert(i < implicitIsDef.size() && "operand out of range!");
|
||||
return implicitIsDef[i];
|
||||
}
|
||||
|
||||
inline const Value*
|
||||
MachineInstr::getImplicitRef(unsigned int i) const
|
||||
{
|
||||
assert(i < implicitRefs.size() && "getImplicitRef() out of range!");
|
||||
return implicitRefs[i];
|
||||
}
|
||||
|
||||
inline Value*
|
||||
MachineInstr::getImplicitRef(unsigned int i)
|
||||
{
|
||||
assert(i < implicitRefs.size() && "getImplicitRef() out of range!");
|
||||
return implicitRefs[i];
|
||||
}
|
||||
|
||||
inline void
|
||||
MachineInstr::addImplicitRef(Value* val,
|
||||
bool isDef)
|
||||
{
|
||||
implicitRefs.push_back(val);
|
||||
implicitIsDef.push_back(isDef);
|
||||
}
|
||||
|
||||
inline void
|
||||
MachineInstr::setImplicitRef(unsigned int i,
|
||||
Value* val,
|
||||
bool isDef)
|
||||
{
|
||||
assert(i < implicitRefs.size() && "setImplicitRef() out of range!");
|
||||
implicitRefs[i] = val;
|
||||
implicitIsDef[i] = isDef;
|
||||
}
|
||||
|
||||
|
||||
template<class _MI, class _V>
|
||||
class ValOpIterator : public std::forward_iterator<_V, ptrdiff_t> {
|
||||
@ -364,16 +422,13 @@ public:
|
||||
// Purpose:
|
||||
// Representation of the sequence of machine instructions created
|
||||
// for a single VM instruction. Additionally records information
|
||||
// about hidden and implicit values used by the machine instructions:
|
||||
// about hidden values used by the machine instructions:
|
||||
//
|
||||
// (1) "Temporary values" are intermediate values used in the machine
|
||||
// instruction sequence, but not in the VM instruction
|
||||
// Note that such values should be treated as pure SSA values with
|
||||
// no interpretation of their operands (i.e., as a TmpInstruction
|
||||
// object which actually represents such a value).
|
||||
//
|
||||
// (2) "Implicit uses" are values used in the VM instruction but not in
|
||||
// the machine instruction sequence
|
||||
// "Temporary values" are intermediate values used in the machine
|
||||
// instruction sequence, but not in the VM instruction
|
||||
// Note that such values should be treated as pure SSA values with
|
||||
// no interpretation of their operands (i.e., as a TmpInstruction
|
||||
// object which actually represents such a value).
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@ -381,7 +436,6 @@ class MachineCodeForVMInstr: public vector<MachineInstr*>
|
||||
{
|
||||
private:
|
||||
vector<Value*> tempVec; // used by m/c instr but not VM instr
|
||||
vector<Value*> implicitUses; // used by VM instr but not m/c instr
|
||||
|
||||
public:
|
||||
/*ctor*/ MachineCodeForVMInstr () {}
|
||||
@ -390,11 +444,7 @@ public:
|
||||
const vector<Value*>& getTempValues () const { return tempVec; }
|
||||
vector<Value*>& getTempValues () { return tempVec; }
|
||||
|
||||
const vector<Value*>& getImplicitUses() const { return implicitUses; }
|
||||
vector<Value*>& getImplicitUses() { return implicitUses; }
|
||||
|
||||
void addTempValue (Value* val) { tempVec.push_back(val); }
|
||||
void addImplicitUse(Value* val) { implicitUses.push_back(val);}
|
||||
|
||||
// dropAllReferences() - This function drops all references within
|
||||
// temporary (hidden) instructions created in implementing the original
|
||||
|
@ -1233,33 +1233,24 @@ FixConstantOperands(const InstructionNode* vmInstrNode,
|
||||
minstr->SetMachineOperand(op, opType, immedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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]))
|
||||
//
|
||||
// Also, check for implicit operands used (not those defined) by 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.
|
||||
// The current instructions with implicit refs (viz., Call and Return)
|
||||
// have no immediate fields, so the constant always needs to be loaded
|
||||
// into a register.
|
||||
//
|
||||
for (unsigned i=1, N=minstr->getNumImplicitRefs(); i < N; ++i)
|
||||
if (isa<ConstPoolVal>(minstr->getImplicitRef(i)))
|
||||
{
|
||||
TmpInstruction* tmpReg =
|
||||
InsertCodeToLoadConstant((ConstPoolVal*) implUseVec[i],
|
||||
vmInstr, loadConstVec, target);
|
||||
implUseVec[i] = tmpReg;
|
||||
TmpInstruction* tmpReg = InsertCodeToLoadConstant((ConstPoolVal*)
|
||||
minstr->getImplicitRef(i),
|
||||
vmInstr, loadConstVec, target);
|
||||
minstr->setImplicitRef(i, tmpReg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1452,7 +1443,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||
// NOTE: Prepass of register allocation is responsible
|
||||
// for moving return value to appropriate register.
|
||||
// Mark the return-address register as a hidden virtual reg.
|
||||
// Mark the return value register as an implicit use.
|
||||
// Mark the return value register as an implicit ref of
|
||||
// the machine instruction.
|
||||
{
|
||||
ReturnInst* returnInstr = (ReturnInst*) subtreeRoot->getInstruction();
|
||||
assert(returnInstr->getOpcode() == Instruction::Ret);
|
||||
@ -1461,15 +1453,14 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||
returnInstr, NULL);
|
||||
returnInstr->getMachineInstrVec().addTempValue(returnReg);
|
||||
|
||||
if (returnInstr->getReturnValue() != NULL)
|
||||
returnInstr->getMachineInstrVec().addImplicitUse(
|
||||
returnInstr->getReturnValue());
|
||||
|
||||
mvec[0] = new MachineInstr(RETURN);
|
||||
mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
|
||||
returnReg);
|
||||
mvec[0]->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,s8);
|
||||
|
||||
if (returnInstr->getReturnValue() != NULL)
|
||||
mvec[0]->addImplicitRef(returnInstr->getReturnValue());
|
||||
|
||||
returnReg->addMachineInstruction(mvec[0]);
|
||||
|
||||
mvec[numInstr++] = new MachineInstr(NOP); // delay slot
|
||||
@ -2055,8 +2046,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||
// is available, replace this with a CALL instruction.
|
||||
// Mark both the indirection register and the return-address
|
||||
// register as hidden virtual registers.
|
||||
// Also, mark the operands of the Call and the return value
|
||||
// as implicit operands of the machine instruction.
|
||||
// Also, mark the operands of the Call and return value (if
|
||||
// any) as implicit operands of the CALL machine instruction.
|
||||
{
|
||||
CallInst *callInstr = cast<CallInst>(subtreeRoot->getInstruction());
|
||||
Method* callee = callInstr->getCalledMethod();
|
||||
@ -2066,7 +2057,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||
Instruction* retAddrReg = new TmpInstruction(Instruction::UserOp1,
|
||||
callInstr, NULL);
|
||||
|
||||
// Note temporary values and implicit uses in mvec
|
||||
// Note temporary values in the machineInstrVec for the VM instr.
|
||||
//
|
||||
// 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
|
||||
@ -2074,12 +2065,6 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||
//
|
||||
callInstr->getMachineInstrVec().addTempValue(jmpAddrReg);
|
||||
callInstr->getMachineInstrVec().addTempValue(retAddrReg);
|
||||
for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
|
||||
if (callInstr->getOperand(i) != callee)
|
||||
callInstr->getMachineInstrVec().addImplicitUse(
|
||||
callInstr->getOperand(i));
|
||||
if (callInstr->getCalledMethod()->getReturnType() == Type::VoidTy)
|
||||
callInstr->getMachineInstrVec().addImplicitUse(callInstr);
|
||||
|
||||
// Generate the machine instruction and its operands
|
||||
mvec[0] = new MachineInstr(JMPL);
|
||||
@ -2090,6 +2075,14 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||
mvec[0]->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
|
||||
retAddrReg);
|
||||
|
||||
// Add the call operands and return value as implicit refs
|
||||
for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
|
||||
if (callInstr->getOperand(i) != callee)
|
||||
mvec[0]->addImplicitRef(callInstr->getOperand(i));
|
||||
|
||||
if (callInstr->getCalledMethod()->getReturnType() != Type::VoidTy)
|
||||
mvec[0]->addImplicitRef(callInstr, /*isDef*/ true);
|
||||
|
||||
// NOTE: jmpAddrReg will be loaded by a different instruction generated
|
||||
// by the final code generator, so we just mark the CALL instruction
|
||||
// as computing that value.
|
||||
|
Loading…
Reference in New Issue
Block a user