aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target
diff options
context:
space:
mode:
authorVikram S. Adve <vadve@cs.uiuc.edu>2002-05-19 15:25:51 +0000
committerVikram S. Adve <vadve@cs.uiuc.edu>2002-05-19 15:25:51 +0000
commit242a8086aa6ccb29990aaf0c7a591003987330f1 (patch)
tree3d43c025cd8a41780f72c009756961c2a6233b9e /lib/Target
parent78771c886ad18e01859feb4dab8559ab5db464b9 (diff)
downloadexternal_llvm-242a8086aa6ccb29990aaf0c7a591003987330f1.zip
external_llvm-242a8086aa6ccb29990aaf0c7a591003987330f1.tar.gz
external_llvm-242a8086aa6ccb29990aaf0c7a591003987330f1.tar.bz2
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
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/SparcV9/SparcV9AsmPrinter.cpp21
-rw-r--r--lib/Target/SparcV9/SparcV9InstrInfo.cpp297
-rw-r--r--lib/Target/SparcV9/SparcV9InstrSelection.cpp615
-rw-r--r--lib/Target/SparcV9/SparcV9InstrSelectionSupport.h27
-rw-r--r--lib/Target/SparcV9/SparcV9Internals.h123
-rw-r--r--lib/Target/SparcV9/SparcV9RegClassInfo.cpp55
-rw-r--r--lib/Target/SparcV9/SparcV9RegClassInfo.h20
-rw-r--r--lib/Target/SparcV9/SparcV9RegInfo.cpp733
8 files changed, 1004 insertions, 887 deletions
diff --git a/lib/Target/SparcV9/SparcV9AsmPrinter.cpp b/lib/Target/SparcV9/SparcV9AsmPrinter.cpp
index 868f871..74b7f73 100644
--- a/lib/Target/SparcV9/SparcV9AsmPrinter.cpp
+++ b/lib/Target/SparcV9/SparcV9AsmPrinter.cpp
@@ -312,9 +312,9 @@ SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &op)
case MachineOperand::MO_PCRelativeDisp:
{
const Value *Val = op.getVRegValue();
- if (!Val)
- toAsm << "\t<*NULL Value*>";
- else if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val))
+ assert(Val && "\tNULL Value in SparcFunctionAsmPrinter");
+
+ if (const BasicBlock *BB = dyn_cast<const BasicBlock>(Val))
toAsm << getID(BB);
else if (const Function *M = dyn_cast<Function>(Val))
toAsm << getID(M);
@@ -323,13 +323,16 @@ SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &op)
else if (const Constant *CV = dyn_cast<Constant>(Val))
toAsm << getID(CV);
else
- toAsm << "<unknown value=" << Val << ">";
+ assert(0 && "Unrecognized value in SparcFunctionAsmPrinter");
break;
}
case MachineOperand::MO_SignExtendedImmed:
+ toAsm << op.getImmedValue();
+ break;
+
case MachineOperand::MO_UnextendedImmed:
- toAsm << (long)op.getImmedValue();
+ toAsm << (uint64_t) op.getImmedValue();
break;
default:
@@ -486,7 +489,9 @@ static string getAsCString(ConstantArray *CPA) {
(unsigned char)cast<ConstantSInt>(CPA->getOperand(i))->getValue() :
(unsigned char)cast<ConstantUInt>(CPA->getOperand(i))->getValue();
- if (isprint(C)) {
+ if (C == '"') {
+ Result += "\\\"";
+ } else if (isprint(C)) {
Result += C;
} else {
switch(C) {
@@ -666,13 +671,13 @@ SparcModuleAsmPrinter::printConstantValueOnly(const Constant* CV)
else if (CPA)
{ // Not a string. Print the values in successive locations
const std::vector<Use> &constValues = CPA->getValues();
- for (unsigned i=1; i < constValues.size(); i++)
+ for (unsigned i=0; i < constValues.size(); i++)
this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
}
else if (ConstantStruct *CPS = dyn_cast<ConstantStruct>(CV))
{ // Print the fields in successive locations
const std::vector<Use>& constValues = CPS->getValues();
- for (unsigned i=1; i < constValues.size(); i++)
+ for (unsigned i=0; i < constValues.size(); i++)
this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
}
else
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 @@ CreateUIntSetInstruction(uint64_t C, Value* dest,
break;
}
}
-
- return minstr;
+#endif USE_DIRECT_SIGN_EXTENSION_INSTRS
}
//************************* External Classes *******************************/
@@ -131,17 +164,18 @@ UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
// 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 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
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 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
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 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
// 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 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
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 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
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 @@ UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Function *F,
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);
}
diff --git a/lib/Target/SparcV9/SparcV9InstrSelection.cpp b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
index 7109ba4..668ac4a 100644
--- a/lib/Target/SparcV9/SparcV9InstrSelection.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
@@ -15,6 +15,7 @@
#include "SparcRegClassInfo.h"
#include "llvm/CodeGen/InstrSelectionSupport.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrAnnot.h"
#include "llvm/CodeGen/InstrForest.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
@@ -38,6 +39,7 @@ static void SetMemOperands_Internal (vector<MachineInstr*>& mvec,
const InstructionNode* vmInstrNode,
Value* ptrVal,
std::vector<Value*>& idxVec,
+ bool allConstantIndices,
const TargetMachine& target);
@@ -176,7 +178,9 @@ ChooseBccInstruction(const InstructionNode* instrNode,
BinaryOperator* setCCInstr = (BinaryOperator*) setCCNode->getInstruction();
const Type* setCCType = setCCInstr->getOperand(0)->getType();
- if (setCCType->isFloatingPoint())
+ isFPBranch = setCCType->isFloatingPoint(); // Return value: don't delete!
+
+ if (isFPBranch)
return ChooseBFpccInstruction(instrNode, setCCInstr);
else
return ChooseBpccInstruction(instrNode, setCCInstr);
@@ -327,31 +331,6 @@ CreateConvertToIntInstr(OpLabel vopCode, Value* srcVal, Value* destVal)
}
static inline MachineOpCode
-ChooseAddInstructionByType(const Type* resultType)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- if (resultType->isIntegral() ||
- isa<PointerType>(resultType) ||
- isa<FunctionType>(resultType) ||
- resultType == Type::LabelTy ||
- resultType == Type::BoolTy)
- {
- opCode = ADD;
- }
- else
- switch(resultType->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = FADDS; break;
- case Type::DoubleTyID: opCode = FADDD; break;
- default: assert(0 && "Invalid type for ADD instruction"); break;
- }
-
- return opCode;
-}
-
-
-static inline MachineOpCode
ChooseAddInstruction(const InstructionNode* instrNode)
{
return ChooseAddInstructionByType(instrNode->getInstruction()->getType());
@@ -383,12 +362,11 @@ CreateAddConstInstruction(const InstructionNode* instrNode)
// (1) Add with 0 for float or double: use an FMOV of appropriate type,
// instead of an FADD (1 vs 3 cycles). There is no integer MOV.
//
- const Type* resultType = instrNode->getInstruction()->getType();
-
if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
double dval = FPC->getValue();
if (dval == 0.0)
- minstr = CreateMovFloatInstruction(instrNode, resultType);
+ minstr = CreateMovFloatInstruction(instrNode,
+ instrNode->getInstruction()->getType());
}
return minstr;
@@ -428,12 +406,11 @@ CreateSubConstInstruction(const InstructionNode* instrNode)
// (1) Sub with 0 for float or double: use an FMOV of appropriate type,
// instead of an FSUB (1 vs 3 cycles). There is no integer MOV.
//
- const Type* resultType = instrNode->getInstruction()->getType();
-
if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
double dval = FPC->getValue();
if (dval == 0.0)
- minstr = CreateMovFloatInstruction(instrNode, resultType);
+ minstr = CreateMovFloatInstruction(instrNode,
+ instrNode->getInstruction()->getType());
}
return minstr;
@@ -506,19 +483,71 @@ CreateIntNegInstruction(const TargetMachine& target,
}
+// Create instruction sequence for any shift operation.
+// SLL or SLLX on an operand smaller than the integer reg. size (64bits)
+// requires a second instruction for explicit sign-extension.
+// Note that we only have to worry about a sign-bit appearing in the
+// most significant bit of the operand after shifting (e.g., bit 32 of
+// Int or bit 16 of Short), so we do not have to worry about results
+// that are as large as a normal integer register.
+//
+static inline void
+CreateShiftInstructions(const TargetMachine& target,
+ Function* F,
+ MachineOpCode shiftOpCode,
+ Value* argVal1,
+ Value* optArgVal2, /* Use optArgVal2 if not NULL */
+ unsigned int optShiftNum, /* else use optShiftNum */
+ Instruction* destVal,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi)
+{
+ assert((optArgVal2 != NULL || optShiftNum <= 64) &&
+ "Large shift sizes unexpected, but can be handled below: "
+ "You need to check whether or not it fits in immed field below");
+
+ // If this is a logical left shift of a type 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 SLL into a temporary.
+ //
+ Value* shiftDest = destVal;
+ const Type* opType = argVal1->getType();
+ unsigned opSize = target.DataLayout.getTypeSize(argVal1->getType());
+ if ((shiftOpCode == SLL || shiftOpCode == SLLX)
+ && opSize < target.DataLayout.getIntegerRegize())
+ { // put SLL result into a temporary
+ shiftDest = new TmpInstruction(argVal1, optArgVal2, "sllTmp");
+ mcfi.addTemp(shiftDest);
+ }
+
+ MachineInstr* M = (optArgVal2 != NULL)
+ ? Create3OperandInstr(shiftOpCode, argVal1, optArgVal2, shiftDest)
+ : Create3OperandInstr_UImmed(shiftOpCode, argVal1, optShiftNum, shiftDest);
+ mvec.push_back(M);
+
+ if (shiftDest != destVal)
+ { // extend the sign-bit of the result into all upper bits of dest
+ assert(8*opSize <= 32 && "Unexpected type size > 4 and < IntRegSize?");
+ target.getInstrInfo().
+ CreateSignExtensionInstructions(target, F, shiftDest, 8*opSize,
+ destVal, mvec, mcfi);
+ }
+}
+
+
// Does not create any instructions if we cannot exploit constant to
// create a cheaper instruction.
// This returns the approximate cost of the instructions generated,
// which is used to pick the cheapest when both operands are constant.
static inline unsigned int
-CreateMulConstInstruction(const TargetMachine &target,
- Value* lval, Value* rval, Value* destVal,
- vector<MachineInstr*>& mvec)
+CreateMulConstInstruction(const TargetMachine &target, Function* F,
+ Value* lval, Value* rval, Instruction* destVal,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi)
{
- /* An integer multiply is generally more costly than FP multiply */
+ /* Use max. multiply cost, viz., cost of MULX */
unsigned int cost = target.getInstrInfo().minLatency(MULX);
- MachineInstr* minstr1 = NULL;
- MachineInstr* minstr2 = NULL;
+ unsigned int firstNewInstr = mvec.size();
Value* constOp = rval;
if (! isa<Constant>(constOp))
@@ -532,11 +561,11 @@ CreateMulConstInstruction(const TargetMachine &target,
if (resultType->isIntegral() || isa<PointerType>(resultType))
{
- unsigned pow;
bool isValidConst;
int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
if (isValidConst)
{
+ unsigned pow;
bool needNeg = false;
if (C < 0)
{
@@ -547,30 +576,28 @@ CreateMulConstInstruction(const TargetMachine &target,
if (C == 0 || C == 1)
{
cost = target.getInstrInfo().minLatency(ADD);
- minstr1 = new MachineInstr(ADD);
- if (C == 0)
- minstr1->SetMachineOperandReg(0,
- target.getRegInfo().getZeroRegNum());
- else
- minstr1->SetMachineOperandVal(0,
- MachineOperand::MO_VirtualRegister, lval);
- minstr1->SetMachineOperandReg(1,
- target.getRegInfo().getZeroRegNum());
+ MachineInstr* M = (C == 0)
+ ? Create3OperandInstr_Reg(ADD,
+ target.getRegInfo().getZeroRegNum(),
+ target.getRegInfo().getZeroRegNum(),
+ destVal)
+ : Create3OperandInstr_Reg(ADD, lval,
+ target.getRegInfo().getZeroRegNum(),
+ destVal);
+ mvec.push_back(M);
}
else if (IsPowerOf2(C, pow))
{
- minstr1 = new MachineInstr((resultType == Type::LongTy)
- ? SLLX : SLL);
- minstr1->SetMachineOperandVal(0,
- MachineOperand::MO_VirtualRegister, lval);
- minstr1->SetMachineOperandConst(1,
- MachineOperand::MO_UnextendedImmed, pow);
+ unsigned int opSize = target.DataLayout.getTypeSize(resultType);
+ MachineOpCode opCode = (opSize <= 32)? SLL : SLLX;
+ CreateShiftInstructions(target, F, opCode, lval, NULL, pow,
+ destVal, mvec, mcfi);
}
- if (minstr1 && needNeg)
+ if (mvec.size() > 0 && needNeg)
{ // insert <reg = SUB 0, reg> after the instr to flip the sign
- minstr2 = CreateIntNegInstruction(target, destVal);
- cost += target.getInstrInfo().minLatency(minstr2->getOpCode());
+ MachineInstr* M = CreateIntNegInstruction(target, destVal);
+ mvec.push_back(M);
}
}
}
@@ -581,34 +608,20 @@ CreateMulConstInstruction(const TargetMachine &target,
double dval = FPC->getValue();
if (fabs(dval) == 1)
{
- bool needNeg = (dval < 0);
-
- MachineOpCode opCode = needNeg
+ MachineOpCode opCode = (dval < 0)
? (resultType == Type::FloatTy? FNEGS : FNEGD)
: (resultType == Type::FloatTy? FMOVS : FMOVD);
-
- minstr1 = new MachineInstr(opCode);
- minstr1->SetMachineOperandVal(0,
- MachineOperand::MO_VirtualRegister,
- lval);
+ MachineInstr* M = Create2OperandInstr(opCode, lval, destVal);
+ mvec.push_back(M);
}
}
}
- if (minstr1 != NULL)
- minstr1->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
- destVal);
-
- if (minstr1)
+ if (firstNewInstr < mvec.size())
{
- mvec.push_back(minstr1);
- cost = target.getInstrInfo().minLatency(minstr1->getOpCode());
- }
- if (minstr2)
- {
- assert(minstr1 && "Otherwise cost needs to be initialized to 0");
- cost += target.getInstrInfo().minLatency(minstr2->getOpCode());
- mvec.push_back(minstr2);
+ cost = 0;
+ for (unsigned int i=firstNewInstr; i < mvec.size(); ++i)
+ cost += target.getInstrInfo().minLatency(mvec[i]->getOpCode());
}
return cost;
@@ -620,17 +633,20 @@ CreateMulConstInstruction(const TargetMachine &target,
//
static inline void
CreateCheapestMulConstInstruction(const TargetMachine &target,
- Value* lval, Value* rval, Value* destVal,
- vector<MachineInstr*>& mvec)
+ Function* F,
+ Value* lval, Value* rval,
+ Instruction* destVal,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi)
{
Value* constOp;
if (isa<Constant>(lval) && isa<Constant>(rval))
{ // both operands are constant: try both orders!
vector<MachineInstr*> mvec1, mvec2;
- unsigned int lcost = CreateMulConstInstruction(target, lval, rval,
- destVal, mvec1);
- unsigned int rcost = CreateMulConstInstruction(target, rval, lval,
- destVal, mvec2);
+ unsigned int lcost = CreateMulConstInstruction(target, F, lval, rval,
+ destVal, mvec1, mcfi);
+ unsigned int rcost = CreateMulConstInstruction(target, F, rval, lval,
+ destVal, mvec2, mcfi);
vector<MachineInstr*>& mincostMvec = (lcost <= rcost)? mvec1 : mvec2;
vector<MachineInstr*>& maxcostMvec = (lcost <= rcost)? mvec2 : mvec1;
mvec.insert(mvec.end(), mincostMvec.begin(), mincostMvec.end());
@@ -639,9 +655,9 @@ CreateCheapestMulConstInstruction(const TargetMachine &target,
delete maxcostMvec[i];
}
else if (isa<Constant>(rval)) // rval is constant, but not lval
- CreateMulConstInstruction(target, lval, rval, destVal, mvec);
+ CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
else if (isa<Constant>(lval)) // lval is constant, but not rval
- CreateMulConstInstruction(target, lval, rval, destVal, mvec);
+ CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
// else neither is constant
return;
@@ -649,13 +665,14 @@ CreateCheapestMulConstInstruction(const TargetMachine &target,
// 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,
+CreateMulInstruction(const TargetMachine &target, Function* F,
+ Value* lval, Value* rval, Instruction* destVal,
vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi,
MachineOpCode forceMulOp = INVALID_MACHINE_OPCODE)
{
unsigned int L = mvec.size();
- CreateCheapestMulConstInstruction(target, lval, rval, destVal, mvec);
+ CreateCheapestMulConstInstruction(target,F, lval, rval, destVal, mvec, mcfi);
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.
@@ -889,6 +906,8 @@ CreateCodeForFixedSizeAlloca(const TargetMachine& target,
+
+
//------------------------------------------------------------------------
// Function SetOperandsForMemInstr
//
@@ -913,15 +932,14 @@ SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
{
MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
- // Variables to hold the index vector, ptr value, and offset value.
+ // Variables to hold the index vector and ptr value.
// The major work here is to extract these for all 3 instruction types
- // and then call the common function SetMemOperands_Internal().
- //
- Value* ptrVal = memInst->getPointerOperand();
-
- // Start with the index vector of this instruction, if any.
+ // and to try to fold chains of constant indices into a single offset.
+ // After that, we call SetMemOperands_Internal(), which creates the
+ // appropriate operands for the machine instruction.
vector<Value*> idxVec;
- idxVec.insert(idxVec.end(), memInst->idx_begin(), memInst->idx_end());
+ bool allConstantIndices = true;
+ Value* ptrVal = memInst->getPointerOperand();
// If there is a GetElemPtr instruction to fold in to this instr,
// it must be in the left child for Load and GetElemPtr, and in the
@@ -930,17 +948,40 @@ SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
? vmInstrNode->rightChild()
: vmInstrNode->leftChild());
- // Fold chains of GetElemPtr instructions for structure references.
- if (isa<StructType>(cast<PointerType>(ptrVal->getType())->getElementType())
- && (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
- ptrChild->getOpLabel() == GetElemPtrIdx))
+ // Check if all indices are constant for this instruction
+ for (MemAccessInst::op_iterator OI=memInst->idx_begin();
+ OI != memInst->idx_end(); ++OI)
+ if (! isa<ConstantUInt>(*OI))
+ {
+ allConstantIndices = false;
+ break;
+ }
+
+ // If we have only constant indices, fold chains of constant indices
+ // in this and any preceding GetElemPtr instructions.
+ if (allConstantIndices &&
+ ptrChild->getOpLabel() == Instruction::GetElementPtr ||
+ ptrChild->getOpLabel() == GetElemPtrIdx)
{
Value* newPtr = FoldGetElemChain((InstructionNode*) ptrChild, idxVec);
if (newPtr)
ptrVal = newPtr;
}
- SetMemOperands_Internal(mvec, mvecI, vmInstrNode, ptrVal, idxVec, target);
+ // Append the index vector of the current instruction, if any.
+ // Discard any leading [0] index.
+ if (memInst->idx_begin() != memInst->idx_end())
+ {
+ ConstantUInt* CV = dyn_cast<ConstantUInt>(* memInst->idx_begin());
+ unsigned zeroOrIOne = (CV && CV->getType() == Type::UIntTy &&
+ (CV->getValue() == 0))? 1 : 0;
+ idxVec.insert(idxVec.end(),
+ memInst->idx_begin()+zeroOrIOne, memInst->idx_end());
+ }
+
+ // Now create the appropriate operands for the machine instruction
+ SetMemOperands_Internal(mvec, mvecI, vmInstrNode,
+ ptrVal, idxVec, allConstantIndices, target);
}
@@ -953,6 +994,7 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
const InstructionNode* vmInstrNode,
Value* ptrVal,
vector<Value*>& idxVec,
+ bool allConstantIndices,
const TargetMachine& target)
{
MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
@@ -967,35 +1009,31 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
//
if (idxVec.size() > 0)
{
- unsigned offset = 0;
-
const PointerType* ptrType = cast<PointerType>(ptrVal->getType());
- // Handle special common case of leading [0] index.
- bool firstIndexIsZero =
- bool(isa<ConstantUInt>(idxVec.front()) &&
- cast<ConstantUInt>(idxVec.front())->getValue() == 0);
-
- // This is a real structure reference if the ptr target is a
- // structure type, and the first offset is [0] (eliminate that offset).
- if (firstIndexIsZero && isa<StructType>(ptrType->getElementType()))
+ // If all indices are constant, compute the combined offset directly.
+ if (allConstantIndices)
{
// Compute the offset value using the index vector. Create a
// virtual reg. for it since it may not fit in the immed field.
- assert(idxVec.size() >= 2);
- idxVec.erase(idxVec.begin());
- unsigned offset = target.DataLayout.getIndexedOffset(ptrType,idxVec);
- valueForRegOffset = ConstantSInt::get(Type::IntTy, offset);
+ uint64_t offset = target.DataLayout.getIndexedOffset(ptrType,idxVec);
+ valueForRegOffset = ConstantSInt::get(Type::LongTy, offset);
}
else
{
- // It is an array ref, and must have been lowered to a single offset.
+ // There is at least one non-constant offset. Therefore, this must
+ // be an array ref, and must have been lowered to a single offset.
assert((memInst->getNumOperands()
== (unsigned) 1 + memInst->getFirstIndexOperandNumber())
&& "Array refs must be lowered before Instruction Selection");
Value* arrayOffsetVal = * memInst->idx_begin();
+ // Handle special common case of leading [0] index.
+ ConstantUInt* CV = dyn_cast<ConstantUInt>(idxVec.front());
+ bool firstIndexIsZero = bool(CV && CV->getType() == Type::UIntTy &&
+ (CV->getValue() == 0));
+
// If index is 0, the offset value is just 0. Otherwise,
// generate a MUL instruction to compute address from index.
// The call to getTypeSize() will fail if size is not constant.
@@ -1018,10 +1056,13 @@ SetMemOperands_Internal(vector<MachineInstr*>& mvec,
ConstantUInt* eltVal = ConstantUInt::get(Type::UIntTy, eltSize);
CreateMulInstruction(target,
+ memInst->getParent()->getParent(),
arrayOffsetVal, /* lval, not likely const */
eltVal, /* rval, likely constant */
addr, /* result*/
- mulVec, INVALID_MACHINE_OPCODE);
+ mulVec,
+ MachineCodeForInstruction::get(memInst),
+ INVALID_MACHINE_OPCODE);
assert(mulVec.size() > 0 && "No multiply instruction created?");
for (vector<MachineInstr*>::const_iterator I = mulVec.begin();
I != mulVec.end(); ++I)
@@ -1116,7 +1157,6 @@ ForwardOperand(InstructionNode* treeNode,
}
else
{
- bool fwdSuccessful = false;
for (unsigned i=0, N=mvec.size(); i < N; i++)
{
MachineInstr* minstr = mvec[i];
@@ -1125,93 +1165,32 @@ ForwardOperand(InstructionNode* treeNode,
const MachineOperand& mop = minstr->getOperand(i);
if (mop.getOperandType() == MachineOperand::MO_VirtualRegister &&
mop.getVRegValue() == unusedOp)
- {
- minstr->SetMachineOperandVal(i,
+ 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;
- }
+ minstr->setImplicitRef(i, fwdOp,
+ minstr->implicitRefIsDefined(i));
}
- assert(fwdSuccessful && "Value to be forwarded is never used!");
}
}
-void UltraSparcInstrInfo::
-CreateCopyInstructionsByType(const TargetMachine& target,
- Function *F,
- Value* src,
- Instruction* dest,
- vector<MachineInstr*>& minstrVec) const
+inline bool
+AllUsesAreBranches(const Instruction* setccI)
{
- 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
- vector<TmpInstruction*> tempVec;
- target.getInstrInfo().CreateCodeToLoadConst(F, src, dest,
- minstrVec, tempVec);
- for (unsigned i=0; i < tempVec.size(); i++)
- MachineCodeForInstruction::get(dest).addTemp(tempVec[i]);
- }
- 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 = new MachineInstr(opCode);
- minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
- Constant::getNullValue(zeroValueType));
- minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, src);
- minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
- minstrVec.push_back(minstr);
- }
+ for (Value::use_const_iterator UI=setccI->use_begin(), UE=setccI->use_end();
+ UI != UE; ++UI)
+ if (! isa<TmpInstruction>(*UI) // ignore tmp instructions here
+ && cast<Instruction>(*UI)->getOpcode() != Instruction::Br)
+ return false;
+ return true;
}
-
-
//******************* Externally Visible Functions *************************/
-
-
//------------------------------------------------------------------------
// External Function: ThisIsAChainRule
//
@@ -1521,11 +1500,33 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
case 27: // reg: ToUIntTy(reg)
case 29: // reg: ToULongTy(reg)
{
+ Instruction* destI = subtreeRoot->getInstruction();
+ Value* opVal = subtreeRoot->leftChild()->getValue();
const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
assert(opType->isIntegral() ||
isa<PointerType>(opType) ||
opType == Type::BoolTy && "Cast is illegal for other types");
- forwardOperandNum = 0; // forward first operand to user
+
+ unsigned opSize = target.DataLayout.getTypeSize(opType);
+ unsigned destSize = target.DataLayout.getTypeSize(destI->getType());
+
+ if (opSize > destSize ||
+ (opType->isSigned()
+ && destSize < target.DataLayout.getIntegerRegize()))
+ { // operand is larger than dest,
+ // OR both are equal but smaller than the full register size
+ // AND operand is signed, so it may have extra sign bits:
+ // mask high bits using AND
+ //
+ M = Create3OperandInstr(AND, opVal,
+ ConstantUInt::get(Type::ULongTy,
+ ((uint64_t) 1 << 8*destSize) - 1),
+ destI);
+ mvec.push_back(M);
+ }
+ else
+ forwardOperandNum = 0; // forward first operand to user
+
break;
}
@@ -1534,18 +1535,49 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
case 28: // reg: ToIntTy(reg)
case 30: // reg: ToLongTy(reg)
{
- const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
+ unsigned int oldMvecSize = mvec.size(); // to check if it grew
+ Instruction* destI = subtreeRoot->getInstruction();
+ Value* opVal = subtreeRoot->leftChild()->getValue();
+ MachineCodeForInstruction& mcfi =MachineCodeForInstruction::get(destI);
+
+ const Type* opType = opVal->getType();
if (opType->isIntegral()
|| isa<PointerType>(opType)
|| opType == Type::BoolTy)
{
- forwardOperandNum = 0; // forward first operand to user
+ // These operand types have the same format as the destination,
+ // but may have different size: add sign bits or mask as needed.
+ //
+ const Type* destType = destI->getType();
+ unsigned opSize = target.DataLayout.getTypeSize(opType);
+ unsigned destSize = target.DataLayout.getTypeSize(destType);
+ if (opSize <= destSize && !opType->isSigned())
+ { // operand is smaller than or same size as dest:
+ // -- if operand is signed (checked above), nothing to do
+ // -- if operand is unsigned, sign-extend the value:
+ //
+ target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), opVal, 8*opSize, destI, mvec, mcfi);
+ }
+ else if (opSize > destSize)
+ { // operand is larger than dest: mask high bits using AND
+ // and then sign-extend using SRA by 0!
+ //
+ TmpInstruction *tmpI = new TmpInstruction(destType, opVal,
+ destI, "maskHi");
+ mcfi.addTemp(tmpI);
+ M = Create3OperandInstr(AND, opVal,
+ ConstantUInt::get(Type::UIntTy,
+ ((uint64_t) 1 << 8*destSize)-1),
+ tmpI);
+ mvec.push_back(M);
+
+ target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), tmpI, 8*destSize, destI, mvec, mcfi);
+ }
}
else
{
// If the source operand is an FP type, the int result must be
// copied from float to int register via memory!
- Instruction *dest = subtreeRoot->getInstruction();
Value* leftVal = subtreeRoot->leftChild()->getValue();
Value* destForCast;
vector<MachineInstr*> minstrVec;
@@ -1559,21 +1591,18 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
// double-prec for a 64-bit int.
//
const Type* destTypeToUse =
- (dest->getType() == Type::LongTy)? Type::DoubleTy
+ (destI->getType() == Type::LongTy)? Type::DoubleTy
: Type::FloatTy;
destForCast = new TmpInstruction(destTypeToUse, leftVal);
MachineCodeForInstruction &destMCFI =
- MachineCodeForInstruction::get(dest);
+ MachineCodeForInstruction::get(destI);
destMCFI.addTemp(destForCast);
- vector<TmpInstruction*> tempVec;
- target.getInstrInfo().CreateCodeToCopyFloatToInt(
- dest->getParent()->getParent(),
- (TmpInstruction*) destForCast, dest,
- minstrVec, tempVec, target);
-
- for (unsigned i=0; i < tempVec.size(); ++i)
- destMCFI.addTemp(tempVec[i]);
+ target.getInstrInfo().
+ CreateCodeToCopyFloatToInt(target,
+ destI->getParent()->getParent(),
+ (TmpInstruction*) destForCast,
+ destI, minstrVec, destMCFI);
}
else
destForCast = leftVal;
@@ -1585,6 +1614,10 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
// Append the copy code, if any, after the conversion instr.
mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
}
+
+ if (oldMvecSize == mvec.size()) // no instruction was generated
+ forwardOperandNum = 0; // forward first operand to user
+
break;
}
@@ -1620,7 +1653,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
Instruction *dest = subtreeRoot->getInstruction();
Value* srcForCast;
int n = 0;
- if (opType->isFloatingPoint())
+ if (! opType->isFloatingPoint())
{
// Create a temporary to represent the FP register
// into which the integer will be copied via memory.
@@ -1637,17 +1670,10 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
MachineCodeForInstruction::get(dest);
destMCFI.addTemp(srcForCast);
- vector<MachineInstr*> minstrVec;
- vector<TmpInstruction*> tempVec;
- target.getInstrInfo().CreateCodeToCopyIntToFloat(
+ target.getInstrInfo().CreateCodeToCopyIntToFloat(target,
dest->getParent()->getParent(),
leftVal, (TmpInstruction*) srcForCast,
- minstrVec, tempVec, target);
-
- mvec.insert(mvec.end(), minstrVec.begin(),minstrVec.end());
-
- for (unsigned i=0; i < tempVec.size(); ++i)
- destMCFI.addTemp(tempVec[i]);
+ mvec, destMCFI);
}
else
srcForCast = leftVal;
@@ -1705,11 +1731,12 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
? FSMULD
: INVALID_MACHINE_OPCODE);
- CreateMulInstruction(target,
+ Instruction* mulInstr = subtreeRoot->getInstruction();
+ CreateMulInstruction(target, mulInstr->getParent()->getParent(),
subtreeRoot->leftChild()->getValue(),
subtreeRoot->rightChild()->getValue(),
- subtreeRoot->getInstruction(),
- mvec, forceOp);
+ mulInstr, mvec,
+ MachineCodeForInstruction::get(mulInstr),forceOp);
break;
}
case 335: // reg: Mul(todouble, todoubleConst)
@@ -1721,11 +1748,13 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
? FSMULD
: INVALID_MACHINE_OPCODE);
- CreateMulInstruction(target,
+ Instruction* mulInstr = subtreeRoot->getInstruction();
+ CreateMulInstruction(target, mulInstr->getParent()->getParent(),
subtreeRoot->leftChild()->getValue(),
subtreeRoot->rightChild()->getValue(),
- subtreeRoot->getInstruction(),
- mvec, forceOp);
+ mulInstr, mvec,
+ MachineCodeForInstruction::get(mulInstr),
+ forceOp);
break;
}
case 236: // reg: Div(reg, Constant)
@@ -1793,7 +1822,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
case 239: // bool: Or(bool, boolconst)
case 339: // reg : BOr(reg, reg)
case 539: // reg : BOr(reg, Constant)
- mvec.push_back(new MachineInstr(ORN));
+ mvec.push_back(new MachineInstr(OR));
Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
break;
@@ -1829,7 +1858,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
// a result register, and setting a condition code.
//
// If the boolean result of the SetCC is used by anything other
- // than a single branch instruction, the boolean must be
+ // than a branch instruction, the boolean must be
// computed and stored in the result register. Otherwise, discard
// the difference (by using %g0) and keep only the condition code.
//
@@ -1840,9 +1869,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
//
InstructionNode* parentNode = (InstructionNode*) subtreeRoot->parent();
Instruction* setCCInstr = subtreeRoot->getInstruction();
- bool keepBoolVal = (parentNode == NULL ||
- parentNode->getInstruction()->getOpcode()
- != Instruction::Br);
+
+ bool keepBoolVal = ! AllUsesAreBranches(setCCInstr);
bool subValIsBoolVal = setCCInstr->getOpcode() == Instruction::SetNE;
bool keepSubVal = keepBoolVal && subValIsBoolVal;
bool computeBoolVal = keepBoolVal && ! subValIsBoolVal;
@@ -2008,7 +2036,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
Value *callee = callInstr->getCalledValue();
// Create hidden virtual register for return address, with type void*.
- Instruction* retAddrReg =
+ TmpInstruction* retAddrReg =
new TmpInstruction(PointerType::get(Type::VoidTy), callInstr);
MachineCodeForInstruction::get(callInstr).addTemp(retAddrReg);
@@ -2036,49 +2064,68 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
mvec.push_back(M);
- // WARNING: Operands 0..N-1 must go in slots 0..N-1 of implicitUses.
- // The result value must go in slot N. This is assumed
- // in register allocation.
- //
- // Add the call operands and return value as implicit refs
- // const Type* funcType = isa<Function>(callee)? callee->getType()
- // : cast<PointerType>(callee->getType())->getElementType();
- const Type* funcType = callee->getType();
- bool isVarArgs = cast<FunctionType>(cast<PointerType>(funcType)
- ->getElementType())->isVarArg();
+ const FunctionType* funcType =
+ cast<FunctionType>(cast<PointerType>(callee->getType())
+ ->getElementType());
+ bool isVarArgs = funcType->isVarArg();
+ bool noPrototype = isVarArgs && funcType->getNumParams() == 0;
- for (unsigned i=0, N=callInstr->getNumOperands(); i < N; ++i)
- if (callInstr->getOperand(i) != callee)
- {
- Value* argVal = callInstr->getOperand(i);
-
- // Check for FP arguments to varargs functions
- if (isVarArgs && argVal->getType()->isFloatingPoint())
- { // Add a copy-float-to-int instruction
- MachineCodeForInstruction &destMCFI =
- MachineCodeForInstruction::get(callInstr);
- Instruction* intArgReg =
- new TmpInstruction(Type::IntTy, argVal);
- destMCFI.addTemp(intArgReg);
-
- vector<MachineInstr*> minstrVec;
- vector<TmpInstruction*> tempVec;
- target.getInstrInfo().CreateCodeToCopyFloatToInt(
- callInstr->getParent()->getParent(),
- argVal, (TmpInstruction*) intArgReg,
- minstrVec, tempVec, target);
-
- mvec.insert(mvec.begin(), minstrVec.begin(),minstrVec.end());
-
- for (unsigned i=0; i < tempVec.size(); ++i)
- destMCFI.addTemp(tempVec[i]);
-
- argVal = intArgReg;
- }
-
- mvec.back()->addImplicitRef(argVal);
- }
+ // Use an annotation to pass information about call arguments
+ // to the register allocator.
+ CallArgsDescriptor* argDesc = new CallArgsDescriptor(callInstr,
+ retAddrReg, isVarArgs, noPrototype);
+ M->addAnnotation(argDesc);
+
+ assert(callInstr->getOperand(0) == callee
+ && "This is assumed in the loop below!");
+ for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i)
+ {
+ Value* argVal = callInstr->getOperand(i);
+ Instruction* intArgReg = NULL;
+
+ // Check for FP arguments to varargs functions.
+ // Any such argument in the first $K$ args must be passed in an
+ // integer register, where K = #integer argument registers.
+ if (isVarArgs && argVal->getType()->isFloatingPoint())
+ {
+ // If it is a function with no prototype, pass value
+ // as an FP value as well as a varargs value
+ if (noPrototype)
+ argDesc->getArgInfo(i-1).setUseFPArgReg();
+
+ // If this arg. is in the first $K$ regs, add a copy
+ // float-to-int instruction to pass the value as an integer.
+ if (i < target.getRegInfo().GetNumOfIntArgRegs())
+ {
+ MachineCodeForInstruction &destMCFI =
+ MachineCodeForInstruction::get(callInstr);
+ intArgReg = new TmpInstruction(Type::IntTy, argVal);
+ destMCFI.addTemp(intArgReg);
+
+ vector<MachineInstr*> copyMvec;
+ target.getInstrInfo().CreateCodeToCopyFloatToInt(target,
+ callInstr->getParent()->getParent(),
+ argVal, (TmpInstruction*) intArgReg,
+ copyMvec, destMCFI);
+ mvec.insert(mvec.begin(),copyMvec.begin(),copyMvec.end());
+
+ argDesc->getArgInfo(i-1).setUseIntArgReg();
+ argDesc->getArgInfo(i-1).setArgCopy(intArgReg);
+ }
+ else
+ // Cannot fit in first $K$ regs so pass the arg on the stack
+ argDesc->getArgInfo(i-1).setUseStackSlot();
+ }
+
+ if (intArgReg)
+ mvec.back()->addImplicitRef(intArgReg);
+
+ mvec.back()->addImplicitRef(argVal);
+ }
+
+ // Add the return value as an implicit ref. The call operands
+ // were added above.
if (callInstr->getType() != Type::VoidTy)
mvec.back()->addImplicitRef(callInstr, /*isDef*/ true);
@@ -2090,20 +2137,29 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
mvec.push_back(new MachineInstr(NOP));
break;
}
-
+
case 62: // reg: Shl(reg, reg)
- { const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
+ {
+ Value* argVal1 = subtreeRoot->leftChild()->getValue();
+ Value* argVal2 = subtreeRoot->rightChild()->getValue();
+ Instruction* shlInstr = subtreeRoot->getInstruction();
+
+ const Type* opType = argVal1->getType();
assert(opType->isIntegral()
- || isa<PointerType>(opType)&& "Shl unsupported for other types");
- mvec.push_back(new MachineInstr((opType == Type::LongTy)? SLLX : SLL));
- Set3OperandsFromInstr(mvec.back(), subtreeRoot, target);
+ || opType == Type::BoolTy
+ || isa<PointerType>(opType)&&"Shl unsupported for other types");
+
+ CreateShiftInstructions(target, shlInstr->getParent()->getParent(),
+ (opType == Type::LongTy)? SLLX : SLL,
+ argVal1, argVal2, 0, shlInstr, mvec,
+ MachineCodeForInstruction::get(shlInstr));
break;
}
case 63: // reg: Shr(reg, reg)
{ const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
assert(opType->isIntegral()
- || isa<PointerType>(opType) &&"Shr unsupported for other types");
+ || isa<PointerType>(opType)&&"Shr unsupported for other types");
mvec.push_back(new MachineInstr((opType->isSigned()
? ((opType == Type::LongTy)? SRAX : SRA)
: ((opType == Type::LongTy)? SRLX : SRL))));
@@ -2150,14 +2206,15 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
else
{
vector<MachineInstr*> minstrVec;
- target.getInstrInfo().CreateCopyInstructionsByType(target,
- subtreeRoot->getInstruction()->getParent()->getParent(),
- subtreeRoot->getInstruction()->getOperand(forwardOperandNum),
- subtreeRoot->getInstruction(), minstrVec);
+ Instruction* instr = subtreeRoot->getInstruction();
+ target.getInstrInfo().
+ CreateCopyInstructionsByType(target,
+ instr->getParent()->getParent(),
+ instr->getOperand(forwardOperandNum),
+ instr, minstrVec,
+ MachineCodeForInstruction::get(instr));
assert(minstrVec.size() > 0);
mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
}
}
}
-
-
diff --git a/lib/Target/SparcV9/SparcV9InstrSelectionSupport.h b/lib/Target/SparcV9/SparcV9InstrSelectionSupport.h
index 848dddd..2ee9294 100644
--- a/lib/Target/SparcV9/SparcV9InstrSelectionSupport.h
+++ b/lib/Target/SparcV9/SparcV9InstrSelectionSupport.h
@@ -12,6 +12,8 @@
#ifndef SPARC_INSTR_SELECTION_SUPPORT_h
#define SPARC_INSTR_SELECTION_SUPPORT_h
+#include "llvm/DerivedTypes.h"
+#include "llvm/Value.h"
inline MachineOpCode
ChooseLoadInstruction(const Type *DestTy)
@@ -58,4 +60,29 @@ ChooseStoreInstruction(const Type *DestTy)
return 0;
}
+
+inline MachineOpCode
+ChooseAddInstructionByType(const Type* resultType)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ if (resultType->isIntegral() ||
+ isa<PointerType>(resultType) ||
+ isa<FunctionType>(resultType) ||
+ resultType == Type::LabelTy ||
+ resultType == Type::BoolTy)
+ {
+ opCode = ADD;
+ }
+ else
+ switch(resultType->getPrimitiveID())
+ {
+ case Type::FloatTyID: opCode = FADDS; break;
+ case Type::DoubleTyID: opCode = FADDD; break;
+ default: assert(0 && "Invalid type for ADD instruction"); break;
+ }
+
+ return opCode;
+}
+
#endif
diff --git a/lib/Target/SparcV9/SparcV9Internals.h b/lib/Target/SparcV9/SparcV9Internals.h
index 4ca6616..b85b58f 100644
--- a/lib/Target/SparcV9/SparcV9Internals.h
+++ b/lib/Target/SparcV9/SparcV9Internals.h
@@ -123,47 +123,69 @@ public:
//-------------------------------------------------------------------------
// Create an instruction sequence to put the constant `val' into
- // the virtual register `dest'. The generated instructions are
- // returned in `minstrVec'. Any temporary registers (TmpInstruction)
- // created are returned in `tempVec'.
+ // 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 `mvec'.
+ // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+ // Any stack space required is allocated via mcff.
//
- virtual void CreateCodeToLoadConst(Function *F,
+ virtual void CreateCodeToLoadConst(const TargetMachine& target,
+ Function* F,
Value* val,
Instruction* dest,
- std::vector<MachineInstr*>& minstrVec,
- std::vector<TmpInstruction*>& tmp) const;
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
-
// 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 mcff.
//
- virtual void CreateCodeToCopyIntToFloat(Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& minstr,
- std::vector<TmpInstruction*>& temp,
- TargetMachine& target) const;
+ virtual void CreateCodeToCopyIntToFloat(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
// 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 mcff.
+ //
+ virtual void CreateCodeToCopyFloatToInt(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
+
+ // 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 mcff.
//
- virtual void CreateCodeToCopyFloatToInt(Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& minstr,
- std::vector<TmpInstruction*>& temp,
- TargetMachine& target) const;
-
- // create copy instruction(s)
virtual void CreateCopyInstructionsByType(const TargetMachine& target,
- Function* F,
- Value* src,
- Instruction* dest,
- std::vector<MachineInstr*>& minstr) const;
+ Function* F,
+ Value* src,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
+
+ // Create instruction sequence to produce a sign-extended register value
+ // from an arbitrary sized value (sized in bits, not bytes).
+ // Any stack space required is allocated via mcff.
+ //
+ virtual void CreateSignExtensionInstructions(const TargetMachine& target,
+ Function* F,
+ Value* unsignedSrcVal,
+ unsigned int srcSizeInBits,
+ Value* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
};
@@ -240,18 +262,16 @@ class UltraSparcRegInfo : public MachineRegInfo {
void suggestReg4CallAddr(const MachineInstr *CallMI, LiveRangeInfo &LRI,
std::vector<RegClass *> RCList) const;
-
-
- // The following methods are used to find the addresses etc. contained
- // in specail machine instructions like CALL/RET
- //
- Value *getValue4ReturnAddr(const MachineInstr *MInst) const;
- const Value *getCallInstRetAddr(const MachineInstr *CallMI) const;
- unsigned getCallInstNumArgs(const MachineInstr *CallMI) const;
-
-
- // The following 3 methods are used to find the RegType (see enum above)
+ void InitializeOutgoingArg(const MachineInstr* CallMI, AddedInstrns *CallAI,
+ PhyRegAlloc &PRA, LiveRange* LR,
+ unsigned regType, unsigned RegClassID,
+ int UniArgReg, unsigned int argNo,
+ std::vector<MachineInstr *>& AddedInstrnsBefore)
+ const;
+
+ // The following 4 methods are used to find the RegType (see enum above)
// of a LiveRange, Value and using the unified RegClassID
+ int getRegType(unsigned regClassID, const Type* type) const;
int getRegType(const LiveRange *LR) const;
int getRegType(const Value *Val) const;
int getRegType(int reg) const;
@@ -353,8 +373,12 @@ public:
//
unsigned getReturnAddressReg() const;
-
-
+ // Number of registers used for passing int args (usually 6: %o0 - %o5)
+ // and float args (usually 32: %f0 - %f31)
+ //
+ unsigned const GetNumOfIntArgRegs() const { return NumOfIntArgRegs; }
+ unsigned const GetNumOfFloatArgRegs() const { return NumOfFloatArgRegs; }
+
// The following methods are used to color special live ranges (e.g.
// function args and return values etc.) with specific hardware registers
// as required. See SparcRegInfo.cpp for the implementation for Sparc.
@@ -427,21 +451,20 @@ public:
const Value * getCallInstRetVal(const MachineInstr *CallMI) const;
const Value * getCallInstIndirectAddrVal(const MachineInstr *CallMI) const;
-
// The following methods are used to generate "copy" machine instructions
// for an architecture.
//
- MachineInstr * cpReg2RegMI(unsigned SrcReg, unsigned DestReg,
- int RegType) const;
+ void cpReg2RegMI(unsigned SrcReg, unsigned DestReg,
+ int RegType, vector<MachineInstr*>& mvec) const;
- MachineInstr * cpReg2MemMI(unsigned SrcReg, unsigned DestPtrReg,
- int Offset, int RegType) const;
-
- MachineInstr * cpMem2RegMI(unsigned SrcPtrReg, int Offset,
- unsigned DestReg, int RegType) const;
+ void cpReg2MemMI(unsigned SrcReg, unsigned DestPtrReg,
+ int Offset, int RegType, vector<MachineInstr*>& mvec) const;
- MachineInstr* cpValue2Value(Value *Src, Value *Dest) const;
+ void cpMem2RegMI(unsigned SrcPtrReg, int Offset, unsigned DestReg,
+ int RegType, vector<MachineInstr*>& mvec) const;
+ void cpValue2Value(Value *Src, Value *Dest,
+ vector<MachineInstr*>& mvec) const;
// To see whether a register is a volatile (i.e., whehter it must be
// preserved acorss calls)
diff --git a/lib/Target/SparcV9/SparcV9RegClassInfo.cpp b/lib/Target/SparcV9/SparcV9RegClassInfo.cpp
index 6f645b1..11a8251 100644
--- a/lib/Target/SparcV9/SparcV9RegClassInfo.cpp
+++ b/lib/Target/SparcV9/SparcV9RegClassInfo.cpp
@@ -20,22 +20,6 @@ using std::cerr;
//-----------------------------------------------------------------------------
void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const {
LiveRange *LR = Node->getParentLR();
- unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
-
- for (unsigned n=0; n < NumNeighbors; n++) { // for each neigh
- IGNode *NeighIGNode = Node->getAdjIGNode(n);
- LiveRange *NeighLR = NeighIGNode->getParentLR();
-
- if(NeighLR->hasColor()) // if has a color
- IsColorUsedArr[NeighLR->getColor()] = true; // record that color
-
- else if (NeighLR->hasSuggestedColor()) {
-
- // if the neighbout can use the suggested color
- if(NeighLR->isSuggestedColorUsable())
- IsColorUsedArr[NeighLR->getSuggestedColor()] = true;
- }
- }
if( DEBUG_RA ) {
cerr << "\nColoring LR [CallInt=" << LR->isCallInterference() <<"]:";
@@ -148,38 +132,35 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, bool IsColorUsedArr[]) const {
//----------------------------------------------------------------------------
void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const{
LiveRange *LR = Node->getParentLR();
- unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
+ // Mark the second color for double-precision registers:
+ // This is UGLY and should be merged into nearly identical code
+ // in RegClass::colorIGNode that handles the first color.
+ //
+ unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh
IGNode *NeighIGNode = Node->getAdjIGNode(n);
LiveRange *NeighLR = NeighIGNode->getParentLR();
-
- if( NeighLR->hasColor() ) { // if neigh has a color
- IsColorUsedArr[ NeighLR->getColor() ] = true; // record that color
- if (NeighLR->getType() == Type::DoubleTy)
- IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true;
- }
- else if( NeighLR->hasSuggestedColor() ) { // if neigh has sugg color
-
- if( NeighLR-> isSuggestedColorUsable() ) {
-
- // if the neighbout can use the suggested color
-
+
+ if( NeighLR->hasColor() &&
+ NeighLR->getType() == Type::DoubleTy) {
+ IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true;
+
+ } else if (NeighLR->hasSuggestedColor() &&
+ NeighLR-> isSuggestedColorUsable() ) {
+
+ // if the neighbour can use the suggested color
IsColorUsedArr[ NeighLR->getSuggestedColor() ] = true;
if (NeighLR->getType() == Type::DoubleTy)
IsColorUsedArr[ (NeighLR->getSuggestedColor()) + 1 ] = true;
- }
-
- }
-
+ }
}
-
// **NOTE: We don't check for call interferences in allocating suggested
// color in this class since ALL registers are volatile. If this fact
// changes, we should change the following part
//- see SparcIntRegClass::colorIGNode()
-
+ //
if( LR->hasSuggestedColor() ) {
if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) {
LR->setColor( LR->getSuggestedColor() );
@@ -244,10 +225,8 @@ void SparcFloatRegClass::colorIGNode(IGNode * Node,bool IsColorUsedArr[]) const{
IsColorUsedArr);
}
-
-
if( ColorFound >= 0 ) {
- LR->setColor(ColorFound); // first color found in preffered order
+ LR->setColor(ColorFound); // first color found in prefered order
LR->markForSaveAcrossCalls();
} else {
// we are here because no color could be found
diff --git a/lib/Target/SparcV9/SparcV9RegClassInfo.h b/lib/Target/SparcV9/SparcV9RegClassInfo.h
index 67d3f33..ab5b35c 100644
--- a/lib/Target/SparcV9/SparcV9RegClassInfo.h
+++ b/lib/Target/SparcV9/SparcV9RegClassInfo.h
@@ -191,15 +191,17 @@ struct SparcIntCCRegOrder {
struct SparcIntCCRegClass : public MachineRegClassInfo {
SparcIntCCRegClass(unsigned ID)
: MachineRegClassInfo(ID, 1, 2) { }
-
+
inline void colorIGNode(IGNode *Node, bool IsColorUsedArr[]) const {
- Node->setColor(0); // only one int cc reg is available
+ if (IsColorUsedArr[0])
+ Node->getParentLR()->markForSpill();
+ else
+ Node->setColor(0); // only one int cc reg is available
}
-
+
// according to Sparc 64 ABI, %ccr is volatile
//
inline bool isRegVolatile(int Reg) const { return true; }
-
};
@@ -231,11 +233,13 @@ struct SparcFloatCCRegClass : public MachineRegClassInfo {
void colorIGNode(IGNode *Node, bool IsColorUsedArr[]) const {
int c;
- for(c=0; c < 4 && IsColorUsedArr[c] ; ++c) ; // find color
- assert ((c < 4) && "Can allocate only 4 float cc registers");
- Node->setColor(c);
+ for(c=0; c < 4 && IsColorUsedArr[c] ; ++c) ; // find unused color
+ if (c < 4)
+ Node->setColor(c);
+ else
+ Node->getParentLR()->markForSpill();
}
-
+
// according to Sparc 64 ABI, all %fp CC regs are volatile
//
inline bool isRegVolatile(int Reg) const { return true; }
diff --git a/lib/Target/SparcV9/SparcV9RegInfo.cpp b/lib/Target/SparcV9/SparcV9RegInfo.cpp
index b660e89..63498e7 100644
--- a/lib/Target/SparcV9/SparcV9RegInfo.cpp
+++ b/lib/Target/SparcV9/SparcV9RegInfo.cpp
@@ -10,7 +10,9 @@
#include "llvm/Target/Sparc.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/PhyRegAlloc.h"
+#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrAnnot.h"
#include "llvm/CodeGen/RegAllocCommon.h"
#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h"
#include "llvm/iTerminators.h"
@@ -127,14 +129,11 @@ UltraSparcRegInfo::regNumForIntArg(bool inCallee, bool isVarArgsCall,
unsigned intArgNo, unsigned fpArgNo,
unsigned& regClassId) const
{
- int firstArgReg = inCallee? SparcIntRegOrder::i0 : SparcIntRegOrder::o0;
+ regClassId = IntRegClassID;
if (argNo >= NumOfIntArgRegs)
return InvalidRegNum;
- else {
- regClassId = IntRegClassID;
- return isVarArgsCall? firstArgReg + argNo
- : firstArgReg + intArgNo;
- }
+ else
+ return argNo + (inCallee? SparcIntRegOrder::i0 : SparcIntRegOrder::o0);
}
// Get the register number for the specified FP arg#,
@@ -153,128 +152,54 @@ UltraSparcRegInfo::regNumForFPArg(unsigned regType,
unsigned intArgNo, unsigned fpArgNo,
unsigned& regClassId) const
{
- if (isVarArgsCall) {
- assert(! isVarArgsCall &&
- "FP arguments to a varargs function should be explicitly copied "
- "to/from int registers by instruction selection!");
- return InvalidRegNum;
- }
- else {
- regClassId = FloatRegClassID;
- if (regType == FPSingleRegType)
- return (fpArgNo*2+1 >= NumOfFloatArgRegs)?
- InvalidRegNum : SparcFloatRegOrder::f0 + (fpArgNo * 2 + 1);
- else if (regType == FPDoubleRegType)
- return (fpArgNo*2 >= NumOfFloatArgRegs)?
- InvalidRegNum : SparcFloatRegOrder::f0 + (fpArgNo * 2);
- else
- assert(0 && "Illegal FP register type");
- }
-}
-
-//---------------------------------------------------------------------------
-// Finds the return value of a sparc specific call instruction
-//---------------------------------------------------------------------------
-
-const Value *
-UltraSparcRegInfo::getCallInstRetVal(const MachineInstr *CallMI) const {
- unsigned OpCode = CallMI->getOpCode();
- unsigned NumOfImpRefs = CallMI->getNumImplicitRefs();
-
- if (OpCode == CALL) {
-
- // The one before the last implicit operand is the return value of
- // a CALL instr
- //
- if( NumOfImpRefs > 1 )
- if (CallMI->implicitRefIsDefined(NumOfImpRefs-2))
- return CallMI->getImplicitRef(NumOfImpRefs-2);
-
- } else if (OpCode == JMPLCALL) {
-
- // The last implicit operand is the return value of a JMPL
- //
- if(NumOfImpRefs > 0)
- if (CallMI->implicitRefIsDefined(NumOfImpRefs-1))
- return CallMI->getImplicitRef(NumOfImpRefs-1);
- } else
- assert(0 && "OpCode must be CALL/JMPL for a call instr");
-
- return NULL;
-}
-
-
-const Value *
-UltraSparcRegInfo::getCallInstIndirectAddrVal(const MachineInstr *CallMI) const
-{
- return (CallMI->getOpCode() == JMPLCALL)?
- CallMI->getOperand(0).getVRegValue() : NULL;
+ if (isVarArgsCall)
+ return regNumForIntArg(inCallee, isVarArgsCall, argNo, intArgNo, fpArgNo,
+ regClassId);
+ else
+ {
+ regClassId = FloatRegClassID;
+ if (regType == FPSingleRegType)
+ return (argNo*2+1 >= NumOfFloatArgRegs)?
+ InvalidRegNum : SparcFloatRegOrder::f0 + (argNo * 2 + 1);
+ else if (regType == FPDoubleRegType)
+ return (argNo*2 >= NumOfFloatArgRegs)?
+ InvalidRegNum : SparcFloatRegOrder::f0 + (argNo * 2);
+ else
+ assert(0 && "Illegal FP register type");
+ }
}
//---------------------------------------------------------------------------
// Finds the return address of a call sparc specific call instruction
//---------------------------------------------------------------------------
-const Value *
-UltraSparcRegInfo::getCallInstRetAddr(const MachineInstr *CallMI) const {
- unsigned OpCode = CallMI->getOpCode();
-
- if (OpCode == CALL) {
- unsigned NumOfImpRefs = CallMI->getNumImplicitRefs();
- assert( NumOfImpRefs && "CALL instr must have at least on ImpRef");
-
- // The last implicit operand is the return address of a CALL instr
- //
- return CallMI->getImplicitRef(NumOfImpRefs-1);
-
- } else if(OpCode == JMPLCALL) {
- MachineOperand &MO = (MachineOperand &)CallMI->getOperand(2);
- return MO.getVRegValue();
- }
-
- assert(0 && "OpCode must be CALL/JMPL for a call instr");
- return 0;
-}
-
-// The following 3 methods are used to find the RegType (see enum above)
-// of a LiveRange, Value and using the unified RegClassID
+// The following 4 methods are used to find the RegType (see enum above)
+// of a LiveRange, a Value, and for a given register unified reg number.
//
-int UltraSparcRegInfo::getRegType(const LiveRange *LR) const {
- switch (LR->getRegClass()->getID()) {
+int UltraSparcRegInfo::getRegType(unsigned regClassID,
+ const Type* type) const {
+ switch (regClassID) {
case IntRegClassID: return IntRegType;
case FloatRegClassID: {
- const Type *Typ = LR->getType();
- if (Typ == Type::FloatTy)
+ if (type == Type::FloatTy)
return FPSingleRegType;
- else if (Typ == Type::DoubleTy)
+ else if (type == Type::DoubleTy)
return FPDoubleRegType;
assert(0 && "Unknown type in FloatRegClass");
}
- case IntCCRegClassID: return IntCCRegType;
+ case IntCCRegClassID: return IntCCRegType;
case FloatCCRegClassID: return FloatCCRegType;
- default: assert( 0 && "Unknown reg class ID");
- return 0;
+ default: assert( 0 && "Unknown reg class ID"); return 0;
}
}
+int UltraSparcRegInfo::getRegType(const LiveRange *LR) const {
+ return getRegType(LR->getRegClass()->getID(), LR->getType());
+}
+
int UltraSparcRegInfo::getRegType(const Value *Val) const {
- unsigned Typ;
-
- switch (getRegClassIDOfValue(Val)) {
- case IntRegClassID: return IntRegType;
- case FloatRegClassID:
- if (Val->getType() == Type::FloatTy)
- return FPSingleRegType;
- else if (Val->getType() == Type::DoubleTy)
- return FPDoubleRegType;
- assert(0 && "Unknown type in FloatRegClass");
-
- case IntCCRegClassID: return IntCCRegType;
- case FloatCCRegClassID: return FloatCCRegType;
- default: assert(0 && "Unknown reg class ID");
- return 0;
- }
+ return getRegType(getRegClassIDOfValue(Val), Val->getType());
}
int UltraSparcRegInfo::getRegType(int reg) const {
@@ -294,47 +219,6 @@ int UltraSparcRegInfo::getRegType(int reg) const {
}
-
-
-
-//---------------------------------------------------------------------------
-// Finds the # of actual arguments of the call instruction
-//---------------------------------------------------------------------------
-unsigned
-UltraSparcRegInfo::getCallInstNumArgs(const MachineInstr *CallMI) const {
-
- unsigned OpCode = CallMI->getOpCode();
- unsigned NumOfImpRefs = CallMI->getNumImplicitRefs();
-
- if (OpCode == CALL) {
- switch (NumOfImpRefs) {
- case 0: assert(0 && "A CALL inst must have at least one ImpRef (RetAddr)");
- case 1: return 0;
- default: // two or more implicit refs
- if (CallMI->implicitRefIsDefined(NumOfImpRefs-2))
- return NumOfImpRefs - 2;
- else
- return NumOfImpRefs - 1;
- }
- } else if (OpCode == JMPLCALL) {
-
- // The last implicit operand is the return value of a JMPL instr
- if( NumOfImpRefs > 0 ) {
- if (CallMI->implicitRefIsDefined(NumOfImpRefs-1))
- return NumOfImpRefs - 1;
- else
- return NumOfImpRefs;
- }
- else
- return NumOfImpRefs;
- }
-
- assert(0 && "OpCode must be CALL/JMPL for a call instr");
- return 0;
-}
-
-
-
//---------------------------------------------------------------------------
// Suggests a register for the ret address in the RET machine instruction.
// We always suggest %i7 by convention.
@@ -372,13 +256,11 @@ void UltraSparcRegInfo::suggestReg4RetAddr(const MachineInstr *RetMI,
void UltraSparcRegInfo::suggestReg4CallAddr(const MachineInstr * CallMI,
LiveRangeInfo& LRI,
std::vector<RegClass *> RCList) const {
-
-
- const Value *RetAddrVal = getCallInstRetAddr( CallMI );
-
- // RetAddrVal cannot be NULL (asserted in getCallInstRetAddr)
- // create a new LR for the return address and color it
+ CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
+ const Value *RetAddrVal = argDesc->getReturnAddrReg();
+ assert(RetAddrVal && "Return address value is required");
+ // create a new LR for the return address and color it
LiveRange * RetAddrLR = new LiveRange();
RetAddrLR->insert( RetAddrVal );
unsigned RegClassID = getRegClassIDOfValue( RetAddrVal );
@@ -419,8 +301,10 @@ void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth,
unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg (unused)
int regNum = (regType == IntRegType)
- ? regNumForIntArg(true, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
- : regNumForFPArg(regType, true, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
+ ? regNumForIntArg(/*inCallee*/ true, isVarArgs,
+ argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
+ : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs,
+ argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
if(regNum != InvalidRegNum)
LR->setSuggestedColor(regNum);
@@ -428,7 +312,6 @@ void UltraSparcRegInfo::suggestRegs4MethodArgs(const Function *Meth,
}
-
//---------------------------------------------------------------------------
// This method is called after graph coloring to move incoming args to
// the correct hardware registers if they did not receive the correct
@@ -463,8 +346,10 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg
int regNum = (regType == IntRegType)
- ? regNumForIntArg(true, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
- : regNumForFPArg(regType, true, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
+ ? regNumForIntArg(/*inCallee*/ true, isVarArgs,
+ argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
+ : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs,
+ argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
if(regNum != InvalidRegNum) {
isArgInReg = true;
@@ -489,12 +374,8 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
// the UniLRReg register
//
if( isArgInReg ) {
- AdMI = cpReg2RegMI( UniArgReg, UniLRReg, regType );
-
if( regClassIDOfArgReg != RegClassID ) {
- assert(0 &&
- "FP arguments to a varargs function should be explicitly "
- "copied to/from int registers by instruction selection!");
+ assert(0 && "This could should work but it is not tested yet");
// It is a variable argument call: the float reg must go in a %o reg.
// We have to move an int reg to a float reg via memory.
@@ -506,15 +387,14 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
int TmpOff = MachineCodeForMethod::get(Meth).pushTempValue(target,
getSpilledRegSize(regType));
- AdMI = cpReg2MemMI(UniArgReg, getFramePointer(), TmpOff, IntRegType);
- FirstAI->InstrnsBefore.push_back(AdMI);
+ cpReg2MemMI(UniArgReg, getFramePointer(), TmpOff, IntRegType,
+ FirstAI->InstrnsBefore);
- AdMI = cpMem2RegMI(getFramePointer(), TmpOff, UniLRReg, regType);
- FirstAI->InstrnsBefore.push_back(AdMI);
+ cpMem2RegMI(getFramePointer(), TmpOff, UniLRReg, regType,
+ FirstAI->InstrnsBefore);
}
else {
- AdMI = cpReg2RegMI(UniArgReg, UniLRReg, regType );
- FirstAI->InstrnsBefore.push_back( AdMI );
+ cpReg2RegMI(UniArgReg, UniLRReg, regType, FirstAI->InstrnsBefore);
}
}
else {
@@ -527,9 +407,8 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
frameInfo.getIncomingArgOffset(MachineCodeForMethod::get(Meth),
argNo);
- AdMI = cpMem2RegMI(getFramePointer(), offsetFromFP,
- UniLRReg, regType );
- FirstAI->InstrnsBefore.push_back( AdMI );
+ cpMem2RegMI(getFramePointer(), offsetFromFP, UniLRReg, regType,
+ FirstAI->InstrnsBefore);
}
} // if LR received a color
@@ -554,15 +433,13 @@ void UltraSparcRegInfo::colorMethodArgs(const Function *Meth,
assert(isVarArgs && regClassIDOfArgReg == IntRegClassID &&
"This should only be an Int register for an FP argument");
- AdMI = cpReg2MemMI(UniArgReg, getFramePointer(),
- LR->getSpillOffFromFP(), IntRegType );
+ cpReg2MemMI(UniArgReg, getFramePointer(), LR->getSpillOffFromFP(),
+ IntRegType, FirstAI->InstrnsBefore);
}
else {
- AdMI = cpReg2MemMI(UniArgReg, getFramePointer(),
- LR->getSpillOffFromFP(), regType );
+ cpReg2MemMI(UniArgReg, getFramePointer(), LR->getSpillOffFromFP(),
+ regType, FirstAI->InstrnsBefore);
}
-
- FirstAI->InstrnsBefore.push_back( AdMI );
}
else {
@@ -598,12 +475,10 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *CallMI,
std::vector<RegClass *> RCList) const {
assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) );
- // check if this is a varArgs function. needed for choosing regs.
- bool isVarArgs = isVarArgsCall(CallMI);
+ CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
suggestReg4CallAddr(CallMI, LRI, RCList);
-
// First color the return value of the call instruction. The return value
// will be in %o0 if the value is an integer type, or in %f0 if the
// value is a float type.
@@ -614,9 +489,7 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *CallMI,
// if type is not void, create a new live range and set its
// register class and add to LRI
-
- const Value *RetVal = getCallInstRetVal( CallMI );
-
+ const Value *RetVal = argDesc->getReturnValue();
if (RetVal) {
assert ((!LRI.getLiveRangeForValue(RetVal)) &&
@@ -644,16 +517,16 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *CallMI,
// the number of registers allocated for argument passing.
// Now, go thru call args - implicit operands of the call MI
- unsigned NumOfCallArgs = getCallInstNumArgs( CallMI );
+ unsigned NumOfCallArgs = argDesc->getNumArgs();
for(unsigned argNo=0, i=0, intArgNo=0, fpArgNo=0;
i < NumOfCallArgs; ++i, ++argNo) {
- const Value *CallArg = CallMI->getImplicitRef(i);
+ const Value *CallArg = argDesc->getArgInfo(i).getArgVal();
// get the LR of call operand (parameter)
LiveRange *const LR = LRI.getLiveRangeForValue(CallArg);
-
+
// not possible to have a null LR since all args (even consts)
// must be defined before
if (!LR) {
@@ -663,24 +536,137 @@ void UltraSparcRegInfo::suggestRegs4CallArgs(const MachineInstr *CallMI,
unsigned regType = getRegType( LR );
unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg (unused)
-
+
// Choose a register for this arg depending on whether it is
- // an INT or FP value, and if it is a varargs call
+ // an INT or FP value. Here we ignore whether or not it is a
+ // varargs calls, because FP arguments will be explicitly copied
+ // to an integer Value and handled under (argCopy != NULL) below.
int regNum = (regType == IntRegType)
- ? regNumForIntArg(false, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
- : regNumForFPArg(regType, false, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
+ ? regNumForIntArg(/*inCallee*/ false, /*isVarArgs*/ false,
+ argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
+ : regNumForFPArg(regType, /*inCallee*/ false, /*isVarArgs*/ false,
+ argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
// If a register could be allocated, use it.
// If not, do NOTHING as this will be colored as a normal value.
if(regNum != InvalidRegNum)
LR->setSuggestedColor(regNum);
+ // Repeat for the second copy of the argument, which would be
+ // an FP argument being passed to a function with no prototype
+ const Value *argCopy = argDesc->getArgInfo(i).getArgCopy();
+ if (argCopy != NULL)
+ {
+ assert(regType != IntRegType && argCopy->getType()->isIntegral()
+ && "Must be passing copy of FP argument in int register");
+ int copyRegNum = regNumForIntArg(/*inCallee*/false, /*isVarArgs*/false,
+ argNo, intArgNo, fpArgNo-1,
+ regClassIDOfArgReg);
+ assert(copyRegNum != InvalidRegNum);
+ LiveRange *const copyLR = LRI.getLiveRangeForValue(argCopy);
+ copyLR->setSuggestedColor(copyRegNum);
+ }
+
} // for all call arguments
}
//---------------------------------------------------------------------------
+// Helper method for UltraSparcRegInfo::colorCallArgs().
+//---------------------------------------------------------------------------
+
+void
+UltraSparcRegInfo::InitializeOutgoingArg(const MachineInstr* CallMI,
+ AddedInstrns *CallAI,
+ PhyRegAlloc &PRA, LiveRange* LR,
+ unsigned regType, unsigned RegClassID,
+ int UniArgRegOrNone, unsigned int argNo,
+ std::vector<MachineInstr *>& AddedInstrnsBefore)
+ const
+{
+ MachineInstr *AdMI;
+ bool isArgInReg = false;
+ unsigned UniArgReg = MAXINT; // unused unless initialized below
+ if (UniArgRegOrNone != InvalidRegNum)
+ {
+ isArgInReg = true;
+ UniArgReg = (unsigned) UniArgRegOrNone;
+ }
+
+ if (LR->hasColor()) {
+ unsigned UniLRReg = getUnifiedRegNum(RegClassID, LR->getColor());
+
+ // if LR received the correct color, nothing to do
+ if( isArgInReg && UniArgReg == UniLRReg )
+ return;
+
+ // The LR is allocated to a register UniLRReg and must be copied
+ // to UniArgReg or to the stack slot.
+ //
+ if( isArgInReg ) {
+ // Copy UniLRReg to UniArgReg
+ cpReg2RegMI(UniLRReg, UniArgReg, regType, AddedInstrnsBefore);
+ }
+ else {
+ // Copy UniLRReg to the stack to pass the arg on stack.
+ const MachineFrameInfo& frameInfo = target.getFrameInfo();
+ int argOffset = frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo);
+ cpReg2MemMI(UniLRReg, getStackPointer(), argOffset, regType,
+ CallAI->InstrnsBefore);
+ }
+
+ } else { // LR is not colored (i.e., spilled)
+
+ if( isArgInReg ) {
+ // Insert a load instruction to load the LR to UniArgReg
+ cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
+ UniArgReg, regType, AddedInstrnsBefore);
+ // Now add the instruction
+ }
+
+ else {
+ // Now, we have to pass the arg on stack. Since LR also did NOT
+ // receive a register we have to move an argument in memory to
+ // outgoing parameter on stack.
+ // Use TReg to load and store the value.
+ // Use TmpOff to save TReg, since that may have a live value.
+ //
+ int TReg = PRA.getUniRegNotUsedByThisInst( LR->getRegClass(), CallMI );
+ int TmpOff = PRA.mcInfo.pushTempValue(target,
+ getSpilledRegSize(getRegType(LR)));
+ const MachineFrameInfo& frameInfo = target.getFrameInfo();
+ int argOffset = frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo);
+
+ MachineInstr *Ad1, *Ad2, *Ad3, *Ad4;
+
+ // Sequence:
+ // (1) Save TReg on stack
+ // (2) Load LR value into TReg from stack pos of LR
+ // (3) Store Treg on outgoing Arg pos on stack
+ // (4) Load the old value of TReg from stack to TReg (restore it)
+ //
+ // OPTIMIZE THIS:
+ // When reverse pointers in MahineInstr are introduced:
+ // Call PRA.getUnusedRegAtMI(....) to get an unused reg. Step 1 is
+ // needed only if this fails. Currently, we cannot call the
+ // above method since we cannot find LVSetBefore without the BB
+ //
+ // NOTE: We directly add to CallAI->InstrnsBefore instead of adding to
+ // AddedInstrnsBefore since these instructions must not be reordered.
+ cpReg2MemMI(TReg, getFramePointer(), TmpOff, regType,
+ CallAI->InstrnsBefore);
+ cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(), TReg, regType,
+ CallAI->InstrnsBefore);
+ cpReg2MemMI(TReg, getStackPointer(), argOffset, regType,
+ CallAI->InstrnsBefore);
+ cpMem2RegMI(getFramePointer(), TmpOff, TReg, regType,
+ CallAI->InstrnsBefore);
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
// After graph coloring, we have call this method to see whehter the return
// value and the call args received the correct colors. If not, we have
// to instert copy instructions.
@@ -694,20 +680,22 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) );
+ CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
+
// First color the return value of the call.
// If there is a LR for the return value, it means this
// method returns a value
MachineInstr *AdMI;
- const Value *RetVal = getCallInstRetVal( CallMI );
+ const Value *RetVal = argDesc->getReturnValue();
if (RetVal) {
LiveRange *RetValLR = LRI.getLiveRangeForValue( RetVal );
if (!RetValLR) {
cerr << "\nNo LR for:" << RAV(RetVal) << "\n";
- assert(0 && "ERR:No LR for non-void return value");
+ assert(RetValLR && "ERR:No LR for non-void return value");
}
unsigned RegClassID = (RetValLR->getRegClass())->getID();
@@ -748,7 +736,7 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
// the return value is coming in UniRetReg but has to go into
// the UniRetLRReg
- AdMI = cpReg2RegMI( UniRetReg, UniRetLRReg, regType );
+ cpReg2RegMI(UniRetReg, UniRetLRReg, regType, CallAI->InstrnsAfter);
} // if LR has color
else {
@@ -756,12 +744,10 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
// if the LR did NOT receive a color, we have to move the return
// value coming in UniRetReg to the stack pos of spilled LR
- AdMI = cpReg2MemMI(UniRetReg, getFramePointer(),
- RetValLR->getSpillOffFromFP(), regType );
+ cpReg2MemMI(UniRetReg, getFramePointer(),RetValLR->getSpillOffFromFP(),
+ regType, CallAI->InstrnsAfter);
}
- CallAI->InstrnsAfter.push_back( AdMI );
-
} // the LR didn't receive the suggested color
} // if there a return value
@@ -772,190 +758,82 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
//-------------------------------------------
std::vector<MachineInstr *> AddedInstrnsBefore;
-
- unsigned NumOfCallArgs = getCallInstNumArgs( CallMI );
-
- bool isVarArgs = isVarArgsCall(CallMI);
- if (DEBUG_RA && isVarArgs) cerr << "\nVar arg call found!!\n";
-
+
+ unsigned NumOfCallArgs = argDesc->getNumArgs();
+
for(unsigned argNo=0, i=0, intArgNo=0, fpArgNo=0;
i < NumOfCallArgs; ++i, ++argNo) {
- const Value *CallArg = CallMI->getImplicitRef(i);
-
+ const Value *CallArg = argDesc->getArgInfo(i).getArgVal();
+
// get the LR of call operand (parameter)
LiveRange *const LR = LRI.getLiveRangeForValue(CallArg);
- unsigned regType = getRegType( CallArg );
unsigned RegClassID = getRegClassIDOfValue( CallArg);
+ unsigned regType = getRegType( RegClassID, CallArg->getType() );
- // find whether this argument is coming in a register (if not, on stack)
+ // Find whether this argument is coming in a register (if not, on stack)
// Also find the correct register the argument must use (UniArgReg)
//
bool isArgInReg = false;
- unsigned UniArgReg = InvalidRegNum; // reg that LR MUST be colored with
+ unsigned UniArgReg = InvalidRegNum; // reg that LR MUST be colored with
unsigned regClassIDOfArgReg = MAXINT; // reg class of chosen reg
+ // Find the register that must be used for this arg, depending on
+ // whether it is an INT or FP value. Here we ignore whether or not it
+ // is a varargs calls, because FP arguments will be explicitly copied
+ // to an integer Value and handled under (argCopy != NULL) below.
int regNum = (regType == IntRegType)
- ? regNumForIntArg(false, isVarArgs, argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
- : regNumForFPArg(regType, false, isVarArgs, argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
+ ? regNumForIntArg(/*inCallee*/ false, /*isVarArgs*/ false,
+ argNo, intArgNo++, fpArgNo, regClassIDOfArgReg)
+ : regNumForFPArg(regType, /*inCallee*/ false, /*isVarArgs*/ false,
+ argNo, intArgNo, fpArgNo++, regClassIDOfArgReg);
if(regNum != InvalidRegNum) {
isArgInReg = true;
UniArgReg = getUnifiedRegNum( regClassIDOfArgReg, regNum);
+ assert(regClassIDOfArgReg == RegClassID &&
+ "Moving values between reg classes must happen during selection");
}
// not possible to have a null LR since all args (even consts)
// must be defined before
if (!LR) {
cerr << " ERROR: In call instr, no LR for arg: " << RAV(CallArg) <<"\n";
- assert(0 && "NO LR for call arg");
+ assert(LR && "NO LR for call arg");
}
-
- if (LR->hasColor()) {
- unsigned UniLRReg = getUnifiedRegNum( RegClassID, LR->getColor() );
-
- // if LR received the correct color, nothing to do
- if( UniLRReg == UniArgReg )
- continue;
-
- // We are here because though the LR is allocated a register, it
- // was not allocated the suggested register. So, we have to copy %ix reg
- // (or stack pos of arg) to the register it was colored with
-
- // the LR is colored with UniLRReg but has to go into UniArgReg
- // to pass it as an argument
-
- if( isArgInReg ) {
-
- if( regClassIDOfArgReg != RegClassID ) {
- assert(0 &&
- "FP arguments to a varargs function should be explicitly "
- "copied to/from int registers by instruction selection!");
-
- // It must be a float arg for a variable argument call, which
- // must come in a %o reg.
- // We have to move a float reg to an int reg via memory.
- //
- assert(isVarArgs &&
- RegClassID == FloatRegClassID &&
- regClassIDOfArgReg == IntRegClassID &&
- "This should only be an Int register for an FP argument");
-
- // The store instruction will be directly added to
- // CallAI->InstrnsBefore since it does not need reordering
- //
- int TmpOff = PRA.mcInfo.pushTempValue(target,
- getSpilledRegSize(regType));
-
- AdMI = cpReg2MemMI(UniLRReg, getFramePointer(), TmpOff, regType );
- CallAI->InstrnsBefore.push_back( AdMI );
-
- AdMI = cpMem2RegMI(getFramePointer(), TmpOff, UniArgReg, IntRegType);
- AddedInstrnsBefore.push_back( AdMI );
- }
-
- else {
- AdMI = cpReg2RegMI(UniLRReg, UniArgReg, regType );
- AddedInstrnsBefore.push_back( AdMI );
- }
-
- } else {
- // Now, we have to pass the arg on stack. Since LR received a register
- // we just have to move that register to the stack position where
- // the argument must be passed
-
- const MachineFrameInfo& frameInfo = target.getFrameInfo();
- int argOffset =
- frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo);
-
- AdMI = cpReg2MemMI(UniLRReg, getStackPointer(), argOffset, regType );
-
- // Now add the instruction. We can directly add to
- // CallAI->InstrnsBefore since we are just saving a reg on stack
- //
- CallAI->InstrnsBefore.push_back( AdMI );
-
- //cerr << "\nCaution: Passing a reg on stack";
- }
-
-
- } else { // LR is not colored (i.e., spilled)
-
- if( isArgInReg ) {
-
- // Now the LR did NOT recieve a register but has a stack poistion.
- // Since, the outgoing arg goes in a register we just have to insert
- // a load instruction to load the LR to outgoing register
-
- if( regClassIDOfArgReg != RegClassID ) {
- assert(isVarArgs && regClassIDOfArgReg == IntRegClassID &&
- "This should only be an Int register for an FP argument");
-
- AdMI = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
- UniArgReg, IntRegType );
- }
- else
- AdMI = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
- UniArgReg, regType );
-
- cerr << "\nCaution: Loading a spilled val to a reg as a call arg";
- AddedInstrnsBefore.push_back( AdMI ); // Now add the instruction
- }
-
- else {
- // Now, we have to pass the arg on stack. Since LR also did NOT
- // receive a register we have to move an argument in memory to
- // outgoing parameter on stack.
-
- // Optimize: Optimize when reverse pointers in MahineInstr are
- // introduced.
- // call PRA.getUnusedRegAtMI(....) to get an unused reg. Only if this
- // fails, then use the following code. Currently, we cannot call the
- // above method since we cannot find LVSetBefore without the BB
-
- int TReg = PRA.getUniRegNotUsedByThisInst( LR->getRegClass(), CallMI );
-
- int TmpOff = PRA.mcInfo.pushTempValue(target,
- getSpilledRegSize(getRegType(LR)) );
-
-
- const MachineFrameInfo& frameInfo = target.getFrameInfo();
- int argOffset =
- frameInfo.getOutgoingArgOffset(PRA.mcInfo, argNo);
+
+ InitializeOutgoingArg(CallMI, CallAI, PRA, LR, regType, RegClassID,
+ UniArgReg, argNo, AddedInstrnsBefore);
+
+ // Repeat for the second copy of the argument, which would be
+ // an FP argument being passed to a function with no prototype.
+ const Value *argCopy = argDesc->getArgInfo(i).getArgCopy();
+ if (argCopy != NULL)
+ {
+ assert(regType != IntRegType && argCopy->getType()->isIntegral()
+ && "Must be passing copy of FP argument in int register");
- MachineInstr *Ad1, *Ad2, *Ad3, *Ad4;
+ unsigned copyRegClassID = getRegClassIDOfValue(argCopy);
+ unsigned copyRegType = getRegType(copyRegClassID, argCopy->getType());
- // Sequence:
- // (1) Save TReg on stack
- // (2) Load LR value into TReg from stack pos of LR
- // (3) Store Treg on outgoing Arg pos on stack
- // (4) Load the old value of TReg from stack to TReg (restore it)
-
- Ad1 = cpReg2MemMI(TReg, getFramePointer(), TmpOff, regType );
- Ad2 = cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
- TReg, regType );
- Ad3 = cpReg2MemMI(TReg, getStackPointer(), argOffset, regType );
- Ad4 = cpMem2RegMI(getFramePointer(), TmpOff, TReg, regType );
-
- // We directly add to CallAI->InstrnsBefore instead of adding to
- // AddedInstrnsBefore since these instructions must not be
- // reordered.
+ int copyRegNum = regNumForIntArg(/*inCallee*/false, /*isVarArgs*/false,
+ argNo, intArgNo, fpArgNo-1,
+ regClassIDOfArgReg);
+ assert(copyRegNum != InvalidRegNum);
+ assert(regClassIDOfArgReg == copyRegClassID &&
+ "Moving values between reg classes must happen during selection");
- CallAI->InstrnsBefore.push_back( Ad1 );
- CallAI->InstrnsBefore.push_back( Ad2 );
- CallAI->InstrnsBefore.push_back( Ad3 );
- CallAI->InstrnsBefore.push_back( Ad4 );
-
- cerr << "\nCaution: Call arg moved from stack2stack for: " << *CallMI ;
+ InitializeOutgoingArg(CallMI, CallAI, PRA,
+ LRI.getLiveRangeForValue(argCopy), copyRegType,
+ copyRegClassID, copyRegNum, argNo,
+ AddedInstrnsBefore);
}
- }
} // for each parameter in call instruction
-
- // if we added any instruction before the call instruction, verify
+ // If we added any instruction before the call instruction, verify
// that they are in the proper order and if not, reorder them
-
+ //
if (!AddedInstrnsBefore.empty()) {
if (DEBUG_RA) {
@@ -977,8 +855,7 @@ void UltraSparcRegInfo::colorCallArgs(const MachineInstr *CallMI,
for(unsigned i=0; i < TmpVec.size(); i++)
CallAI->InstrnsBefore.push_back( TmpVec[i] );
}
-
-
+
// now insert caller saving code for this call instruction
//
insertCallerSavingCode(CallMI, BB, PRA);
@@ -1076,13 +953,11 @@ void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI,
// the LR received UniLRReg but must be colored with UniRetReg
// to pass as the return value
- RetAI->InstrnsBefore.push_back(cpReg2RegMI(UniLRReg, UniRetReg, regType));
+ cpReg2RegMI(UniLRReg, UniRetReg, regType, RetAI->InstrnsBefore);
}
else { // if the LR is spilled
- MachineInstr *AdMI = cpMem2RegMI(getFramePointer(),
- LR->getSpillOffFromFP(),
- UniRetReg, regType);
- RetAI->InstrnsBefore.push_back(AdMI);
+ cpMem2RegMI(getFramePointer(), LR->getSpillOffFromFP(),
+ UniRetReg, regType, RetAI->InstrnsBefore);
cerr << "\nCopied the return value from stack\n";
}
@@ -1096,25 +971,30 @@ void UltraSparcRegInfo::colorRetValue(const MachineInstr *RetMI,
// register number
//---------------------------------------------------------------------------
-MachineInstr * UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg,
- unsigned DestReg,
- int RegType) const {
+void
+UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg,
+ unsigned DestReg,
+ int RegType,
+ vector<MachineInstr*>& mvec) const {
assert( ((int)SrcReg != InvalidRegNum) && ((int)DestReg != InvalidRegNum) &&
"Invalid Register");
MachineInstr * MI = NULL;
-
+
switch( RegType ) {
- case IntRegType:
case IntCCRegType:
case FloatCCRegType:
+ assert(0 && "This code was bogus and needs to be fixed!");
+ break;
+
+ case IntRegType:
MI = new MachineInstr(ADD, 3);
MI->SetMachineOperandReg(0, SrcReg, false);
MI->SetMachineOperandReg(1, this->getZeroRegNum(), false);
MI->SetMachineOperandReg(2, DestReg, true);
break;
-
+
case FPSingleRegType:
MI = new MachineInstr(FMOVS, 2);
MI->SetMachineOperandReg(0, SrcReg, false);
@@ -1128,10 +1008,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg,
break;
default:
- assert(0 && "Unknow RegType");
+ assert(0 && "Unknown RegType");
}
-
- return MI;
+
+ if (MI)
+ mvec.push_back(MI);
}
//---------------------------------------------------------------------------
@@ -1140,9 +1021,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2RegMI(unsigned SrcReg,
//---------------------------------------------------------------------------
-MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg,
- unsigned DestPtrReg,
- int Offset, int RegType) const {
+void
+UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg,
+ unsigned DestPtrReg,
+ int Offset, int RegType,
+ vector<MachineInstr*>& mvec) const {
MachineInstr * MI = NULL;
switch( RegType ) {
case IntRegType:
@@ -1174,10 +1057,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg,
assert( 0 && "Cannot directly store %ccr to memory");
default:
- assert(0 && "Unknow RegType in cpReg2MemMI");
+ assert(0 && "Unknown RegType in cpReg2MemMI");
}
- return MI;
+ if (MI)
+ mvec.push_back(MI);
}
@@ -1187,10 +1071,12 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(unsigned SrcReg,
//---------------------------------------------------------------------------
-MachineInstr * UltraSparcRegInfo::cpMem2RegMI(unsigned SrcPtrReg,
- int Offset,
- unsigned DestReg,
- int RegType) const {
+void
+UltraSparcRegInfo::cpMem2RegMI(unsigned SrcPtrReg,
+ int Offset,
+ unsigned DestReg,
+ int RegType,
+ vector<MachineInstr*>& mvec) const {
MachineInstr * MI = NULL;
switch (RegType) {
case IntRegType:
@@ -1226,20 +1112,21 @@ MachineInstr * UltraSparcRegInfo::cpMem2RegMI(unsigned SrcPtrReg,
assert(0 && "Unknown RegType in cpMem2RegMI");
}
- return MI;
+ if (MI)
+ mvec.push_back(MI);
}
-
-
-
//---------------------------------------------------------------------------
// Generate a copy instruction to copy a value to another. Temporarily
// used by PhiElimination code.
//---------------------------------------------------------------------------
-MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const {
+void
+UltraSparcRegInfo::cpValue2Value(Value *Src,
+ Value *Dest,
+ vector<MachineInstr*>& mvec) const {
int RegType = getRegType( Src );
assert( (RegType==getRegType(Src)) && "Src & Dest are diff types");
@@ -1271,7 +1158,8 @@ MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const {
assert(0 && "Unknow RegType in CpValu2Value");
}
- return MI;
+ if (MI)
+ mvec.push_back(MI);
}
@@ -1293,14 +1181,18 @@ MachineInstr *UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const {
//----------------------------------------------------------------------------
-void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
+void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *CallMI,
const BasicBlock *BB,
PhyRegAlloc &PRA) const {
+ assert ( (UltraSparcInfo->getInstrInfo()).isCall(CallMI->getOpCode()) );
+
// has set to record which registers were saved/restored
//
std::hash_set<unsigned> PushedRegSet;
+ CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
+
// Now find the LR of the return value of the call
// The last *implicit operand* is the return value of a call
// Insert it to to he PushedRegSet since we must not save that register
@@ -1309,8 +1201,7 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
// to determine, which LRs must be saved across calls. The return value
// of the call is live in this set - but we must not save/restore it.
-
- const Value *RetVal = getCallInstRetVal( MInst );
+ const Value *RetVal = argDesc->getReturnValue();
if (RetVal) {
LiveRange *RetValLR = PRA.LRI.getLiveRangeForValue( RetVal );
@@ -1323,7 +1214,7 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
}
- const ValueSet &LVSetAft = PRA.LVI->getLiveVarSetAfterMInst(MInst, BB);
+ const ValueSet &LVSetAft = PRA.LVI->getLiveVarSetAfterMInst(CallMI, BB);
ValueSet::const_iterator LIt = LVSetAft.begin();
// for each live var in live variable set after machine inst
@@ -1374,25 +1265,28 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
// push %ccr on to the stack
const ValueSet &LVSetBef =
- PRA.LVI->getLiveVarSetBeforeMInst(MInst, BB);
+ PRA.LVI->getLiveVarSetBeforeMInst(CallMI, BB);
// get a free INTEGER register
int FreeIntReg =
PRA.getUsableUniRegAtMI(PRA.getRegClassByID(IntRegClassID) /*LR->getRegClass()*/,
- IntRegType, MInst, &LVSetBef, AdIBefCC, AdIAftCC);
+ IntRegType, CallMI, &LVSetBef, AdIBefCC, AdIAftCC);
// insert the instructions in reverse order since we are
// adding them to the front of InstrnsBefore
-
+ AddedInstrns& addedI = PRA.AddedInstrMap[CallMI];
if(AdIAftCC)
- PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIAftCC);
-
+ addedI.InstrnsBefore.insert(addedI.InstrnsBefore.begin(),
+ AdIAftCC);
+
AdICpCC = cpCCR2IntMI(FreeIntReg);
- PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdICpCC);
-
+ addedI.InstrnsBefore.insert(addedI.InstrnsBefore.begin(),
+ AdICpCC);
+
if(AdIBefCC)
- PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIBefCC);
-
+ addedI.InstrnsBefore.insert(addedI.InstrnsBefore.begin(),
+ AdIBefCC);
+
if(DEBUG_RA) {
cerr << "\n!! Inserted caller saving (push) inst for %ccr:";
if(AdIBefCC) cerr << "\t" << *(AdIBefCC);
@@ -1402,8 +1296,8 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
} else {
// for any other register type, just add the push inst
- AdIBef = cpReg2MemMI(Reg, getFramePointer(), StackOff, RegType );
- PRA.AddedInstrMap[MInst].InstrnsBefore.push_front(AdIBef);
+ cpReg2MemMI(Reg, getFramePointer(), StackOff, RegType,
+ PRA.AddedInstrMap[CallMI].InstrnsBefore);
}
@@ -1417,16 +1311,16 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
// get a free INT register
int FreeIntReg =
PRA.getUsableUniRegAtMI(PRA.getRegClassByID(IntRegClassID) /* LR->getRegClass()*/,
- IntRegType, MInst, &LVSetAft, AdIBefCC, AdIAftCC);
+ IntRegType, CallMI, &LVSetAft, AdIBefCC, AdIAftCC);
if(AdIBefCC)
- PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIBefCC);
+ PRA.AddedInstrMap[CallMI].InstrnsAfter.push_back(AdIBefCC);
AdICpCC = cpInt2CCRMI(FreeIntReg);
- PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdICpCC);
+ PRA.AddedInstrMap[CallMI].InstrnsAfter.push_back(AdICpCC);
if(AdIAftCC)
- PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIAftCC);
+ PRA.AddedInstrMap[CallMI].InstrnsAfter.push_back(AdIAftCC);
if(DEBUG_RA) {
@@ -1438,14 +1332,14 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
} else {
// for any other register type, just add the pop inst
- AdIAft = cpMem2RegMI(getFramePointer(), StackOff, Reg, RegType );
- PRA.AddedInstrMap[MInst].InstrnsAfter.push_back(AdIAft);
+ cpMem2RegMI(getFramePointer(), StackOff, Reg, RegType,
+ PRA.AddedInstrMap[CallMI].InstrnsAfter);
}
PushedRegSet.insert(Reg);
if(DEBUG_RA) {
- cerr << "\nFor call inst:" << *MInst;
+ cerr << "\nFor call inst:" << *CallMI;
cerr << " -inserted caller saving instrs:\n\t ";
if( RegType == IntCCRegType ) {
if(AdIBefCC) cerr << *AdIBefCC << "\t";
@@ -1535,21 +1429,20 @@ void UltraSparcRegInfo::printReg(const LiveRange *LR) {
// The unordered instructions come in the UnordVec. These instructions are
// instructions inserted by RegAlloc. All such instruction MUST have
// their USES BEFORE THE DEFS after reordering.
-
+//
// The UnordVec & OrdVec must be DISTINCT. The OrdVec must be empty when
// this method is called.
-
+//
// This method uses two vectors for efficiency in accessing
-
+//
// Since instructions are inserted in RegAlloc, this assumes that the
// first operand is the source reg and the last operand is the dest reg.
-
+//
// All the uses are before THE def to a register
-
-
//---------------------------------------------------------------------------
-void UltraSparcRegInfo::OrderAddedInstrns(std::vector<MachineInstr *> &UnordVec,
- std::vector<MachineInstr *> &OrdVec,
+
+void UltraSparcRegInfo::OrderAddedInstrns(std::vector<MachineInstr*> &UnordVec,
+ std::vector<MachineInstr*> &OrdVec,
PhyRegAlloc &PRA) const{
/*
@@ -1719,9 +1612,12 @@ void UltraSparcRegInfo::moveInst2OrdVec(std::vector<MachineInstr *> &OrdVec,
getSpilledRegSize(RegType));
// Save the UReg (%ox) on stack before it's destroyed
- AdIBef=cpReg2MemMI(UReg, getFramePointer(), StackOff, RegType);
- OrdIt = OrdVec.insert( OrdIt, AdIBef);
- OrdIt++; // points to current instr we processed
+ vector<MachineInstr*> mvec;
+ cpReg2MemMI(UReg, getFramePointer(), StackOff, RegType, mvec);
+ for (vector<MachineInstr*>::iterator MI=mvec.begin(); MI != mvec.end(); ++MI) {
+ OrdIt = OrdVec.insert(OrdIt, *MI);
+ ++OrdIt; // OrdIt must still point to current instr we processed
+ }
// Load directly into DReg (%oy)
MachineOperand& DOp=
@@ -1729,8 +1625,7 @@ void UltraSparcRegInfo::moveInst2OrdVec(std::vector<MachineInstr *> &OrdVec,
assert(DOp.opIsDef() && "Last operand is not the def");
const int DReg = DOp.getMachineRegNum();
- AdIAft=cpMem2RegMI(getFramePointer(), StackOff, DReg, RegType);
- OrdVec.push_back(AdIAft);
+ cpMem2RegMI(getFramePointer(), StackOff, DReg, RegType, OrdVec);
cerr << "\nFixed CIRCULAR references by reordering";