diff options
author | Vikram S. Adve <vadve@cs.uiuc.edu> | 2002-05-19 15:25:51 +0000 |
---|---|---|
committer | Vikram S. Adve <vadve@cs.uiuc.edu> | 2002-05-19 15:25:51 +0000 |
commit | 242a8086aa6ccb29990aaf0c7a591003987330f1 (patch) | |
tree | 3d43c025cd8a41780f72c009756961c2a6233b9e /lib/Target | |
parent | 78771c886ad18e01859feb4dab8559ab5db464b9 (diff) | |
download | external_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.cpp | 21 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9InstrInfo.cpp | 297 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9InstrSelection.cpp | 615 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9InstrSelectionSupport.h | 27 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9Internals.h | 123 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegClassInfo.cpp | 55 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegClassInfo.h | 20 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9RegInfo.cpp | 733 |
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"; |