Numerous bug fixes:
-- correct sign extensions for integer casts and for shift-by-constant
instructions generated for integer multiply
-- passing FP arguments to functions with more than 6 arguments
-- passing FP arguments to varargs functions
-- passing FP arguments to functions with no prototypes
-- incorrect stack frame size when padding a section
-- folding getelementptr operations with mixed array and struct indexes
-- use uint64_t instead of uint for constant offsets in mem operands
-- incorrect coloring for CC registers (both int and FP): interferences
were being completely ignored for int CC and were considered but no
spills were marked for fp CC!
Also some code improvements:
-- better interface to generating machine instr for common cases
(many places still need to be updated to use this interface)
-- annotations on MachineInstr to communicate information from
one codegen phase to another (now used to pass information about
CALL/JMPLCALL operands from selection to register allocation)
-- all sizes and offests in class TargetData are uint64_t instead of uint
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2640 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/SparcV9/SparcV9InstrInfo.cpp b/lib/Target/SparcV9/SparcV9InstrInfo.cpp
index fd18841..5fbced0 100644
--- a/lib/Target/SparcV9/SparcV9InstrInfo.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrInfo.cpp
@@ -16,7 +16,10 @@
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/InstrSelectionSupport.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
+#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/Function.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Instruction.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
@@ -24,56 +27,87 @@
//************************ Internal Functions ******************************/
-static inline MachineInstr*
-CreateIntSetInstruction(int64_t C, Value* dest,
- std::vector<TmpInstruction*>& tempVec)
+static inline void
+CreateIntSetInstruction(const TargetMachine& target, Function* F,
+ int64_t C, Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi)
{
- MachineInstr* minstr;
+ assert(dest->getType()->isSigned() && "Use CreateUIntSetInstruction()");
+
+ MachineInstr* M;
uint64_t absC = (C >= 0)? C : -C;
if (absC > (unsigned int) ~0)
{ // C does not fit in 32 bits
TmpInstruction* tmpReg = new TmpInstruction(Type::IntTy);
- tempVec.push_back(tmpReg);
+ mcfi.addTemp(tmpReg);
- minstr = new MachineInstr(SETX);
- minstr->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed, C);
- minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
- /*isdef*/ true);
- minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+ M = new MachineInstr(SETX);
+ M->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+ /*isdef*/ true);
+ M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+ mvec.push_back(M);
}
else
{
- minstr = new MachineInstr(SETSW);
- minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
- minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
+ M = Create2OperandInstr_SImmed(SETSW, C, dest);
+ mvec.push_back(M);
}
-
- return minstr;
}
-static inline MachineInstr*
-CreateUIntSetInstruction(uint64_t C, Value* dest,
- std::vector<TmpInstruction*>& tempVec)
+static inline void
+CreateUIntSetInstruction(const TargetMachine& target, Function* F,
+ uint64_t C, Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi)
{
- MachineInstr* minstr;
+ assert(! dest->getType()->isSigned() && "Use CreateIntSetInstruction()");
+ unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
+ MachineInstr* M;
+
if (C > (unsigned int) ~0)
{ // C does not fit in 32 bits
assert(dest->getType() == Type::ULongTy && "Sign extension problems");
TmpInstruction *tmpReg = new TmpInstruction(Type::IntTy);
- tempVec.push_back(tmpReg);
+ mcfi.addTemp(tmpReg);
- minstr = new MachineInstr(SETX);
- minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
- minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
- tmpReg, /*isdef*/ true);
- minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
+ M = new MachineInstr(SETX);
+ M->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+ /*isdef*/ true);
+ M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
+ mvec.push_back(M);
}
- else if (dest->getType() == Type::ULongTy)
+ else
{
- minstr = new MachineInstr(SETUW);
- minstr->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
- minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
+ // If the destination is smaller than the standard integer reg. size,
+ // we have to extend the sign-bit into upper bits of dest, so we
+ // need to put the result of the SETUW into a temporary.
+ //
+ Value* setuwDest = dest;
+ if (destSize < target.DataLayout.getIntegerRegize())
+ {
+ setuwDest = new TmpInstruction(dest, NULL, "setTmp");
+ mcfi.addTemp(setuwDest);
+ }
+
+ M = Create2OperandInstr_UImmed(SETUW, C, setuwDest);
+ mvec.push_back(M);
+
+ if (setuwDest != dest)
+ { // extend the sign-bit of the result into all upper bits of dest
+ assert(8*destSize <= 32 &&
+ "Unexpected type size > 4 and < IntRegSize?");
+ target.getInstrInfo().
+ CreateSignExtensionInstructions(target, F,
+ setuwDest, 8*destSize, dest,
+ mvec, mcfi);
+ }
}
+
+#define USE_DIRECT_SIGN_EXTENSION_INSTRS
+#ifndef USE_DIRECT_SIGN_EXTENSION_INSTRS
else
{ // cast to signed type of the right length and use signed op (SETSW)
// to get correct sign extension
@@ -103,8 +137,7 @@
break;
}
}
-
- return minstr;
+#endif USE_DIRECT_SIGN_EXTENSION_INSTRS
}
//************************* External Classes *******************************/
@@ -131,17 +164,18 @@
// Create an instruction sequence to put the constant `val' into
// the virtual register `dest'. `val' may be a Constant or a
// GlobalValue, viz., the constant address of a global variable or function.
-// The generated instructions are returned in `minstrVec'.
-// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
//
void
-UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
+UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
+ Function* F,
+ Value* val,
Instruction* dest,
- std::vector<MachineInstr*>&minstrVec,
- std::vector<TmpInstruction*>& tempVec) const
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
{
- MachineInstr* minstr;
-
assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
"I only know about constant values and global addresses");
@@ -153,19 +187,18 @@
if (valType->isIntegral() || valType == Type::BoolTy)
{
- if (ConstantUInt* uval = dyn_cast<ConstantUInt>(val))
+ if (! val->getType()->isSigned())
{
- uint64_t C = uval->getValue();
- minstr = CreateUIntSetInstruction(C, dest, tempVec);
+ uint64_t C = cast<ConstantUInt>(val)->getValue();
+ CreateUIntSetInstruction(target, F, C, dest, mvec, mcfi);
}
else
{
bool isValidConstant;
int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
assert(isValidConstant && "Unrecognized constant");
- minstr = CreateIntSetInstruction(C, dest, tempVec);
+ CreateIntSetInstruction(target, F, C, dest, mvec, mcfi);
}
- minstrVec.push_back(minstr);
}
else
{
@@ -180,42 +213,35 @@
TmpInstruction* tmpReg =
new TmpInstruction(PointerType::get(val->getType()), val);
- tempVec.push_back(tmpReg);
+ mcfi.addTemp(tmpReg);
if (isa<Constant>(val))
{
// Create another TmpInstruction for the hidden integer register
TmpInstruction* addrReg =
new TmpInstruction(PointerType::get(val->getType()), val);
- tempVec.push_back(addrReg);
+ mcfi.addTemp(addrReg);
addrVal = addrReg;
}
else
addrVal = dest;
- minstr = new MachineInstr(SETX);
- minstr->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
- minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,tmpReg,
- /*isdef*/ true);
- minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
- addrVal);
- minstrVec.push_back(minstr);
+ MachineInstr* M = new MachineInstr(SETX);
+ M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
+ M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
+ /*isdef*/ true);
+ M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, addrVal);
+ mvec.push_back(M);
if (isa<Constant>(val))
{
// Make sure constant is emitted to constant pool in assembly code.
- MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
- mcinfo.addToConstantPool(cast<Constant>(val));
+ MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
// Generate the load instruction
- minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
- minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
- addrVal);
- minstr->SetMachineOperandConst(1,MachineOperand::MO_SignExtendedImmed,
- zeroOffset);
- minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
- dest);
- minstrVec.push_back(minstr);
+ M = Create3OperandInstr_SImmed(ChooseLoadInstruction(val->getType()),
+ addrVal, zeroOffset, dest);
+ mvec.push_back(M);
}
}
}
@@ -224,24 +250,24 @@
// Create an instruction sequence to copy an integer value `val'
// to a floating point value `dest' by copying to memory and back.
// val must be an integral type. dest must be a Float or Double.
-// The generated instructions are returned in `minstrVec'.
-// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
//
void
-UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& minstrVec,
- std::vector<TmpInstruction*>& tempVec,
- TargetMachine& target) const
+UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
{
assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
&& "Source type must be integral");
assert(dest->getType()->isFloatingPoint()
&& "Dest type must be float/double");
- MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
- int offset = mcinfo.allocateLocalVar(target, val);
+ int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
// Store instruction stores `val' to [%fp+offset].
// The store and load opCodes are based on the value being copied, and
@@ -254,8 +280,8 @@
MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
- store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed, offset);
- minstrVec.push_back(store);
+ store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
+ mvec.push_back(store);
// Load instruction loads [%fp+offset] to `dest'.
//
@@ -263,29 +289,30 @@
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
- minstrVec.push_back(load);
+ mvec.push_back(load);
}
// Similarly, create an instruction sequence to copy an FP value
// `val' to an integer value `dest' by copying to memory and back.
-// See the previous function for information about return values.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
//
void
-UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Function *F,
+UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
+ Function* F,
Value* val,
Instruction* dest,
- std::vector<MachineInstr*>& minstrVec,
- std::vector<TmpInstruction*>& tempVec,
- TargetMachine& target) const
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
{
assert(val->getType()->isFloatingPoint()
&& "Source type must be float/double");
assert((dest->getType()->isIntegral() || isa<PointerType>(dest->getType()))
&& "Dest type must be integral");
- MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
- int offset = mcinfo.allocateLocalVar(target, val);
+ int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
// Store instruction stores `val' to [%fp+offset].
// The store and load opCodes are based on the value being copied, and
@@ -298,13 +325,113 @@
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
- minstrVec.push_back(store);
+ mvec.push_back(store);
// Load instruction loads [%fp+offset] to `dest'.
//
MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
- load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed, offset);
+ load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
- minstrVec.push_back(load);
+ mvec.push_back(load);
+}
+
+
+// Create instruction(s) to copy src to dest, for arbitrary types
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
+//
+void
+UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
+ Function *F,
+ Value* src,
+ Instruction* dest,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
+{
+ bool loadConstantToReg = false;
+
+ const Type* resultType = dest->getType();
+
+ MachineOpCode opCode = ChooseAddInstructionByType(resultType);
+ if (opCode == INVALID_OPCODE)
+ {
+ assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
+ return;
+ }
+
+ // 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<Constant>(src))
+ {
+ unsigned int machineRegNum;
+ int64_t immedValue;
+ MachineOperand::MachineOperandType opType =
+ ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
+ machineRegNum, immedValue);
+
+ if (opType == MachineOperand::MO_VirtualRegister)
+ loadConstantToReg = true;
+ }
+ 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
+ target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
+ mvec, mcfi);
+ }
+ else
+ { // 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* zeroValueType =
+ isa<PointerType>(resultType) ? Type::ULongTy : resultType;
+ MachineInstr* minstr =
+ Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
+ src, dest);
+ mvec.push_back(minstr);
+ }
+}
+
+
+// Create instruction sequence to produce a sign-extended register value
+// from an arbitrary sized value (sized in bits, not bytes).
+// For SPARC v9, we sign-extend the given unsigned operand using SLL; SRA.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineCodeForMethod.
+//
+void
+UltraSparcInstrInfo::CreateSignExtensionInstructions(
+ const TargetMachine& target,
+ Function* F,
+ Value* unsignedSrcVal,
+ unsigned int srcSizeInBits,
+ Value* dest,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
+{
+ MachineInstr* M;
+
+ assert(srcSizeInBits > 0 && srcSizeInBits <= 32
+ && "Hmmm... srcSizeInBits > 32 unexpected but could be handled here.");
+
+ if (srcSizeInBits < 32)
+ { // SLL is needed since operand size is < 32 bits.
+ TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
+ unsignedSrcVal, dest,"make32");
+ mcfi.addTemp(tmpI);
+ M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
+ mvec.push_back(M);
+ unsignedSrcVal = tmpI;
+ }
+
+ M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);
+ mvec.push_back(M);
}