1. Add a bottom-up pass on BURG trees that is used to fix constant operands.
[oota-llvm.git] / lib / Target / SparcV9 / InstrSelection / InstrSelectionSupport.cpp
1 // $Id$ -*-c++-*-
2 //***************************************************************************
3 // File:
4 //      InstrSelectionSupport.h
5 // 
6 // Purpose:
7 //      Target-independent instruction selection code.
8 //      See SparcInstrSelection.cpp for usage.
9 //      
10 // History:
11 //      10/10/01         -  Vikram Adve  -  Created
12 //**************************************************************************/
13
14 #include "llvm/CodeGen/InstrSelectionSupport.h"
15 #include "llvm/CodeGen/InstrSelection.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/Target/TargetMachine.h"
18 #include "llvm/Target/MachineRegInfo.h"
19 #include "llvm/ConstPoolVals.h"
20 #include "llvm/Instruction.h"
21 #include "llvm/Type.h"
22 #include "llvm/iMemory.h"
23
24
25 //*************************** Local Functions ******************************/
26
27
28 static TmpInstruction*
29 InsertCodeToLoadConstant(Value* opValue,
30                          Instruction* vmInstr,
31                          vector<MachineInstr*>& loadConstVec,
32                          TargetMachine& target)
33 {
34   vector<TmpInstruction*> tempVec;
35   
36   // Create a tmp virtual register to hold the constant.
37   TmpInstruction* tmpReg =
38     new TmpInstruction(TMP_INSTRUCTION_OPCODE, opValue, NULL);
39   vmInstr->getMachineInstrVec().addTempValue(tmpReg);
40   
41   target.getInstrInfo().CreateCodeToLoadConst(opValue, tmpReg,
42                                               loadConstVec, tempVec);
43   
44   // Register the new tmp values created for this m/c instruction sequence
45   for (unsigned i=0; i < tempVec.size(); i++)
46     vmInstr->getMachineInstrVec().addTempValue(tempVec[i]);
47   
48   // Record the mapping from the tmp VM instruction to machine instruction.
49   // Do this for all machine instructions that were not mapped to any
50   // other temp values created by 
51   // tmpReg->addMachineInstruction(loadConstVec.back());
52   
53   return tmpReg;
54 }
55
56
57 //---------------------------------------------------------------------------
58 // Function GetConstantValueAsSignedInt
59 // 
60 // Convenience function to get the value of an integer constant, for an
61 // appropriate integer or non-integer type that can be held in an integer.
62 // The type of the argument must be the following:
63 //      Signed or unsigned integer
64 //      Boolean
65 //      Pointer
66 // 
67 // isValidConstant is set to true if a valid constant was found.
68 //---------------------------------------------------------------------------
69
70 int64_t
71 GetConstantValueAsSignedInt(const Value *V,
72                             bool &isValidConstant)
73 {
74   if (!isa<ConstPoolVal>(V))
75     {
76       isValidConstant = false;
77       return 0;
78     }
79   
80   isValidConstant = true;
81   
82   if (V->getType() == Type::BoolTy)
83     return (int64_t) ((ConstPoolBool*)V)->getValue();
84   
85   if (V->getType()->isIntegral())
86     {
87       if (V->getType()->isSigned())
88         return ((ConstPoolSInt*)V)->getValue();
89       
90       assert(V->getType()->isUnsigned());
91       uint64_t Val = ((ConstPoolUInt*)V)->getValue();
92       if (Val < INT64_MAX)     // then safe to cast to signed
93         return (int64_t)Val;
94     }
95
96   isValidConstant = false;
97   return 0;
98 }
99
100
101 //---------------------------------------------------------------------------
102 // Function: FoldGetElemChain
103 // 
104 // Purpose:
105 //   Fold a chain of GetElementPtr instructions into an equivalent
106 //   (Pointer, IndexVector) pair.  Returns the pointer Value, and
107 //   stores the resulting IndexVector in argument chainIdxVec.
108 //---------------------------------------------------------------------------
109
110 Value*
111 FoldGetElemChain(const InstructionNode* getElemInstrNode,
112                  vector<ConstPoolVal*>& chainIdxVec)
113 {
114   MemAccessInst* getElemInst = (MemAccessInst*)
115     getElemInstrNode->getInstruction();
116   
117   // Initialize return values from the incoming instruction
118   Value* ptrVal = getElemInst->getPtrOperand();
119   chainIdxVec = getElemInst->getIndexVec(); // copies index vector values
120   
121   // Now chase the chain of getElementInstr instructions, if any
122   InstrTreeNode* ptrChild = getElemInstrNode->leftChild();
123   while (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
124          ptrChild->getOpLabel() == GetElemPtrIdx)
125     {
126       // Child is a GetElemPtr instruction
127       getElemInst = (MemAccessInst*)
128         ((InstructionNode*) ptrChild)->getInstruction();
129       const vector<ConstPoolVal*>& idxVec = getElemInst->getIndexVec();
130       
131       // Get the pointer value out of ptrChild and *prepend* its index vector
132       ptrVal = getElemInst->getPtrOperand();
133       chainIdxVec.insert(chainIdxVec.begin(), idxVec.begin(), idxVec.end());
134       
135       ptrChild = ptrChild->leftChild();
136     }
137   
138   return ptrVal;
139 }
140
141
142 //------------------------------------------------------------------------ 
143 // Function Set2OperandsFromInstr
144 // Function Set3OperandsFromInstr
145 // 
146 // For the common case of 2- and 3-operand arithmetic/logical instructions,
147 // set the m/c instr. operands directly from the VM instruction's operands.
148 // Check whether the first or second operand is 0 and can use a dedicated "0"
149 // register.
150 // Check whether the second operand should use an immediate field or register.
151 // (First and third operands are never immediates for such instructions.)
152 // 
153 // Arguments:
154 // canDiscardResult: Specifies that the result operand can be discarded
155 //                   by using the dedicated "0"
156 // 
157 // op1position, op2position and resultPosition: Specify in which position
158 //                   in the machine instruction the 3 operands (arg1, arg2
159 //                   and result) should go.
160 // 
161 // RETURN VALUE: unsigned int flags, where
162 //      flags & 0x01    => operand 1 is constant and needs a register
163 //      flags & 0x02    => operand 2 is constant and needs a register
164 //------------------------------------------------------------------------ 
165
166 void
167 Set2OperandsFromInstr(MachineInstr* minstr,
168                       InstructionNode* vmInstrNode,
169                       const TargetMachine& target,
170                       bool canDiscardResult,
171                       int op1Position,
172                       int resultPosition)
173 {
174   Set3OperandsFromInstr(minstr, vmInstrNode, target,
175                         canDiscardResult, op1Position,
176                         /*op2Position*/ -1, resultPosition);
177 }
178
179
180 void
181 Set3OperandsFromInstr(MachineInstr* minstr,
182                       InstructionNode* vmInstrNode,
183                       const TargetMachine& target,
184                       bool canDiscardResult,
185                       int op1Position,
186                       int op2Position,
187                       int resultPosition)
188 {
189   assert(op1Position >= 0);
190   assert(resultPosition >= 0);
191   
192   // operand 1
193   minstr->SetMachineOperand(op1Position, MachineOperand::MO_VirtualRegister,
194                             vmInstrNode->leftChild()->getValue());   
195   
196   // operand 2 (if any)
197   if (op2Position >= 0)
198     minstr->SetMachineOperand(op2Position, MachineOperand::MO_VirtualRegister,
199                               vmInstrNode->rightChild()->getValue());   
200   
201   // result operand: if it can be discarded, use a dead register if one exists
202   if (canDiscardResult && target.getRegInfo().getZeroRegNum() >= 0)
203     minstr->SetMachineOperand(resultPosition,
204                               target.getRegInfo().getZeroRegNum());
205   else
206     minstr->SetMachineOperand(resultPosition,
207                               MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
208 }
209
210
211 MachineOperand::MachineOperandType
212 ChooseRegOrImmed(Value* val,
213                  MachineOpCode opCode,
214                  const TargetMachine& target,
215                  bool canUseImmed,
216                  unsigned int& getMachineRegNum,
217                  int64_t& getImmedValue)
218 {
219   MachineOperand::MachineOperandType opType =
220     MachineOperand::MO_VirtualRegister;
221   getMachineRegNum = 0;
222   getImmedValue = 0;
223   
224   // Check for the common case first: argument is not constant
225   // 
226   ConstPoolVal *CPV = dyn_cast<ConstPoolVal>(val);
227   if (!CPV) return opType;
228
229   if (CPV->getType() == Type::BoolTy)
230     {
231       ConstPoolBool *CPB = (ConstPoolBool*)CPV;
232       if (!CPB->getValue() && target.getRegInfo().getZeroRegNum() >= 0)
233         {
234           getMachineRegNum = target.getRegInfo().getZeroRegNum();
235           return MachineOperand::MO_MachineRegister;
236         }
237
238       getImmedValue = 1;
239       return MachineOperand::MO_SignExtendedImmed;
240     }
241   
242   if (!CPV->getType()->isIntegral()) return opType;
243
244   // Now get the constant value and check if it fits in the IMMED field.
245   // Take advantage of the fact that the max unsigned value will rarely
246   // fit into any IMMED field and ignore that case (i.e., cast smaller
247   // unsigned constants to signed).
248   // 
249   int64_t intValue;
250   if (CPV->getType()->isSigned())
251     {
252       intValue = ((ConstPoolSInt*)CPV)->getValue();
253     }
254   else
255     {
256       uint64_t V = ((ConstPoolUInt*)CPV)->getValue();
257       if (V >= INT64_MAX) return opType;
258       intValue = (int64_t)V;
259     }
260
261   if (intValue == 0 && target.getRegInfo().getZeroRegNum() >= 0)
262     {
263       opType = MachineOperand::MO_MachineRegister;
264       getMachineRegNum = target.getRegInfo().getZeroRegNum();
265     }
266   else if (canUseImmed &&
267            target.getInstrInfo().constantFitsInImmedField(opCode, intValue))
268     {
269       opType = MachineOperand::MO_SignExtendedImmed;
270       getImmedValue = intValue;
271     }
272   
273   return opType;
274 }
275
276
277 //---------------------------------------------------------------------------
278 // Function: FixConstantOperandsForInstr
279 // 
280 // Purpose:
281 // Special handling for constant operands of a machine instruction
282 // -- if the constant is 0, use the hardwired 0 register, if any;
283 // -- if the constant fits in the IMMEDIATE field, use that field;
284 // -- else create instructions to put the constant into a register, either
285 //    directly or by loading explicitly from the constant pool.
286 // 
287 // In the first 2 cases, the operand of `minstr' is modified in place.
288 // Returns a vector of machine instructions generated for operands that
289 // fall under case 3; these must be inserted before `minstr'.
290 //---------------------------------------------------------------------------
291
292 vector<MachineInstr*>
293 FixConstantOperandsForInstr(Instruction* vmInstr,
294                             MachineInstr* minstr,
295                             TargetMachine& target)
296 {
297   vector<MachineInstr*> loadConstVec;
298   
299   const MachineInstrDescriptor& instrDesc =
300     target.getInstrInfo().getDescriptor(minstr->getOpCode());
301   
302   for (unsigned op=0; op < minstr->getNumOperands(); op++)
303     {
304       const MachineOperand& mop = minstr->getOperand(op);
305           
306       // skip the result position (for efficiency below) and any other
307       // positions already marked as not a virtual register
308       if (instrDesc.resultPos == (int) op || 
309           mop.getOperandType() != MachineOperand::MO_VirtualRegister ||
310           mop.getVRegValue() == NULL)
311         {
312           continue;
313         }
314           
315       Value* opValue = mop.getVRegValue();
316       bool constantThatMustBeLoaded = false;
317       
318       if (isa<ConstPoolVal>(opValue))
319         {
320           unsigned int machineRegNum;
321           int64_t immedValue;
322           MachineOperand::MachineOperandType opType =
323             ChooseRegOrImmed(opValue, minstr->getOpCode(), target,
324                              /*canUseImmed*/ (op == 1),
325                              machineRegNum, immedValue);
326               
327           if (opType == MachineOperand::MO_MachineRegister)
328             minstr->SetMachineOperand(op, machineRegNum);
329           else if (opType == MachineOperand::MO_VirtualRegister)
330             constantThatMustBeLoaded = true; // load is generated below
331           else
332             minstr->SetMachineOperand(op, opType, immedValue);
333         }
334
335       if (constantThatMustBeLoaded || isa<GlobalValue>(opValue))
336         { // opValue is a constant that must be explicitly loaded into a reg.
337           TmpInstruction* tmpReg = InsertCodeToLoadConstant(opValue, vmInstr,
338                                                         loadConstVec, target);
339           minstr->SetMachineOperand(op, MachineOperand::MO_VirtualRegister,
340                                         tmpReg);
341         }
342     }
343   
344   // 
345   // Also, check for implicit operands used (not those defined) by the
346   // machine instruction.  These include:
347   // -- arguments to a Call
348   // -- return value of a Return
349   // Any such operand that is a constant value needs to be fixed also.
350   // The current instructions with implicit refs (viz., Call and Return)
351   // have no immediate fields, so the constant always needs to be loaded
352   // into a register.
353   // 
354   for (unsigned i=0, N=minstr->getNumImplicitRefs(); i < N; ++i)
355     if (isa<ConstPoolVal>(minstr->getImplicitRef(i)) ||
356         isa<GlobalValue>(minstr->getImplicitRef(i)))
357       {
358         TmpInstruction* tmpReg =
359           InsertCodeToLoadConstant(minstr->getImplicitRef(i), vmInstr,
360                                    loadConstVec, target);
361         minstr->setImplicitRef(i, tmpReg);
362       }
363   
364   return loadConstVec;
365 }
366
367
368 #undef SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
369 #ifdef SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
370 unsigned
371 FixConstantOperands(const InstructionNode* vmInstrNode,
372                     TargetMachine& target)
373 {
374   Instruction* vmInstr = vmInstrNode->getInstruction();
375   MachineCodeForVMInstr& mvec = vmInstr->getMachineInstrVec();
376   
377   for (unsigned i=0; i < mvec.size(); i++)
378     {
379       vector<MachineInsr*> loadConstVec =
380         FixConstantOperandsForInstr(mvec[i], target);
381     }
382   
383   // 
384   // Finally, inserted the generated instructions in the vector
385   // to be returned.
386   // 
387   unsigned numNew = loadConstVec.size();
388   if (numNew > 0)
389     {
390       // Insert the new instructions *before* the old ones by moving
391       // the old ones over `numNew' positions (last-to-first, of course!).
392       // We do check *after* returning that we did not exceed the vector mvec.
393       for (int i=numInstr-1; i >= 0; i--)
394         mvec[i+numNew] = mvec[i];
395       
396       for (unsigned i=0; i < numNew; i++)
397         mvec[i] = loadConstVec[i];
398     }
399   
400   return (numInstr + numNew);
401 }
402 #endif SAVE_TO_MOVE_BACK_TO_SPARCISSCPP
403
404