1 //***************************************************************************
8 // 10/15/01 - Vikram Adve - Created
9 //**************************************************************************/
12 #include "SparcInternals.h"
13 #include "SparcInstrSelectionSupport.h"
14 #include "llvm/Target/Sparc.h"
15 #include "llvm/CodeGen/InstrSelection.h"
16 #include "llvm/CodeGen/InstrSelectionSupport.h"
17 #include "llvm/CodeGen/MachineCodeForMethod.h"
18 #include "llvm/CodeGen/MachineCodeForInstruction.h"
19 #include "llvm/Function.h"
20 #include "llvm/BasicBlock.h"
21 #include "llvm/Instruction.h"
22 #include "llvm/Constants.h"
23 #include "llvm/DerivedTypes.h"
26 //************************ Internal Functions ******************************/
30 CreateIntSetInstruction(const TargetMachine& target, Function* F,
31 int64_t C, Instruction* dest,
32 std::vector<MachineInstr*>& mvec,
33 MachineCodeForInstruction& mcfi)
35 assert(dest->getType()->isSigned() && "Use CreateUIntSetInstruction()");
38 uint64_t absC = (C >= 0)? C : -C;
39 if (absC > (unsigned int) ~0)
40 { // C does not fit in 32 bits
41 TmpInstruction* tmpReg = new TmpInstruction(Type::IntTy);
44 M = new MachineInstr(SETX);
45 M->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
46 M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
48 M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
53 M = Create2OperandInstr_SImmed(SETSW, C, dest);
59 CreateUIntSetInstruction(const TargetMachine& target, Function* F,
60 uint64_t C, Instruction* dest,
61 std::vector<MachineInstr*>& mvec,
62 MachineCodeForInstruction& mcfi)
64 assert(! dest->getType()->isSigned() && "Use CreateIntSetInstruction()");
65 unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
68 if (C > (unsigned int) ~0)
69 { // C does not fit in 32 bits
70 assert(dest->getType() == Type::ULongTy && "Sign extension problems");
71 TmpInstruction *tmpReg = new TmpInstruction(Type::IntTy);
74 M = new MachineInstr(SETX);
75 M->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
76 M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
78 M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
83 // If the destination is smaller than the standard integer reg. size,
84 // we have to extend the sign-bit into upper bits of dest, so we
85 // need to put the result of the SETUW into a temporary.
87 Value* setuwDest = dest;
88 if (destSize < target.DataLayout.getIntegerRegize())
90 setuwDest = new TmpInstruction(dest, NULL, "setTmp");
91 mcfi.addTemp(setuwDest);
94 M = Create2OperandInstr_UImmed(SETUW, C, setuwDest);
97 if (setuwDest != dest)
98 { // extend the sign-bit of the result into all upper bits of dest
99 assert(8*destSize <= 32 &&
100 "Unexpected type size > 4 and < IntRegSize?");
101 target.getInstrInfo().
102 CreateSignExtensionInstructions(target, F,
103 setuwDest, 8*destSize, dest,
108 #define USE_DIRECT_SIGN_EXTENSION_INSTRS
109 #ifndef USE_DIRECT_SIGN_EXTENSION_INSTRS
111 { // cast to signed type of the right length and use signed op (SETSW)
112 // to get correct sign extension
114 minstr = new MachineInstr(SETSW);
115 minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
117 switch (dest->getType()->getPrimitiveID())
120 minstr->SetMachineOperandConst(0,
121 MachineOperand::MO_SignExtendedImmed,
124 case Type::UShortTyID:
125 minstr->SetMachineOperandConst(0,
126 MachineOperand::MO_SignExtendedImmed,
129 case Type::UByteTyID:
130 minstr->SetMachineOperandConst(0,
131 MachineOperand::MO_SignExtendedImmed,
135 assert(0 && "Unexpected unsigned type");
139 #endif USE_DIRECT_SIGN_EXTENSION_INSTRS
142 //************************* External Classes *******************************/
144 //---------------------------------------------------------------------------
145 // class UltraSparcInstrInfo
148 // Information about individual instructions.
149 // Most information is stored in the SparcMachineInstrDesc array above.
150 // Other information is computed on demand, and most such functions
151 // default to member functions in base class MachineInstrInfo.
152 //---------------------------------------------------------------------------
155 UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
156 : MachineInstrInfo(tgt, SparcMachineInstrDesc,
157 /*descSize = */ NUM_TOTAL_OPCODES,
158 /*numRealOpCodes = */ NUM_REAL_OPCODES)
163 // Create an instruction sequence to put the constant `val' into
164 // the virtual register `dest'. `val' may be a Constant or a
165 // GlobalValue, viz., the constant address of a global variable or function.
166 // The generated instructions are returned in `mvec'.
167 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
168 // Any stack space required is allocated via MachineCodeForMethod.
171 UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
175 std::vector<MachineInstr*>& mvec,
176 MachineCodeForInstruction& mcfi) const
178 assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
179 "I only know about constant values and global addresses");
181 // Use a "set" instruction for known constants that can go in an integer reg.
182 // Use a "load" instruction for all other constants, in particular,
183 // floating point constants and addresses of globals.
185 const Type* valType = val->getType();
187 if (valType->isIntegral() || valType == Type::BoolTy)
189 if (! val->getType()->isSigned())
191 uint64_t C = cast<ConstantUInt>(val)->getValue();
192 CreateUIntSetInstruction(target, F, C, dest, mvec, mcfi);
196 bool isValidConstant;
197 int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
198 assert(isValidConstant && "Unrecognized constant");
199 CreateIntSetInstruction(target, F, C, dest, mvec, mcfi);
204 // Make an instruction sequence to load the constant, viz:
205 // SETX <addr-of-constant>, tmpReg, addrReg
206 // LOAD /*addr*/ addrReg, /*offset*/ 0, dest
207 // Only the SETX is needed if `val' is a GlobalValue, i.e,. it is
208 // itself a constant address. Otherwise, both are needed.
211 int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
213 TmpInstruction* tmpReg =
214 new TmpInstruction(PointerType::get(val->getType()), val);
215 mcfi.addTemp(tmpReg);
217 if (isa<Constant>(val))
219 // Create another TmpInstruction for the hidden integer register
220 TmpInstruction* addrReg =
221 new TmpInstruction(PointerType::get(val->getType()), val);
222 mcfi.addTemp(addrReg);
228 MachineInstr* M = new MachineInstr(SETX);
229 M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
230 M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
232 M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, addrVal);
235 if (isa<Constant>(val))
237 // Make sure constant is emitted to constant pool in assembly code.
238 MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
240 // Generate the load instruction
241 M = Create3OperandInstr_SImmed(ChooseLoadInstruction(val->getType()),
242 addrVal, zeroOffset, dest);
249 // Create an instruction sequence to copy an integer value `val'
250 // to a floating point value `dest' by copying to memory and back.
251 // val must be an integral type. dest must be a Float or Double.
252 // The generated instructions are returned in `mvec'.
253 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
254 // Any stack space required is allocated via MachineCodeForMethod.
257 UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
261 std::vector<MachineInstr*>& mvec,
262 MachineCodeForInstruction& mcfi) const
264 assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
265 && "Source type must be integral");
266 assert(dest->getType()->isFloatingPoint()
267 && "Dest type must be float/double");
269 int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
271 // Store instruction stores `val' to [%fp+offset].
272 // The store and load opCodes are based on the value being copied, and
273 // they use integer and float types that accomodate the
274 // larger of the source type and the destination type:
275 // On SparcV9: int for float, long for double.
277 Type* tmpType = (dest->getType() == Type::FloatTy)? Type::IntTy
279 MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
280 store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
281 store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
282 store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
283 mvec.push_back(store);
285 // Load instruction loads [%fp+offset] to `dest'.
287 MachineInstr* load =new MachineInstr(ChooseLoadInstruction(dest->getType()));
288 load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
289 load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
290 load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
291 mvec.push_back(load);
295 // Similarly, create an instruction sequence to copy an FP value
296 // `val' to an integer value `dest' by copying to memory and back.
297 // The generated instructions are returned in `mvec'.
298 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
299 // Any stack space required is allocated via MachineCodeForMethod.
302 UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
306 std::vector<MachineInstr*>& mvec,
307 MachineCodeForInstruction& mcfi) const
309 assert(val->getType()->isFloatingPoint()
310 && "Source type must be float/double");
311 assert((dest->getType()->isIntegral() || isa<PointerType>(dest->getType()))
312 && "Dest type must be integral");
314 int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
316 // Store instruction stores `val' to [%fp+offset].
317 // The store and load opCodes are based on the value being copied, and
318 // they use the integer type that matches the source type in size:
319 // On SparcV9: int for float, long for double.
321 Type* tmpType = (val->getType() == Type::FloatTy)? Type::IntTy
323 MachineInstr* store=new MachineInstr(ChooseStoreInstruction(val->getType()));
324 store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
325 store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
326 store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
327 mvec.push_back(store);
329 // Load instruction loads [%fp+offset] to `dest'.
331 MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
332 load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
333 load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
334 load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
335 mvec.push_back(load);
339 // Create instruction(s) to copy src to dest, for arbitrary types
340 // The generated instructions are returned in `mvec'.
341 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
342 // Any stack space required is allocated via MachineCodeForMethod.
345 UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
349 vector<MachineInstr*>& mvec,
350 MachineCodeForInstruction& mcfi) const
352 bool loadConstantToReg = false;
354 const Type* resultType = dest->getType();
356 MachineOpCode opCode = ChooseAddInstructionByType(resultType);
357 if (opCode == INVALID_OPCODE)
359 assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
363 // if `src' is a constant that doesn't fit in the immed field or if it is
364 // a global variable (i.e., a constant address), generate a load
365 // instruction instead of an add
367 if (isa<Constant>(src))
369 unsigned int machineRegNum;
371 MachineOperand::MachineOperandType opType =
372 ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
373 machineRegNum, immedValue);
375 if (opType == MachineOperand::MO_VirtualRegister)
376 loadConstantToReg = true;
378 else if (isa<GlobalValue>(src))
379 loadConstantToReg = true;
381 if (loadConstantToReg)
382 { // `src' is constant and cannot fit in immed field for the ADD
383 // Insert instructions to "load" the constant into a register
384 target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
388 { // Create an add-with-0 instruction of the appropriate type.
389 // Make `src' the second operand, in case it is a constant
390 // Use (unsigned long) 0 for a NULL pointer value.
392 const Type* zeroValueType =
393 isa<PointerType>(resultType) ? Type::ULongTy : resultType;
394 MachineInstr* minstr =
395 Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
397 mvec.push_back(minstr);
402 // Create instruction sequence to produce a sign-extended register value
403 // from an arbitrary sized value (sized in bits, not bytes).
404 // For SPARC v9, we sign-extend the given unsigned operand using SLL; SRA.
405 // The generated instructions are returned in `mvec'.
406 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
407 // Any stack space required is allocated via MachineCodeForMethod.
410 UltraSparcInstrInfo::CreateSignExtensionInstructions(
411 const TargetMachine& target,
413 Value* unsignedSrcVal,
414 unsigned int srcSizeInBits,
416 vector<MachineInstr*>& mvec,
417 MachineCodeForInstruction& mcfi) const
421 assert(srcSizeInBits > 0 && srcSizeInBits <= 32
422 && "Hmmm... srcSizeInBits > 32 unexpected but could be handled here.");
424 if (srcSizeInBits < 32)
425 { // SLL is needed since operand size is < 32 bits.
426 TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
427 unsignedSrcVal, dest,"make32");
429 M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
431 unsignedSrcVal = tmpI;
434 M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);