aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/SparcV9/SparcV9InstrSelection.cpp1088
1 files changed, 607 insertions, 481 deletions
diff --git a/lib/Target/SparcV9/SparcV9InstrSelection.cpp b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
index 059935981f..e3764ece0c 100644
--- a/lib/Target/SparcV9/SparcV9InstrSelection.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
@@ -12,6 +12,7 @@
#include "SparcInternals.h"
#include "SparcInstrSelectionSupport.h"
+#include "SparcRegClassInfo.h"
#include "llvm/CodeGen/InstrSelectionSupport.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/InstrForest.h"
@@ -32,10 +33,10 @@ using std::vector;
//************************* Forward Declarations ***************************/
-static void SetMemOperands_Internal (MachineInstr* minstr,
+static void SetMemOperands_Internal (vector<MachineInstr*>& mvec,
+ vector<MachineInstr*>::iterator mvecI,
const InstructionNode* vmInstrNode,
Value* ptrVal,
- Value* arrayOffsetVal,
const std::vector<Value*>& idxVec,
const TargetMachine& target);
@@ -259,12 +260,12 @@ ChooseConvertToFloatInstr(const InstructionNode* instrNode,
break;
case ToDoubleTy:
- // Use FXTOD for all integer-to-double conversions. This has to be
- // consistent with the code in CreateCodeToCopyIntToFloat() since
- // that will be used to load the integer into an FP register.
- //
- if (opType == Type::SByteTy || opType == Type::ShortTy ||
- opType == Type::IntTy || opType == Type::LongTy)
+ // This is usually used in conjunction with CreateCodeToCopyIntToFloat().
+ // Both functions should treat the integer as a 32-bit value for types
+ // of 4 bytes or less, and as a 64-bit value otherwise.
+ if (opType == Type::SByteTy || opType == Type::ShortTy || opType == Type::IntTy)
+ opCode = FITOD;
+ else if (opType == Type::LongTy)
opCode = FXTOD;
else if (opType == Type::FloatTy)
opCode = FSTOD;
@@ -356,10 +357,10 @@ CreateMovFloatInstruction(const InstructionNode* instrNode,
{
MachineInstr* minstr = new MachineInstr((resultType == Type::FloatTy)
? FMOVS : FMOVD);
- minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
- instrNode->leftChild()->getValue());
- minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
- instrNode->getValue());
+ minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
+ instrNode->leftChild()->getValue());
+ minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
+ instrNode->getValue());
return minstr;
}
@@ -490,46 +491,38 @@ ChooseMulInstructionByType(const Type* resultType)
}
-static inline MachineOpCode
-ChooseMulInstruction(const InstructionNode* instrNode,
- bool checkCasts)
-{
- if (checkCasts && BothFloatToDouble(instrNode))
- return FSMULD;
-
- // else use the regular multiply instructions
- return ChooseMulInstructionByType(instrNode->getInstruction()->getType());
-}
-
static inline MachineInstr*
-CreateIntNegInstruction(TargetMachine& target,
+CreateIntNegInstruction(const TargetMachine& target,
Value* vreg)
{
MachineInstr* minstr = new MachineInstr(SUB);
- minstr->SetMachineOperand(0, target.getRegInfo().getZeroRegNum());
- minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, vreg);
- minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, vreg);
+ minstr->SetMachineOperandReg(0, target.getRegInfo().getZeroRegNum());
+ minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, vreg);
+ minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, vreg);
return minstr;
}
-static inline MachineInstr*
-CreateMulConstInstruction(TargetMachine &target,
- const InstructionNode* instrNode,
- MachineInstr*& getMinstr2)
+// Does not create any instructions if we cannot exploit constant to
+// create a cheaper instruction
+static inline void
+CreateMulConstInstruction(const TargetMachine &target,
+ Value* lval, Value* rval, Value* destVal,
+ vector<MachineInstr*>& mvec)
{
- MachineInstr* minstr = NULL; // return NULL if we cannot exploit constant
- getMinstr2 = NULL; // to create a cheaper instruction
-
- Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
- assert(isa<Constant>(constOp));
+ MachineInstr* minstr1 = NULL;
+ MachineInstr* minstr2 = NULL;
+
+ Value* constOp = rval;
+ if (! isa<Constant>(constOp))
+ return;
// Cases worth optimizing are:
// (1) Multiply by 0 or 1 for any type: replace with copy (ADD or FMOV)
// (2) Multiply by 2^x for integer types: replace with Shift
//
- const Type* resultType = instrNode->getInstruction()->getType();
+ const Type* resultType = destVal->getType();
if (resultType->isIntegral() || resultType->isPointerType())
{
@@ -547,30 +540,29 @@ CreateMulConstInstruction(TargetMachine &target,
if (C == 0 || C == 1)
{
- minstr = new MachineInstr(ADD);
+ minstr1 = new MachineInstr(ADD);
if (C == 0)
- minstr->SetMachineOperand(0,
+ minstr1->SetMachineOperandReg(0,
target.getRegInfo().getZeroRegNum());
else
- minstr->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
- instrNode->leftChild()->getValue());
- minstr->SetMachineOperand(1,target.getRegInfo().getZeroRegNum());
+ minstr1->SetMachineOperandVal(0,MachineOperand::MO_VirtualRegister,
+ lval);
+ minstr1->SetMachineOperandReg(1,target.getRegInfo().getZeroRegNum());
}
else if (IsPowerOf2(C, pow))
{
- minstr = new MachineInstr((resultType == Type::LongTy)
+ minstr1 = new MachineInstr((resultType == Type::LongTy)
? SLLX : SLL);
- minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
- instrNode->leftChild()->getValue());
- minstr->SetMachineOperand(1, MachineOperand::MO_UnextendedImmed,
- pow);
+ minstr1->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
+ lval);
+ minstr1->SetMachineOperandConst(1, MachineOperand::MO_UnextendedImmed,
+ pow);
}
- if (minstr && needNeg)
+ if (minstr1 && needNeg)
{ // insert <reg = SUB 0, reg> after the instr to flip the sign
- getMinstr2 = CreateIntNegInstruction(target,
- instrNode->getValue());
+ minstr2 = CreateIntNegInstruction(target, destVal);
}
}
}
@@ -588,19 +580,47 @@ CreateMulConstInstruction(TargetMachine &target,
? (resultType == Type::FloatTy? FNEGS : FNEGD)
: (resultType == Type::FloatTy? FMOVS : FMOVD);
- minstr = new MachineInstr(opCode);
- minstr->SetMachineOperand(0,
- MachineOperand::MO_VirtualRegister,
- instrNode->leftChild()->getValue());
+ minstr1 = new MachineInstr(opCode);
+ minstr1->SetMachineOperandVal(0,
+ MachineOperand::MO_VirtualRegister,
+ lval);
}
}
}
- if (minstr != NULL)
- minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
- instrNode->getValue());
+ if (minstr1 != NULL)
+ minstr1->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
+ destVal);
- return minstr;
+ if (minstr1)
+ mvec.push_back(minstr1);
+ if (minstr2)
+ mvec.push_back(minstr2);
+}
+
+
+// Return NULL if we cannot exploit constant to create a cheaper instruction
+static inline void
+CreateMulInstruction(const TargetMachine &target,
+ Value* lval, Value* rval, Value* destVal,
+ vector<MachineInstr*>& mvec,
+ MachineOpCode forceMulOp = INVALID_MACHINE_OPCODE)
+{
+ unsigned int L = mvec.size();
+ CreateMulConstInstruction(target, lval, rval, destVal, mvec);
+ if (mvec.size() == L)
+ { // no instructions were added so create MUL reg, reg, reg.
+ // Use FSMULD if both operands are actually floats cast to doubles.
+ // Otherwise, use the default opcode for the appropriate type.
+ MachineOpCode mulOp = ((forceMulOp != INVALID_MACHINE_OPCODE)
+ ? forceMulOp
+ : ChooseMulInstructionByType(destVal->getType()));
+ MachineInstr* M = new MachineInstr(mulOp);
+ M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, lval);
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, rval);
+ M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, destVal);
+ mvec.push_back(M);
+ }
}
@@ -630,16 +650,18 @@ ChooseDivInstruction(TargetMachine &target,
}
-static inline MachineInstr*
+// Return NULL if we cannot exploit constant to create a cheaper instruction
+static inline void
CreateDivConstInstruction(TargetMachine &target,
const InstructionNode* instrNode,
- MachineInstr*& getMinstr2)
+ vector<MachineInstr*>& mvec)
{
- MachineInstr* minstr = NULL;
- getMinstr2 = NULL;
+ MachineInstr* minstr1 = NULL;
+ MachineInstr* minstr2 = NULL;
Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
- assert(isa<Constant>(constOp));
+ if (! isa<Constant>(constOp))
+ return;
// Cases worth optimizing are:
// (1) Divide by 1 for any type: replace with copy (ADD or FMOV)
@@ -663,26 +685,26 @@ CreateDivConstInstruction(TargetMachine &target,
if (C == 1)
{
- minstr = new MachineInstr(ADD);
- minstr->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
+ minstr1 = new MachineInstr(ADD);
+ minstr1->SetMachineOperandVal(0,MachineOperand::MO_VirtualRegister,
instrNode->leftChild()->getValue());
- minstr->SetMachineOperand(1,target.getRegInfo().getZeroRegNum());
+ minstr1->SetMachineOperandReg(1,target.getRegInfo().getZeroRegNum());
}
else if (IsPowerOf2(C, pow))
{
MachineOpCode opCode= ((resultType->isSigned())
? (resultType==Type::LongTy)? SRAX : SRA
: (resultType==Type::LongTy)? SRLX : SRL);
- minstr = new MachineInstr(opCode);
- minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ minstr1 = new MachineInstr(opCode);
+ minstr1->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
instrNode->leftChild()->getValue());
- minstr->SetMachineOperand(1, MachineOperand::MO_UnextendedImmed,
+ minstr1->SetMachineOperandConst(1, MachineOperand::MO_UnextendedImmed,
pow);
}
- if (minstr && needNeg)
+ if (minstr1 && needNeg)
{ // insert <reg = SUB 0, reg> after the instr to flip the sign
- getMinstr2 = CreateIntNegInstruction(target,
+ minstr2 = CreateIntNegInstruction(target,
instrNode->getValue());
}
}
@@ -701,21 +723,116 @@ CreateDivConstInstruction(TargetMachine &target,
? (resultType == Type::FloatTy? FNEGS : FNEGD)
: (resultType == Type::FloatTy? FMOVS : FMOVD);
- minstr = new MachineInstr(opCode);
- minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ minstr1 = new MachineInstr(opCode);
+ minstr1->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
instrNode->leftChild()->getValue());
}
}
}
- if (minstr != NULL)
- minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
- instrNode->getValue());
+ if (minstr1 != NULL)
+ minstr1->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
+ instrNode->getValue());
- return minstr;
+ if (minstr1)
+ mvec.push_back(minstr1);
+ if (minstr2)
+ mvec.push_back(minstr2);
+}
+
+
+static void
+CreateCodeForVariableSizeAlloca(const TargetMachine& target,
+ Instruction* result,
+ unsigned int tsize,
+ Value* numElementsVal,
+ vector<MachineInstr*>& getMvec)
+{
+ MachineInstr* M;
+
+ // Create a Value to hold the (constant) element size
+ Value* tsizeVal = ConstantSInt::get(Type::IntTy, tsize);
+
+ // Get the constant offset from SP for dynamically allocated storage
+ // and create a temporary Value to hold it.
+ assert(result && result->getParent() && "Result value is not part of a method?");
+ Method* method = result->getParent()->getParent();
+ MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(method);
+ bool growUp;
+ ConstantSInt* dynamicAreaOffset =
+ ConstantSInt::get(Type::IntTy,
+ target.getFrameInfo().getDynamicAreaOffset(mcInfo,growUp));
+ assert(! growUp && "Has SPARC v9 stack frame convention changed?");
+
+ // Create a temporary value to hold the result of MUL
+ TmpInstruction* tmpProd = new TmpInstruction(numElementsVal, tsizeVal);
+ MachineCodeForInstruction::get(result).addTemp(tmpProd);
+
+ // Instruction 1: mul numElements, typeSize -> tmpProd
+ M = new MachineInstr(MULX);
+ M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, numElementsVal);
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tsizeVal);
+ M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, tmpProd);
+ getMvec.push_back(M);
+
+ // Instruction 2: sub %sp, tmpProd -> %sp
+ M = new MachineInstr(SUB);
+ M->SetMachineOperandReg(0, target.getRegInfo().getStackPointer());
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpProd);
+ M->SetMachineOperandReg(2, target.getRegInfo().getStackPointer());
+ getMvec.push_back(M);
+
+ // Instruction 3: add %sp, frameSizeBelowDynamicArea -> result
+ M = new MachineInstr(ADD);
+ M->SetMachineOperandReg(0, target.getRegInfo().getStackPointer());
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, dynamicAreaOffset);
+ M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, result);
+ getMvec.push_back(M);
+}
+
+
+static void
+CreateCodeForFixedSizeAlloca(const TargetMachine& target,
+ Instruction* result,
+ unsigned int tsize,
+ unsigned int numElements,
+ vector<MachineInstr*>& getMvec)
+{
+ assert(result && result->getParent() && "Result value is not part of a method?");
+ Method* method = result->getParent()->getParent();
+ MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(method);
+
+ // Check if the offset would small enough to use as an immediate in load/stores
+ // (check LDX because all load/stores have the same-size immediate field).
+ // If not, put the variable in the dynamically sized area of the frame.
+ int offsetFromFP = mcInfo.computeOffsetforLocalVar(target, result,
+ tsize * numElements);
+ if (! target.getInstrInfo().constantFitsInImmedField(LDX, offsetFromFP))
+ {
+ CreateCodeForVariableSizeAlloca(target, result, tsize,
+ ConstantSInt::get(Type::IntTy,numElements),
+ getMvec);
+ return;
+ }
+
+ // else offset fits in immediate field so go ahead and allocate it.
+ offsetFromFP = mcInfo.allocateLocalVar(target, result, tsize * numElements);
+
+ // Create a temporary Value to hold the constant offset.
+ // This is needed because it may not fit in the immediate field.
+ ConstantSInt* offsetVal = ConstantSInt::get(Type::IntTy, offsetFromFP);
+
+ // Instruction 1: add %fp, offsetFromFP -> result
+ MachineInstr* M = new MachineInstr(ADD);
+ M->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, offsetVal);
+ M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, result);
+
+ getMvec.push_back(M);
}
+
//------------------------------------------------------------------------
// Function SetOperandsForMemInstr
//
@@ -733,7 +850,8 @@ CreateDivConstInstruction(TargetMachine &target,
//------------------------------------------------------------------------
static void
-SetOperandsForMemInstr(MachineInstr* minstr,
+SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
+ vector<MachineInstr*>::iterator mvecI,
const InstructionNode* vmInstrNode,
const TargetMachine& target)
{
@@ -744,8 +862,7 @@ SetOperandsForMemInstr(MachineInstr* minstr,
// and then call the common function SetMemOperands_Internal().
//
vector<Value*> idxVec;
- Value* ptrVal;
- Value* arrayOffsetVal = NULL;
+ Value* ptrVal = memInst->getPointerOperand();
// Test if a GetElemPtr instruction is being folded into this mem instrn.
// If so, it will be in the left child for Load and GetElemPtr,
@@ -755,49 +872,39 @@ SetOperandsForMemInstr(MachineInstr* minstr,
? vmInstrNode->rightChild()
: vmInstrNode->leftChild());
- if (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
- ptrChild->getOpLabel() == GetElemPtrIdx)
+ // We can only fold a chain of GetElemPtr instructions for structure references
+ //
+ if (isa<StructType>(cast<PointerType>(ptrVal->getType())->getElementType())
+ && (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
+ ptrChild->getOpLabel() == GetElemPtrIdx))
{
// There is a GetElemPtr instruction and there may be a chain of
// more than one. Use the pointer value of the last one in the chain.
// Fold the index vectors from the entire chain and from the mem
// instruction into one single index vector.
- // Finally, we never fold for an array instruction so make that NULL.
-
- ptrVal = FoldGetElemChain((InstructionNode*) ptrChild, idxVec);
- idxVec.insert(idxVec.end(), memInst->idx_begin(), memInst->idx_end());
- assert(!((PointerType*)ptrVal->getType())->getElementType()->isArrayType()
- && "GetElemPtr cannot be folded into array refs in selection");
- }
- else
- {
- // There is no GetElemPtr instruction.
- // Use the pointer value and the index vector from the Mem instruction.
- // If it is an array reference, check that it has been lowered to
- // at most a single offset, then get the array offset value.
//
- ptrVal = memInst->getPointerOperand();
+ ptrVal = FoldGetElemChain((InstructionNode*) ptrChild, idxVec);
- const Type* opType = cast<PointerType>(ptrVal->getType())->getElementType();
- if (opType->isArrayType())
- {
- assert((memInst->getNumOperands()
- == (unsigned) 1 + memInst->getFirstIndexOperandNumber())
- && "Array refs must be lowered before Instruction Selection");
- arrayOffsetVal = * memInst->idx_begin();
- }
+ assert (! cast<PointerType>(ptrVal->getType())->getElementType()->isArrayType()
+ && "GetElemPtr cannot be folded into array refs in selection");
}
- SetMemOperands_Internal(minstr, vmInstrNode, ptrVal, arrayOffsetVal,
- idxVec, target);
+ // Append the index vector of this instruction (may be none) to the indexes
+ // folded in previous getElementPtr's (may be none)
+ idxVec.insert(idxVec.end(), memInst->idx_begin(), memInst->idx_end());
+
+ SetMemOperands_Internal(mvec, mvecI, vmInstrNode, ptrVal, idxVec, target);
}
+// Generate the correct operands (and additional instructions if needed)
+// for the given pointer and given index vector.
+//
static void
-SetMemOperands_Internal(MachineInstr* minstr,
+SetMemOperands_Internal(vector<MachineInstr*>& mvec,
+ vector<MachineInstr*>::iterator mvecI,
const InstructionNode* vmInstrNode,
Value* ptrVal,
- Value* arrayOffsetVal,
const vector<Value*>& idxVec,
const TargetMachine& target)
{
@@ -808,51 +915,70 @@ SetMemOperands_Internal(MachineInstr* minstr,
Value* valueForRegOffset = NULL;
MachineOperand::MachineOperandType offsetOpType =MachineOperand::MO_VirtualRegister;
- // Check if there is an index vector and if so, if it translates to
- // a small enough constant to fit in the immediate-offset field.
+ // Check if there is an index vector and if so, compute the
+ // right offset for structures and for arrays
//
if (idxVec.size() > 0)
{
- bool isConstantOffset = false;
unsigned offset = 0;
- const PointerType* ptrType = (PointerType*) ptrVal->getType();
+ const PointerType* ptrType = cast<PointerType>(ptrVal->getType());
if (ptrType->getElementType()->isStructType())
{
- // the offset is always constant for structs
- isConstantOffset = true;
-
- // Compute the offset value using the index vector
- offset = target.DataLayout.getIndexedOffset(ptrType, idxVec);
+ // Compute the offset value using the index vector,
+ // and create a virtual register for it.
+ unsigned offset = target.DataLayout.getIndexedOffset(ptrType,idxVec);
+ valueForRegOffset = ConstantSInt::get(Type::IntTy, offset);
}
else
{
- // It must be an array ref. Check if the offset is a constant,
- // and that the indexing has been lowered to a single offset.
- //
- assert(isa<SequentialType>(ptrType->getElementType()));
- assert(arrayOffsetVal != NULL
- && "Expect to be given Value* for array offsets");
+ // It must be an array ref. Check that the indexing has been
+ // lowered to a single offset.
+ assert((memInst->getNumOperands()
+ == (unsigned) 1 + memInst->getFirstIndexOperandNumber())
+ && "Array refs must be lowered before Instruction Selection");
- if (Constant *CPV = dyn_cast<Constant>(arrayOffsetVal))
- {
- isConstantOffset = true; // always constant for structs
- assert(arrayOffsetVal->getType()->isIntegral());
- offset = (CPV->getType()->isSigned()
- ? cast<ConstantSInt>(CPV)->getValue()
- : (int64_t) cast<ConstantUInt>(CPV)->getValue());
- }
- else
+ Value* arrayOffsetVal = * memInst->idx_begin();
+
+ // Generate a MUL instruction to compute address from index
+ // The call to getTypeSize() will fail if size is not constant
+ vector<MachineInstr*> mulVec;
+ Instruction* addr = new TmpInstruction(Type::UIntTy, memInst);
+ MachineCodeForInstruction::get(memInst).addTemp(addr);
+ unsigned int eltSize =
+ target.DataLayout.getTypeSize(ptrType->getElementType());
+ assert(eltSize > 0 && "Invalid or non-constant array element size");
+ ConstantUInt* eltVal = ConstantUInt::get(Type::UIntTy, eltSize);
+
+ CreateMulInstruction(target,
+ arrayOffsetVal, /* lval, not likely constant */
+ eltVal, /* rval, likely constant */
+ addr, /* result*/
+ mulVec, INVALID_MACHINE_OPCODE);
+ assert(mulVec.size() > 0 && "No multiply instruction created?");
+ for (vector<MachineInstr*>::const_iterator I = mulVec.begin();
+ I != mulVec.end(); ++I)
{
- valueForRegOffset = arrayOffsetVal;
+ mvecI = mvec.insert(mvecI, *I); // get ptr to inserted value
+ ++mvecI; // get ptr to mem. instr.
}
- }
-
- if (isConstantOffset)
- {
- // create a virtual register for the constant
- valueForRegOffset = ConstantSInt::get(Type::IntTy, offset);
+
+ valueForRegOffset = addr;
+
+ // Check if the offset is a constant,
+ // if (Constant *CPV = dyn_cast<Constant>(arrayOffsetVal))
+ // {
+ // isConstantOffset = true; // always constant for structs
+ // assert(arrayOffsetVal->getType()->isIntegral());
+ // offset = (CPV->getType()->isSigned()
+ // ? cast<ConstantSInt>(CPV)->getValue()
+ // : (int64_t) cast<ConstantUInt>(CPV)->getValue());
+ // }
+ // else
+ // {
+ // valueForRegOffset = arrayOffsetVal;
+ // }
}
}
else
@@ -864,7 +990,8 @@ SetMemOperands_Internal(MachineInstr* minstr,
// Operand 0 is value for STORE, ptr for LOAD or GET_ELEMENT_PTR
// It is the left child in the instruction tree in all cases.
Value* leftVal = vmInstrNode->leftChild()->getValue();
- minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, leftVal);
+ (*mvecI)->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
+ leftVal);
// Operand 1 is ptr for STORE, offset for LOAD or GET_ELEMENT_PTR
// Operand 2 is offset for STORE, result reg for LOAD or GET_ELEMENT_PTR
@@ -873,16 +1000,19 @@ SetMemOperands_Internal(MachineInstr* minstr,
if (offsetOpType == MachineOperand::MO_VirtualRegister)
{
assert(valueForRegOffset != NULL);
- minstr->SetMachineOperand(offsetOpNum, offsetOpType, valueForRegOffset);
+ (*mvecI)->SetMachineOperandVal(offsetOpNum, offsetOpType,
+ valueForRegOffset);
}
else
- minstr->SetMachineOperand(offsetOpNum, offsetOpType, smallConstOffset);
+ (*mvecI)->SetMachineOperandConst(offsetOpNum, offsetOpType,
+ smallConstOffset);
if (memInst->getOpcode() == Instruction::Store)
- minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, ptrVal);
+ (*mvecI)->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
+ ptrVal);
else
- minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
- vmInstrNode->getValue());
+ (*mvecI)->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
+ vmInstrNode->getValue());
}
@@ -890,6 +1020,9 @@ SetMemOperands_Internal(MachineInstr* minstr,
// Substitute operand `operandNum' of the instruction in node `treeNode'
// in place of the use(s) of that instruction in node `parent'.
// Check both explicit and implicit operands!
+// Also make sure to skip over a parent who:
+// (1) is a list node in the Burg tree, or
+// (2) itself had its results forwarded to its parent
//
static void
ForwardOperand(InstructionNode* treeNode,
@@ -911,31 +1044,50 @@ ForwardOperand(InstructionNode* treeNode,
Instruction* userInstr = parentInstrNode->getInstruction();
MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(userInstr);
- for (unsigned i=0, N=mvec.size(); i < N; i++)
+
+ // The parent's mvec would be empty if it was itself forwarded.
+ // Recursively call ForwardOperand in that case...
+ //
+ if (mvec.size() == 0)
{
- MachineInstr* minstr = mvec[i];
-
- for (unsigned i=0, numOps=minstr->getNumOperands(); i < numOps; ++i)
+ assert(parent->parent() != NULL &&
+ "Parent could not have been forwarded, yet has no instructions?");
+ ForwardOperand(treeNode, parent->parent(), operandNum);
+ }
+ else
+ {
+ bool fwdSuccessful = false;
+ for (unsigned i=0, N=mvec.size(); i < N; i++)
{
- const MachineOperand& mop = minstr->getOperand(i);
- if (mop.getOperandType() == MachineOperand::MO_VirtualRegister &&
- mop.getVRegValue() == unusedOp)
+ MachineInstr* minstr = mvec[i];
+ for (unsigned i=0, numOps=minstr->getNumOperands(); i < numOps; ++i)
{
- minstr->SetMachineOperand(i, MachineOperand::MO_VirtualRegister,
- fwdOp);
+ const MachineOperand& mop = minstr->getOperand(i);
+ if (mop.getOperandType() == MachineOperand::MO_VirtualRegister &&
+ mop.getVRegValue() == unusedOp)
+ {
+ minstr->SetMachineOperandVal(i,
+ MachineOperand::MO_VirtualRegister, fwdOp);
+ fwdSuccessful = true;
+ }
}
+
+ for (unsigned i=0,numOps=minstr->getNumImplicitRefs(); i<numOps; ++i)
+ if (minstr->getImplicitRef(i) == unusedOp)
+ {
+ minstr->setImplicitRef(i, fwdOp,
+ minstr->implicitRefIsDefined(i));
+ fwdSuccessful = true;
+ }
}
-
- for (unsigned i=0, numOps=minstr->getNumImplicitRefs(); i < numOps; ++i)
- if (minstr->getImplicitRef(i) == unusedOp)
- minstr->setImplicitRef(i, fwdOp, minstr->implicitRefIsDefined(i));
+ assert(fwdSuccessful && "Value to be forwarded is never used!");
}
}
-
void UltraSparcInstrInfo::
CreateCopyInstructionsByType(const TargetMachine& target,
+ Method* method,
Value* src,
Instruction* dest,
vector<MachineInstr*>& minstrVec) const
@@ -973,23 +1125,23 @@ CreateCopyInstructionsByType(const TargetMachine& target,
{ // `src' is constant and cannot fit in immed field for the ADD
// Insert instructions to "load" the constant into a register
vector<TmpInstruction*> tempVec;
- target.getInstrInfo().CreateCodeToLoadConst(src,dest,minstrVec,tempVec);
+ target.getInstrInfo().CreateCodeToLoadConst(method, src, dest,minstrVec,tempVec);
for (unsigned i=0; i < tempVec.size(); i++)
MachineCodeForInstruction::get(dest).addTemp(tempVec[i]);
}
else
- { // Create the appropriate add instruction.
+ { // Create an add-with-0 instruction of the appropriate type.
// Make `src' the second operand, in case it is a constant
// Use (unsigned long) 0 for a NULL pointer value.
//
- const Type* nullValueType =
+ const Type* zeroValueType =
(resultType->getPrimitiveID() == Type::PointerTyID)? Type::ULongTy
: resultType;
MachineInstr* minstr = new MachineInstr(opCode);
- minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
- Constant::getNullConstant(nullValueType));
- minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, src);
- minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, dest);
+ minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
+ Constant::getNullConstant(zeroValueType));
+ minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, src);
+ minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
minstrVec.push_back(minstr);
}
}
@@ -1012,12 +1164,15 @@ GetInstructionsForProlog(BasicBlock* entryBB,
TargetMachine &target,
MachineInstr** mvec)
{
+ MachineInstr* M;
const MachineFrameInfo& frameInfo = target.getFrameInfo();
+ unsigned int N = 0;
// The second operand is the stack size. If it does not fit in the
- // immediate field, we either have to find an unused register in the
- // caller's window or move some elements to the dynamically allocated
- // area of the stack frame (just above save area and method args).
+ // immediate field, we have to use a free register to hold the size.
+ // We will assume that local register `l0' is unused since the SAVE
+ // instruction must be the first instruction in each procedure.
+ //
Method* method = entryBB->getParent();
MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(method);
unsigned int staticStackSize = mcInfo.getStaticStackSize();
@@ -1029,16 +1184,37 @@ GetInstructionsForProlog(BasicBlock* entryBB,
(unsigned) frameInfo.getStackFrameSizeAlignment()))
staticStackSize += frameInfo.getStackFrameSizeAlignment() - padsz;
- assert(target.getInstrInfo().constantFitsInImmedField(SAVE, staticStackSize)
- && "Stack size too large for immediate field of SAVE instruction. Need additional work as described in the comment above");
-
- mvec[0] = new MachineInstr(SAVE);
- mvec[0]->SetMachineOperand(0, target.getRegInfo().getStackPointer());
- mvec[0]->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
- - (int) staticStackSize);
- mvec[0]->SetMachineOperand(2, target.getRegInfo().getStackPointer());
+ if (target.getInstrInfo().constantFitsInImmedField(SAVE, staticStackSize))
+ {
+ M = new MachineInstr(SAVE);
+ M->SetMachineOperandReg(0, target.getRegInfo().getStackPointer());
+ M->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
+ - (int) staticStackSize);
+ M->SetMachineOperandReg(2, target.getRegInfo().getStackPointer());
+ mvec[N++] = M;
+ }
+ else
+ {
+ M = new MachineInstr(SETSW);
+ M->SetMachineOperandReg(0, MachineOperand::MO_SignExtendedImmed,
+ - staticStackSize);
+ M->SetMachineOperandReg(1, MachineOperand::MO_MachineRegister,
+ target.getRegInfo().getUnifiedRegNum(
+ target.getRegInfo().getRegClassIDOfType(Type::IntTy),
+ SparcIntRegOrder::l0));
+ mvec[N++] = M;
+
+ M = new MachineInstr(SAVE);
+ M->SetMachineOperandReg(0, target.getRegInfo().getStackPointer());
+ M->SetMachineOperandReg(1, MachineOperand::MO_MachineRegister,
+ target.getRegInfo().getUnifiedRegNum(
+ target.getRegInfo().getRegClassIDOfType(Type::IntTy),
+ SparcIntRegOrder::l0));
+ M->SetMachineOperandReg(2, target.getRegInfo().getStackPointer());
+ mvec[N++] = M;
+ }
- return 1;
+ return N;
}
@@ -1048,10 +1224,10 @@ GetInstructionsForEpilog(BasicBlock* anExitBB,
MachineInstr** mvec)
{
mvec[0] = new MachineInstr(RESTORE);
- mvec[0]->SetMachineOperand(0, target.getRegInfo().getZeroRegNum());
- mvec[0]->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
+ mvec[0]->SetMachineOperandReg(0, target.getRegInfo().getZeroRegNum());
+ mvec[0]->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
(int64_t)0);
- mvec[0]->SetMachineOperand(2, target.getRegInfo().getZeroRegNum());
+ mvec[0]->SetMachineOperandReg(2, target.getRegInfo().getZeroRegNum());
return 1;
}
@@ -1105,20 +1281,21 @@ ThisIsAChainRule(int eruleno)
// patterns chosen by the BURG-generated parser.
//------------------------------------------------------------------------
-unsigned
+void
GetInstructionsByRule(InstructionNode* subtreeRoot,
int ruleForNode,
short* nts,
TargetMachine &target,
- MachineInstr** mvec)
+ vector<MachineInstr*>& mvec)
{
- int numInstr = 1; // initialize for common case
bool checkCast = false; // initialize here to use fall-through
int nextRule;
int forwardOperandNum = -1;
-
- for (unsigned i=0; i < MAX_INSTR_PER_VMINSTR; i++)
- mvec[i] = NULL;
+ unsigned int allocaSize = 0;
+ MachineInstr* M, *M2;
+ unsigned int L;
+
+ mvec.clear();
//
// Let's check for chain rules outside the switch so that we don't have
@@ -1133,7 +1310,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
&& "A chain rule should have only one RHS non-terminal!");
nextRule = burm_rule(subtreeRoot->state, nts[0]);
nts = burm_nts[nextRule];
- numInstr = GetInstructionsByRule(subtreeRoot, nextRule, nts,target,mvec);
+ GetInstructionsByRule(subtreeRoot, nextRule, nts, target, mvec);
}
else
{
@@ -1153,39 +1330,40 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
Instruction* returnReg = new TmpInstruction(returnInstr);
MachineCodeForInstruction::get(returnInstr).addTemp(returnReg);
- mvec[0] = new MachineInstr(JMPLRET);
- mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ M = new MachineInstr(JMPLRET);
+ M->SetMachineOperandReg(0, MachineOperand::MO_VirtualRegister,
returnReg);
- mvec[0]->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
+ M->SetMachineOperandConst(1,MachineOperand::MO_SignExtendedImmed,
(int64_t)8);
- mvec[0]->SetMachineOperand(2, target.getRegInfo().getZeroRegNum());
+ M->SetMachineOperandReg(2, target.getRegInfo().getZeroRegNum());
if (returnInstr->getReturnValue() != NULL)
- mvec[0]->addImplicitRef(returnInstr->getReturnValue());