aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVikram S. Adve <vadve@cs.uiuc.edu>2002-03-18 03:15:35 +0000
committerVikram S. Adve <vadve@cs.uiuc.edu>2002-03-18 03:15:35 +0000
commit7482532129d8f181f4d826a7362d500310db32b0 (patch)
treecdfdfd8da3809a8b40eb7b62d9b7901f0f11608e
parentf1c15ee4d15c3632343fccb723cce6f1d35bb5ba (diff)
Add support for code generation for array references.
Also, use distinct names for the three types of SetMachineOperand to avoid painful overloading problems and errors. Bug fix in converting-int-to-float. Other minor stuff. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1896 91177308-0d34-0410-b5e6-96231b3b80d8
-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();