Remove diff-cluttering tags
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9InstrInfo.cpp
1 //***************************************************************************
2 // File:
3 //      SparcInstrInfo.cpp
4 // 
5 // Purpose:
6 //      
7 // History:
8 //      10/15/01         -  Vikram Adve  -  Created
9 //**************************************************************************/
10
11
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"
24 using std::vector;
25
26 //************************ Internal Functions ******************************/
27
28
29 static inline void
30 CreateIntSetInstruction(const TargetMachine& target, Function* F,
31                         int64_t C, Instruction* dest,
32                         std::vector<MachineInstr*>& mvec,
33                         MachineCodeForInstruction& mcfi)
34 {
35   assert(dest->getType()->isSigned() && "Use CreateUIntSetInstruction()");
36   
37   MachineInstr* M;
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);
42       mcfi.addTemp(tmpReg);
43       
44       M = new MachineInstr(SETX);
45       M->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
46       M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
47                                  /*isdef*/ true);
48       M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
49       mvec.push_back(M);
50     }
51   else
52     {
53       M = Create2OperandInstr_SImmed(SETSW, C, dest);
54       mvec.push_back(M);
55     }
56 }
57
58 static inline void
59 CreateUIntSetInstruction(const TargetMachine& target, Function* F,
60                          uint64_t C, Instruction* dest,
61                          std::vector<MachineInstr*>& mvec,
62                          MachineCodeForInstruction& mcfi)
63 {
64   assert(! dest->getType()->isSigned() && "Use CreateIntSetInstruction()");
65   unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
66   MachineInstr* M;
67   
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);
72       mcfi.addTemp(tmpReg);
73       
74       M = new MachineInstr(SETX);
75       M->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
76       M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
77                               /*isdef*/ true);
78       M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
79       mvec.push_back(M);
80     }
81   else
82     {
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.
86       // 
87       Value* setuwDest = dest;
88       if (destSize < target.DataLayout.getIntegerRegize())
89         {
90           setuwDest = new TmpInstruction(dest, NULL, "setTmp");
91           mcfi.addTemp(setuwDest);
92         }
93       
94       M = Create2OperandInstr_UImmed(SETUW, C, setuwDest);
95       mvec.push_back(M);
96       
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,
104                                             mvec, mcfi);
105         }
106     }
107   
108 #define USE_DIRECT_SIGN_EXTENSION_INSTRS
109 #ifndef USE_DIRECT_SIGN_EXTENSION_INSTRS
110   else
111     { // cast to signed type of the right length and use signed op (SETSW)
112       // to get correct sign extension
113       // 
114       minstr = new MachineInstr(SETSW);
115       minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
116       
117       switch (dest->getType()->getPrimitiveID())
118         {
119         case Type::UIntTyID:
120           minstr->SetMachineOperandConst(0,
121                                          MachineOperand::MO_SignExtendedImmed,
122                                          (int) C);
123           break;
124         case Type::UShortTyID:
125           minstr->SetMachineOperandConst(0,
126                                          MachineOperand::MO_SignExtendedImmed,
127                                          (short) C);
128           break;
129         case Type::UByteTyID:
130           minstr->SetMachineOperandConst(0,
131                                          MachineOperand::MO_SignExtendedImmed,
132                                          (char) C);
133           break;
134         default:
135           assert(0 && "Unexpected unsigned type");
136           break;
137         }
138     }
139 #endif USE_DIRECT_SIGN_EXTENSION_INSTRS
140 }
141
142 //************************* External Classes *******************************/
143
144 //---------------------------------------------------------------------------
145 // class UltraSparcInstrInfo 
146 // 
147 // Purpose:
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 //---------------------------------------------------------------------------
153
154 /*ctor*/
155 UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
156   : MachineInstrInfo(tgt, SparcMachineInstrDesc,
157                      /*descSize = */ NUM_TOTAL_OPCODES,
158                      /*numRealOpCodes = */ NUM_REAL_OPCODES)
159 {
160 }
161
162 // 
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.
169 // 
170 void
171 UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
172                                            Function* F,
173                                            Value* val,
174                                            Instruction* dest,
175                                            std::vector<MachineInstr*>& mvec,
176                                        MachineCodeForInstruction& mcfi) const
177 {
178   assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
179          "I only know about constant values and global addresses");
180   
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.
184   // 
185   const Type* valType = val->getType();
186   
187   if (valType->isIntegral() || valType == Type::BoolTy)
188     {
189       if (! val->getType()->isSigned())
190         {
191           uint64_t C = cast<ConstantUInt>(val)->getValue();
192           CreateUIntSetInstruction(target, F, C, dest, mvec, mcfi);
193         }
194       else
195         {
196           bool isValidConstant;
197           int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
198           assert(isValidConstant && "Unrecognized constant");
199           CreateIntSetInstruction(target, F, C, dest, mvec, mcfi);
200         }
201     }
202   else
203     {
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.
209       
210       Value* addrVal;
211       int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
212       
213       TmpInstruction* tmpReg =
214         new TmpInstruction(PointerType::get(val->getType()), val);
215       mcfi.addTemp(tmpReg);
216       
217       if (isa<Constant>(val))
218         {
219           // Create another TmpInstruction for the hidden integer register
220           TmpInstruction* addrReg =
221             new TmpInstruction(PointerType::get(val->getType()), val);
222           mcfi.addTemp(addrReg);
223           addrVal = addrReg;
224         }
225       else
226         addrVal = dest;
227       
228       MachineInstr* M = new MachineInstr(SETX);
229       M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
230       M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
231                               /*isdef*/ true);
232       M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, addrVal);
233       mvec.push_back(M);
234       
235       if (isa<Constant>(val))
236         {
237           // Make sure constant is emitted to constant pool in assembly code.
238           MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
239           
240           // Generate the load instruction
241           M = Create3OperandInstr_SImmed(ChooseLoadInstruction(val->getType()),
242                                          addrVal, zeroOffset, dest);
243           mvec.push_back(M);
244         }
245     }
246 }
247
248
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.
255 // 
256 void
257 UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
258                                         Function* F,
259                                         Value* val,
260                                         Instruction* dest,
261                                         std::vector<MachineInstr*>& mvec,
262                                         MachineCodeForInstruction& mcfi) const
263 {
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");
268   
269   int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
270   
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.
276   // 
277   Type* tmpType = (dest->getType() == Type::FloatTy)? Type::IntTy
278                                                     : Type::LongTy;
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);
284
285   // Load instruction loads [%fp+offset] to `dest'.
286   // 
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);
292 }
293
294
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.
300 // 
301 void
302 UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
303                                         Function* F,
304                                         Value* val,
305                                         Instruction* dest,
306                                         std::vector<MachineInstr*>& mvec,
307                                         MachineCodeForInstruction& mcfi) const
308 {
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");
313   
314   int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
315   
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.
320   // 
321   Type* tmpType = (val->getType() == Type::FloatTy)? Type::IntTy
322                                                    : Type::LongTy;
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);
328   
329   // Load instruction loads [%fp+offset] to `dest'.
330   // 
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);
336 }
337
338
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.
343 // 
344 void
345 UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
346                                                   Function *F,
347                                                   Value* src,
348                                                   Instruction* dest,
349                                                   vector<MachineInstr*>& mvec,
350                                           MachineCodeForInstruction& mcfi) const
351 {
352   bool loadConstantToReg = false;
353   
354   const Type* resultType = dest->getType();
355   
356   MachineOpCode opCode = ChooseAddInstructionByType(resultType);
357   if (opCode == INVALID_OPCODE)
358     {
359       assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
360       return;
361     }
362   
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
366   // 
367   if (isa<Constant>(src))
368     {
369       unsigned int machineRegNum;
370       int64_t immedValue;
371       MachineOperand::MachineOperandType opType =
372         ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
373                          machineRegNum, immedValue);
374       
375       if (opType == MachineOperand::MO_VirtualRegister)
376         loadConstantToReg = true;
377     }
378   else if (isa<GlobalValue>(src))
379     loadConstantToReg = true;
380   
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,
385                                                   mvec, mcfi);
386     }
387   else
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.
391       // 
392       const Type* zeroValueType =
393         isa<PointerType>(resultType) ? Type::ULongTy : resultType;
394       MachineInstr* minstr =
395         Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
396                             src, dest);
397       mvec.push_back(minstr);
398     }
399 }
400
401
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.
408 // 
409 void
410 UltraSparcInstrInfo::CreateSignExtensionInstructions(
411                                         const TargetMachine& target,
412                                         Function* F,
413                                         Value* unsignedSrcVal,
414                                         unsigned int srcSizeInBits,
415                                         Value* dest,
416                                         vector<MachineInstr*>& mvec,
417                                         MachineCodeForInstruction& mcfi) const
418 {
419   MachineInstr* M;
420   
421   assert(srcSizeInBits > 0 && srcSizeInBits <= 32
422      && "Hmmm... srcSizeInBits > 32 unexpected but could be handled here.");
423   
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");
428       mcfi.addTemp(tmpI);
429       M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
430       mvec.push_back(M);
431       unsignedSrcVal = tmpI;
432     }
433   
434   M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);
435   mvec.push_back(M);
436 }