Numerous bug fixes:
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9InstrInfo.cpp
1 // $Id$
2 //***************************************************************************
3 // File:
4 //      SparcInstrInfo.cpp
5 // 
6 // Purpose:
7 //      
8 // History:
9 //      10/15/01         -  Vikram Adve  -  Created
10 //**************************************************************************/
11
12
13 #include "SparcInternals.h"
14 #include "SparcInstrSelectionSupport.h"
15 #include "llvm/Target/Sparc.h"
16 #include "llvm/CodeGen/InstrSelection.h"
17 #include "llvm/CodeGen/InstrSelectionSupport.h"
18 #include "llvm/CodeGen/MachineCodeForMethod.h"
19 #include "llvm/CodeGen/MachineCodeForInstruction.h"
20 #include "llvm/Function.h"
21 #include "llvm/BasicBlock.h"
22 #include "llvm/Instruction.h"
23 #include "llvm/Constants.h"
24 #include "llvm/DerivedTypes.h"
25
26
27 //************************ Internal Functions ******************************/
28
29
30 static inline void
31 CreateIntSetInstruction(const TargetMachine& target, Function* F,
32                         int64_t C, Instruction* dest,
33                         std::vector<MachineInstr*>& mvec,
34                         MachineCodeForInstruction& mcfi)
35 {
36   assert(dest->getType()->isSigned() && "Use CreateUIntSetInstruction()");
37   
38   MachineInstr* M;
39   uint64_t absC = (C >= 0)? C : -C;
40   if (absC > (unsigned int) ~0)
41     { // C does not fit in 32 bits
42       TmpInstruction* tmpReg = new TmpInstruction(Type::IntTy);
43       mcfi.addTemp(tmpReg);
44       
45       M = new MachineInstr(SETX);
46       M->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
47       M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
48                                  /*isdef*/ true);
49       M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
50       mvec.push_back(M);
51     }
52   else
53     {
54       M = Create2OperandInstr_SImmed(SETSW, C, dest);
55       mvec.push_back(M);
56     }
57 }
58
59 static inline void
60 CreateUIntSetInstruction(const TargetMachine& target, Function* F,
61                          uint64_t C, Instruction* dest,
62                          std::vector<MachineInstr*>& mvec,
63                          MachineCodeForInstruction& mcfi)
64 {
65   assert(! dest->getType()->isSigned() && "Use CreateIntSetInstruction()");
66   unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
67   MachineInstr* M;
68   
69   if (C > (unsigned int) ~0)
70     { // C does not fit in 32 bits
71       assert(dest->getType() == Type::ULongTy && "Sign extension problems");
72       TmpInstruction *tmpReg = new TmpInstruction(Type::IntTy);
73       mcfi.addTemp(tmpReg);
74       
75       M = new MachineInstr(SETX);
76       M->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
77       M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
78                               /*isdef*/ true);
79       M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
80       mvec.push_back(M);
81     }
82   else
83     {
84       // If the destination is smaller than the standard integer reg. size,
85       // we have to extend the sign-bit into upper bits of dest, so we
86       // need to put the result of the SETUW into a temporary.
87       // 
88       Value* setuwDest = dest;
89       if (destSize < target.DataLayout.getIntegerRegize())
90         {
91           setuwDest = new TmpInstruction(dest, NULL, "setTmp");
92           mcfi.addTemp(setuwDest);
93         }
94       
95       M = Create2OperandInstr_UImmed(SETUW, C, setuwDest);
96       mvec.push_back(M);
97       
98       if (setuwDest != dest)
99         { // extend the sign-bit of the result into all upper bits of dest
100           assert(8*destSize <= 32 &&
101                  "Unexpected type size > 4 and < IntRegSize?");
102           target.getInstrInfo().
103             CreateSignExtensionInstructions(target, F,
104                                             setuwDest, 8*destSize, dest,
105                                             mvec, mcfi);
106         }
107     }
108   
109 #define USE_DIRECT_SIGN_EXTENSION_INSTRS
110 #ifndef USE_DIRECT_SIGN_EXTENSION_INSTRS
111   else
112     { // cast to signed type of the right length and use signed op (SETSW)
113       // to get correct sign extension
114       // 
115       minstr = new MachineInstr(SETSW);
116       minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
117       
118       switch (dest->getType()->getPrimitiveID())
119         {
120         case Type::UIntTyID:
121           minstr->SetMachineOperandConst(0,
122                                          MachineOperand::MO_SignExtendedImmed,
123                                          (int) C);
124           break;
125         case Type::UShortTyID:
126           minstr->SetMachineOperandConst(0,
127                                          MachineOperand::MO_SignExtendedImmed,
128                                          (short) C);
129           break;
130         case Type::UByteTyID:
131           minstr->SetMachineOperandConst(0,
132                                          MachineOperand::MO_SignExtendedImmed,
133                                          (char) C);
134           break;
135         default:
136           assert(0 && "Unexpected unsigned type");
137           break;
138         }
139     }
140 #endif USE_DIRECT_SIGN_EXTENSION_INSTRS
141 }
142
143 //************************* External Classes *******************************/
144
145 //---------------------------------------------------------------------------
146 // class UltraSparcInstrInfo 
147 // 
148 // Purpose:
149 //   Information about individual instructions.
150 //   Most information is stored in the SparcMachineInstrDesc array above.
151 //   Other information is computed on demand, and most such functions
152 //   default to member functions in base class MachineInstrInfo. 
153 //---------------------------------------------------------------------------
154
155 /*ctor*/
156 UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
157   : MachineInstrInfo(tgt, SparcMachineInstrDesc,
158                      /*descSize = */ NUM_TOTAL_OPCODES,
159                      /*numRealOpCodes = */ NUM_REAL_OPCODES)
160 {
161 }
162
163 // 
164 // Create an instruction sequence to put the constant `val' into
165 // the virtual register `dest'.  `val' may be a Constant or a
166 // GlobalValue, viz., the constant address of a global variable or function.
167 // The generated instructions are returned in `mvec'.
168 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
169 // Any stack space required is allocated via MachineCodeForMethod.
170 // 
171 void
172 UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
173                                            Function* F,
174                                            Value* val,
175                                            Instruction* dest,
176                                            std::vector<MachineInstr*>& mvec,
177                                        MachineCodeForInstruction& mcfi) const
178 {
179   assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
180          "I only know about constant values and global addresses");
181   
182   // Use a "set" instruction for known constants that can go in an integer reg.
183   // Use a "load" instruction for all other constants, in particular,
184   // floating point constants and addresses of globals.
185   // 
186   const Type* valType = val->getType();
187   
188   if (valType->isIntegral() || valType == Type::BoolTy)
189     {
190       if (! val->getType()->isSigned())
191         {
192           uint64_t C = cast<ConstantUInt>(val)->getValue();
193           CreateUIntSetInstruction(target, F, C, dest, mvec, mcfi);
194         }
195       else
196         {
197           bool isValidConstant;
198           int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
199           assert(isValidConstant && "Unrecognized constant");
200           CreateIntSetInstruction(target, F, C, dest, mvec, mcfi);
201         }
202     }
203   else
204     {
205       // Make an instruction sequence to load the constant, viz:
206       //            SETX <addr-of-constant>, tmpReg, addrReg
207       //            LOAD  /*addr*/ addrReg, /*offset*/ 0, dest
208       // Only the SETX is needed if `val' is a GlobalValue, i.e,. it is
209       // itself a constant address.  Otherwise, both are needed.
210       
211       Value* addrVal;
212       int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
213       
214       TmpInstruction* tmpReg =
215         new TmpInstruction(PointerType::get(val->getType()), val);
216       mcfi.addTemp(tmpReg);
217       
218       if (isa<Constant>(val))
219         {
220           // Create another TmpInstruction for the hidden integer register
221           TmpInstruction* addrReg =
222             new TmpInstruction(PointerType::get(val->getType()), val);
223           mcfi.addTemp(addrReg);
224           addrVal = addrReg;
225         }
226       else
227         addrVal = dest;
228       
229       MachineInstr* M = new MachineInstr(SETX);
230       M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
231       M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
232                               /*isdef*/ true);
233       M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, addrVal);
234       mvec.push_back(M);
235       
236       if (isa<Constant>(val))
237         {
238           // Make sure constant is emitted to constant pool in assembly code.
239           MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
240           
241           // Generate the load instruction
242           M = Create3OperandInstr_SImmed(ChooseLoadInstruction(val->getType()),
243                                          addrVal, zeroOffset, dest);
244           mvec.push_back(M);
245         }
246     }
247 }
248
249
250 // Create an instruction sequence to copy an integer value `val'
251 // to a floating point value `dest' by copying to memory and back.
252 // val must be an integral type.  dest must be a Float or Double.
253 // The generated instructions are returned in `mvec'.
254 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
255 // Any stack space required is allocated via MachineCodeForMethod.
256 // 
257 void
258 UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
259                                         Function* F,
260                                         Value* val,
261                                         Instruction* dest,
262                                         std::vector<MachineInstr*>& mvec,
263                                         MachineCodeForInstruction& mcfi) const
264 {
265   assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
266          && "Source type must be integral");
267   assert(dest->getType()->isFloatingPoint()
268          && "Dest type must be float/double");
269   
270   int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
271   
272   // Store instruction stores `val' to [%fp+offset].
273   // The store and load opCodes are based on the value being copied, and
274   // they use integer and float types that accomodate the
275   // larger of the source type and the destination type:
276   // On SparcV9: int for float, long for double.
277   // 
278   Type* tmpType = (dest->getType() == Type::FloatTy)? Type::IntTy
279                                                     : Type::LongTy;
280   MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
281   store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
282   store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
283   store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
284   mvec.push_back(store);
285
286   // Load instruction loads [%fp+offset] to `dest'.
287   // 
288   MachineInstr* load =new MachineInstr(ChooseLoadInstruction(dest->getType()));
289   load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
290   load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
291   load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
292   mvec.push_back(load);
293 }
294
295
296 // Similarly, create an instruction sequence to copy an FP value
297 // `val' to an integer value `dest' by copying to memory and back.
298 // The generated instructions are returned in `mvec'.
299 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
300 // Any stack space required is allocated via MachineCodeForMethod.
301 // 
302 void
303 UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
304                                         Function* F,
305                                         Value* val,
306                                         Instruction* dest,
307                                         std::vector<MachineInstr*>& mvec,
308                                         MachineCodeForInstruction& mcfi) const
309 {
310   assert(val->getType()->isFloatingPoint()
311          && "Source type must be float/double");
312   assert((dest->getType()->isIntegral() || isa<PointerType>(dest->getType()))
313          && "Dest type must be integral");
314   
315   int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val); 
316   
317   // Store instruction stores `val' to [%fp+offset].
318   // The store and load opCodes are based on the value being copied, and
319   // they use the integer type that matches the source type in size:
320   // On SparcV9: int for float, long for double.
321   // 
322   Type* tmpType = (val->getType() == Type::FloatTy)? Type::IntTy
323                                                    : Type::LongTy;
324   MachineInstr* store=new MachineInstr(ChooseStoreInstruction(val->getType()));
325   store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
326   store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
327   store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
328   mvec.push_back(store);
329   
330   // Load instruction loads [%fp+offset] to `dest'.
331   // 
332   MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
333   load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
334   load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
335   load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
336   mvec.push_back(load);
337 }
338
339
340 // Create instruction(s) to copy src to dest, for arbitrary types
341 // The generated instructions are returned in `mvec'.
342 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
343 // Any stack space required is allocated via MachineCodeForMethod.
344 // 
345 void
346 UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
347                                                   Function *F,
348                                                   Value* src,
349                                                   Instruction* dest,
350                                                   vector<MachineInstr*>& mvec,
351                                           MachineCodeForInstruction& mcfi) const
352 {
353   bool loadConstantToReg = false;
354   
355   const Type* resultType = dest->getType();
356   
357   MachineOpCode opCode = ChooseAddInstructionByType(resultType);
358   if (opCode == INVALID_OPCODE)
359     {
360       assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
361       return;
362     }
363   
364   // if `src' is a constant that doesn't fit in the immed field or if it is
365   // a global variable (i.e., a constant address), generate a load
366   // instruction instead of an add
367   // 
368   if (isa<Constant>(src))
369     {
370       unsigned int machineRegNum;
371       int64_t immedValue;
372       MachineOperand::MachineOperandType opType =
373         ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
374                          machineRegNum, immedValue);
375       
376       if (opType == MachineOperand::MO_VirtualRegister)
377         loadConstantToReg = true;
378     }
379   else if (isa<GlobalValue>(src))
380     loadConstantToReg = true;
381   
382   if (loadConstantToReg)
383     { // `src' is constant and cannot fit in immed field for the ADD
384       // Insert instructions to "load" the constant into a register
385       target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
386                                                   mvec, mcfi);
387     }
388   else
389     { // Create an add-with-0 instruction of the appropriate type.
390       // Make `src' the second operand, in case it is a constant
391       // Use (unsigned long) 0 for a NULL pointer value.
392       // 
393       const Type* zeroValueType =
394         isa<PointerType>(resultType) ? Type::ULongTy : resultType;
395       MachineInstr* minstr =
396         Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
397                             src, dest);
398       mvec.push_back(minstr);
399     }
400 }
401
402
403 // Create instruction sequence to produce a sign-extended register value
404 // from an arbitrary sized value (sized in bits, not bytes).
405 // For SPARC v9, we sign-extend the given unsigned operand using SLL; SRA.
406 // The generated instructions are returned in `mvec'.
407 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
408 // Any stack space required is allocated via MachineCodeForMethod.
409 // 
410 void
411 UltraSparcInstrInfo::CreateSignExtensionInstructions(
412                                         const TargetMachine& target,
413                                         Function* F,
414                                         Value* unsignedSrcVal,
415                                         unsigned int srcSizeInBits,
416                                         Value* dest,
417                                         vector<MachineInstr*>& mvec,
418                                         MachineCodeForInstruction& mcfi) const
419 {
420   MachineInstr* M;
421   
422   assert(srcSizeInBits > 0 && srcSizeInBits <= 32
423      && "Hmmm... srcSizeInBits > 32 unexpected but could be handled here.");
424   
425   if (srcSizeInBits < 32)
426     { // SLL is needed since operand size is < 32 bits.
427       TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
428                                                 unsignedSrcVal, dest,"make32");
429       mcfi.addTemp(tmpI);
430       M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
431       mvec.push_back(M);
432       unsignedSrcVal = tmpI;
433     }
434   
435   M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);
436   mvec.push_back(M);
437 }