diff options
Diffstat (limited to 'llvm/lib/Target/Sparc/SparcInstrInfo.cpp')
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.cpp | 297 |
1 files changed, 212 insertions, 85 deletions
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp index fd18841dc18..5fbced0f9f1 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.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); } |

