diff options
-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 868f8710d8..74b7f73da3 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 fd18841dc1..5fbced0f9f 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 7109ba4a35..668ac4a566 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, |