aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target
diff options
context:
space:
mode:
authorVikram S. Adve <vadve@cs.uiuc.edu>2001-10-18 00:26:20 +0000
committerVikram S. Adve <vadve@cs.uiuc.edu>2001-10-18 00:26:20 +0000
commit7fe27874be12ce754d136310e33b210cc28f4625 (patch)
tree033c075f0f7ac2f1a1dd0ff9d4634e2eeebdcd6e /lib/Target
parent8f1afbf3b3a70f90d477d6805d66f4fb02541df1 (diff)
downloadexternal_llvm-7fe27874be12ce754d136310e33b210cc28f4625.zip
external_llvm-7fe27874be12ce754d136310e33b210cc28f4625.tar.gz
external_llvm-7fe27874be12ce754d136310e33b210cc28f4625.tar.bz2
1. Move most of the constant-fixup code into machine-independent file
InstrSelectionSupport.cpp. It now happens in a bottom-up pass on each BURG tree after the original top-down selection pass on the tree. 2. Handle global values as constants (viz., constant addresses). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@868 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/SparcV9/SparcV9InstrSelection.cpp437
1 files changed, 42 insertions, 395 deletions
diff --git a/lib/Target/SparcV9/SparcV9InstrSelection.cpp b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
index 25b1d7b..ac8388a 100644
--- a/lib/Target/SparcV9/SparcV9InstrSelection.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
@@ -11,6 +11,7 @@
//**************************************************************************/
#include "SparcInternals.h"
+#include "SparcInstrSelectionSupport.h"
#include "llvm/CodeGen/InstrSelectionSupport.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/InstrForest.h"
@@ -48,46 +49,6 @@ static void SetMemOperands_Internal (MachineInstr* minstr,
//************************ Internal Functions ******************************/
-// Convenience function to get the value of an integer constant, for an
-// appropriate integer or non-integer type that can be held in an integer.
-// The type of the argument must be the following:
-// Signed or unsigned integer
-// Boolean
-// Pointer
-//
-// isValidConstant is set to true if a valid constant was found.
-//
-static int64_t
-GetConstantValueAsSignedInt(const Value *V,
- bool &isValidConstant)
-{
- if (!isa<ConstPoolVal>(V))
- {
- isValidConstant = false;
- return 0;
- }
-
- isValidConstant = true;
-
- if (V->getType() == Type::BoolTy)
- return (int64_t) ((ConstPoolBool*)V)->getValue();
-
- if (V->getType()->isIntegral())
- {
- if (V->getType()->isSigned())
- return ((ConstPoolSInt*)V)->getValue();
-
- assert(V->getType()->isUnsigned());
- uint64_t Val = ((ConstPoolUInt*)V)->getValue();
- if (Val < INT64_MAX) // then safe to cast to signed
- return (int64_t)Val;
- }
-
- isValidConstant = false;
- return 0;
-}
-
-
//------------------------------------------------------------------------
// External Function: ThisIsAChainRule
@@ -778,52 +739,6 @@ CreateDivConstInstruction(TargetMachine &target,
}
-static inline MachineOpCode
-ChooseLoadInstruction(const Type *DestTy)
-{
- switch (DestTy->getPrimitiveID()) {
- case Type::BoolTyID:
- case Type::UByteTyID: return LDUB;
- case Type::SByteTyID: return LDSB;
- case Type::UShortTyID: return LDUH;
- case Type::ShortTyID: return LDSH;
- case Type::UIntTyID: return LDUW;
- case Type::IntTyID: return LDSW;
- case Type::PointerTyID:
- case Type::ULongTyID:
- case Type::LongTyID: return LDX;
- case Type::FloatTyID: return LD;
- case Type::DoubleTyID: return LDD;
- default: assert(0 && "Invalid type for Load instruction");
- }
-
- return 0;
-}
-
-
-static inline MachineOpCode
-ChooseStoreInstruction(const Type *DestTy)
-{
- switch (DestTy->getPrimitiveID()) {
- case Type::BoolTyID:
- case Type::UByteTyID:
- case Type::SByteTyID: return STB;
- case Type::UShortTyID:
- case Type::ShortTyID: return STH;
- case Type::UIntTyID:
- case Type::IntTyID: return STW;
- case Type::PointerTyID:
- case Type::ULongTyID:
- case Type::LongTyID: return STX;
- case Type::FloatTyID: return ST;
- case Type::DoubleTyID: return STD;
- default: assert(0 && "Invalid type for Store instruction");
- }
-
- return 0;
-}
-
-
//------------------------------------------------------------------------
// Function SetOperandsForMemInstr
//
@@ -1003,277 +918,6 @@ SetMemOperands_Internal(MachineInstr* minstr,
}
-static inline MachineInstr*
-CreateIntSetInstruction(int64_t C, bool isSigned, Value* dest)
-{
- MachineInstr* minstr;
- if (isSigned)
- {
- minstr = new MachineInstr(SETSW);
- minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, C);
- }
- else
- {
- minstr = new MachineInstr(SETUW);
- minstr->SetMachineOperand(0, MachineOperand::MO_UnextendedImmed, C);
- }
-
- minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, dest);
-
- return minstr;
-}
-
-
-// Create an instruction sequence to load a constant into a register.
-// This always creates either one or two instructions.
-// If two instructions are created, the second one is returned in getMinstr2
-//
-static MachineInstr*
-CreateLoadConstInstr(const TargetMachine &target,
- Instruction* vmInstr,
- Value* val,
- Instruction* dest,
- MachineInstr*& getMinstr2)
-{
- assert(isa<ConstPoolVal>(val));
-
- MachineInstr* minstr1 = NULL;
-
- getMinstr2 = NULL;
-
- // Use a "set" instruction for known constants that can go in an integer reg.
- // Use a "set" instruction followed by a int-to-float conversion for known
- // constants that must go in a floating point reg but have an integer value.
- // Use a "load" instruction for all other constants, in particular,
- // floating point constants.
- //
- const Type* valType = val->getType();
-
- if (valType->isIntegral() || valType == Type::BoolTy)
- {
- bool isValidConstant;
- int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
- assert(isValidConstant && "Unrecognized constant");
- minstr1 = CreateIntSetInstruction(C, valType->isSigned(), dest);
- }
- else
- {
-
-#undef MOVE_INT_TO_FP_REG_AVAILABLE
-#ifdef MOVE_INT_TO_FP_REG_AVAILABLE
- //
- // This code was written to generate the following sequence:
- // SET[SU]W <int-const> <int-reg>
- // FITO[SD] <int-reg> <fp-reg>
- // (it really should have moved the int-reg to an fp-reg and then FITOS).
- // But for now the only way to move a value from an int-reg to an fp-reg
- // is via memory. Leave this code here but unused.
- //
- assert(valType == Type::FloatTy || valType == Type::DoubleTy);
- double dval = ((ConstPoolFP*) val)->getValue();
- if (dval == (int64_t) dval)
- {
- // The constant actually has an integer value, so use a
- // [set; int-to-float] sequence instead of a load instruction.
- //
- TmpInstruction* addrReg = NULL;
- if (dval != 0.0)
- { // First, create an integer constant of the same value as dval
- ConstPoolSInt* ival = ConstPoolSInt::get(Type::IntTy,
- (int64_t) dval);
- // Create another TmpInstruction for the hidden integer register
- addrReg = new TmpInstruction(Instruction::UserOp1, ival, NULL);
- vmInstr->getMachineInstrVec().addTempValue(addrReg);
-
- // Create the `SET' instruction
- minstr1 = CreateIntSetInstruction((int64_t)dval, true, addrReg);
- addrReg->addMachineInstruction(minstr1);
- }
-
- // In which variable do we put the second instruction?
- MachineInstr*& instr2 = (minstr1)? getMinstr2 : minstr1;
-
- // Create the int-to-float instruction
- instr2 = new MachineInstr(valType == Type::FloatTy? FITOS : FITOD);
-
- if (dval == 0.0)
- instr2->SetMachineOperand(0, target.getRegInfo().getZeroRegNum());
- else
- instr2->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
- addrReg);
-
- instr2->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
- dest);
- }
- else
-#endif /*MOVE_INT_TO_FP_REG_AVAILABLE*/
-
- {
- // Make an instruction sequence to load the constant, viz:
- // SETSW <addr-of-constant>, addrReg
- // LOAD /*addr*/ addrReg, /*offset*/ 0, dest
- // set the offset field to 0.
- //
- int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
-
- // Create another TmpInstruction for the hidden integer register
- TmpInstruction* addrReg =
- new TmpInstruction(Instruction::UserOp1, val, NULL);
- vmInstr->getMachineInstrVec().addTempValue(addrReg);
-
- minstr1 = new MachineInstr(SETUW);
- minstr1->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp,val);
- minstr1->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
- addrReg);
- addrReg->addMachineInstruction(minstr1);
-
- getMinstr2 = new MachineInstr(ChooseLoadInstruction(val->getType()));
- getMinstr2->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
- addrReg);
- getMinstr2->SetMachineOperand(1,MachineOperand::MO_SignExtendedImmed,
- zeroOffset);
- getMinstr2->SetMachineOperand(2,MachineOperand::MO_VirtualRegister,
- dest);
- }
- }
-
- assert(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:
-// -- 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,
-// use int-to-float conversion instruction instead of generating a load;
-// -- if the constant fits in the IMMEDIATE field, use that field;
-// -- else insert instructions to put the constant into a register, either
-// directly or by loading explicitly from the constant pool.
-//
-static unsigned
-FixConstantOperands(const InstructionNode* vmInstrNode,
- MachineInstr** mvec,
- unsigned numInstr,
- TargetMachine& target)
-{
- vector<MachineInstr*> loadConstVec;
- loadConstVec.reserve(MAX_INSTR_PER_VMINSTR);
-
- Instruction* vmInstr = vmInstrNode->getInstruction();
-
- for (unsigned i=0; i < numInstr; i++)
- {
- MachineInstr* minstr = mvec[i];
- const MachineInstrDescriptor& instrDesc =
- target.getInstrInfo().getDescriptor(minstr->getOpCode());
-
- for (unsigned op=0; op < minstr->getNumOperands(); op++)
- {
- const MachineOperand& mop = minstr->getOperand(op);
-
- // skip the result position (for efficiency below) and any other
- // positions already marked as not a virtual register
- if (instrDesc.resultPos == (int) op ||
- mop.getOperandType() != MachineOperand::MO_VirtualRegister ||
- mop.getVRegValue() == NULL)
- {
- continue;
- }
-
- Value* opValue = mop.getVRegValue();
-
- if (isa<ConstPoolVal>(opValue))
- {
- unsigned int machineRegNum;
- int64_t immedValue;
- MachineOperand::MachineOperandType opType =
- ChooseRegOrImmed(opValue, minstr->getOpCode(), target,
- /*canUseImmed*/ (op == 1),
- machineRegNum, immedValue);
-
- if (opType == MachineOperand::MO_MachineRegister)
- minstr->SetMachineOperand(op, machineRegNum);
- else if (opType == MachineOperand::MO_VirtualRegister)
- {
- TmpInstruction* tmpReg =
- InsertCodeToLoadConstant((ConstPoolVal*) opValue,
- vmInstr, loadConstVec, target);
- minstr->SetMachineOperand(op, opType, tmpReg);
- }
- else
- minstr->SetMachineOperand(op, opType, immedValue);
- }
- }
-
- //
- // 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=0, N=minstr->getNumImplicitRefs(); i < N; ++i)
- if (isa<ConstPoolVal>(minstr->getImplicitRef(i)))
- {
- TmpInstruction* tmpReg = InsertCodeToLoadConstant((ConstPoolVal*)
- minstr->getImplicitRef(i),
- vmInstr, loadConstVec, target);
- minstr->setImplicitRef(i, tmpReg);
- }
- }
-
- //
- // Finally, inserted the generated instructions in the vector
- // to be returned.
- //
- unsigned numNew = loadConstVec.size();
- if (numNew > 0)
- {
- // Insert the new instructions *before* the old ones by moving
- // the old ones over `numNew' positions (last-to-first, of course!).
- // We do check *after* returning that we did not exceed the vector mvec.
- for (int i=numInstr-1; i >= 0; i--)
- mvec[i+numNew] = mvec[i];
-
- for (unsigned i=0; i < numNew; i++)
- mvec[i] = loadConstVec[i];
- }
-
- return (numInstr + numNew);
-}
-
-
//
// Substitute operand `operandNum' of the instruction in node `treeNode'
// in place of the use(s) of that instruction in node `parent'.
@@ -1321,15 +965,13 @@ ForwardOperand(InstructionNode* treeNode,
}
-MachineInstr*
+void
CreateCopyInstructionsByType(const TargetMachine& target,
Value* src,
Instruction* dest,
- MachineInstr*& getMinstr2)
+ vector<MachineInstr*>& minstrVec)
{
- getMinstr2 = NULL; // initialize second return value
-
- MachineInstr* minstr1 = NULL;
+ bool loadConstantToReg = false;
const Type* resultType = dest->getType();
@@ -1337,11 +979,13 @@ CreateCopyInstructionsByType(const TargetMachine& target,
if (opCode == INVALID_OPCODE)
{
assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
- return NULL;
+ return;
}
- // if `src' is a constant that doesn't fit in the immed field, generate
- // a load instruction instead of an add
+ // if `src' is a constant that doesn't fit in the immed field or if it is
+ // a global variable (i.e., a constant address), generate a load
+ // instruction instead of an add
+ //
if (isa<ConstPoolVal>(src))
{
unsigned int machineRegNum;
@@ -1351,12 +995,20 @@ CreateCopyInstructionsByType(const TargetMachine& target,
machineRegNum, immedValue);
if (opType == MachineOperand::MO_VirtualRegister)
- { // value is constant and cannot fit in immed field for the ADD
- minstr1 = CreateLoadConstInstr(target, dest, src, dest, getMinstr2);
- }
+ loadConstantToReg = true;
}
-
- if (minstr1 == NULL)
+ else if (isa<GlobalValue>(src))
+ loadConstantToReg = true;
+
+ if (loadConstantToReg)
+ { // `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);
+ for (unsigned i=0; i < tempVec.size(); i++)
+ dest->getMachineInstrVec().addTempValue(tempVec[i]);
+ }
+ else
{ // Create the appropriate add instruction.
// Make `src' the second operand, in case it is a constant
// Use (unsigned long) 0 for a NULL pointer value.
@@ -1364,14 +1016,13 @@ CreateCopyInstructionsByType(const TargetMachine& target,
const Type* nullValueType =
(resultType->getPrimitiveID() == Type::PointerTyID)? Type::ULongTy
: resultType;
- minstr1 = new MachineInstr(opCode);
- minstr1->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
- ConstPoolVal::getNullConstant(nullValueType));
- minstr1->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, src);
- minstr1->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, dest);
+ MachineInstr* minstr = new MachineInstr(opCode);
+ minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ ConstPoolVal::getNullConstant(nullValueType));
+ minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, src);
+ minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, dest);
+ minstrVec.push_back(minstr);
}
-
- return minstr1;
}
@@ -1454,7 +1105,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
ReturnInst* returnInstr = (ReturnInst*) subtreeRoot->getInstruction();
assert(returnInstr->getOpcode() == Instruction::Ret);
- Instruction* returnReg = new TmpInstruction(Instruction::UserOp1,
+ Instruction* returnReg = new TmpInstruction(TMP_INSTRUCTION_OPCODE,
returnInstr, NULL);
returnInstr->getMachineInstrVec().addTempValue(returnReg);
@@ -1466,7 +1117,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
if (returnInstr->getReturnValue() != NULL)
mvec[0]->addImplicitRef(returnInstr->getReturnValue());
- returnReg->addMachineInstruction(mvec[0]);
+ // returnReg->addMachineInstruction(mvec[0]);
mvec[numInstr++] = new MachineInstr(NOP); // delay slot
break;
@@ -2011,7 +1662,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
ConstPoolSInt* valueForTSize = ConstPoolSInt::get(Type::IntTy, tsize);
// Create a temporary value to hold `tmp'
- Instruction* tmpInstr = new TmpInstruction(Instruction::UserOp1,
+ Instruction* tmpInstr = new TmpInstruction(TMP_INSTRUCTION_OPCODE,
subtreeRoot->leftChild()->getValue(),
NULL /*could insert tsize here*/);
subtreeRoot->getInstruction()->getMachineInstrVec().addTempValue(tmpInstr);
@@ -2025,7 +1676,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
mvec[0]->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
tmpInstr);
- tmpInstr->addMachineInstruction(mvec[0]);
+ // tmpInstr->addMachineInstruction(mvec[0]);
// Instruction 2: sub %sp, tmp -> %sp
numInstr++;
@@ -2057,9 +1708,9 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
CallInst *callInstr = cast<CallInst>(subtreeRoot->getInstruction());
Value *callee = callInstr->getCalledValue();
- Instruction* jmpAddrReg = new TmpInstruction(Instruction::UserOp1,
+ Instruction* jmpAddrReg = new TmpInstruction(TMP_INSTRUCTION_OPCODE,
callee, NULL);
- Instruction* retAddrReg = new TmpInstruction(Instruction::UserOp1,
+ Instruction* retAddrReg = new TmpInstruction(TMP_INSTRUCTION_OPCODE,
callInstr, NULL);
// Note temporary values in the machineInstrVec for the VM instr.
@@ -2093,8 +1744,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
// as computing that value.
// The retAddrReg is actually computed by the CALL instruction.
//
- jmpAddrReg->addMachineInstruction(mvec[0]);
- retAddrReg->addMachineInstruction(mvec[0]);
+ // jmpAddrReg->addMachineInstruction(mvec[0]);
+ // retAddrReg->addMachineInstruction(mvec[0]);
mvec[numInstr++] = new MachineInstr(NOP); // delay slot
break;
@@ -2152,20 +1803,16 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
ForwardOperand(subtreeRoot, subtreeRoot->parent(), forwardOperandNum);
else
{
- MachineInstr *minstr1 = NULL, *minstr2 = NULL;
- minstr1 = CreateCopyInstructionsByType(target,
+ vector<MachineInstr*> minstrVec;
+ CreateCopyInstructionsByType(target,
subtreeRoot->getInstruction()->getOperand(forwardOperandNum),
- subtreeRoot->getInstruction(), minstr2);
- assert(minstr1);
- mvec[numInstr++] = minstr1;
- if (minstr2 != NULL)
- mvec[numInstr++] = minstr2;
+ subtreeRoot->getInstruction(), minstrVec);
+ assert(minstrVec.size() > 0);
+ for (unsigned i=0; i < minstrVec.size(); ++i)
+ mvec[numInstr++] = minstrVec[i];
}
}
- if (! ThisIsAChainRule(ruleForNode))
- numInstr = FixConstantOperands(subtreeRoot, mvec, numInstr, target);
-
return numInstr;
}