Rename ConstPoolVal -> Constant
[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/MachineInstr.h"
19 #include "llvm/Method.h"
20 #include "llvm/ConstantVals.h"
21 #include "llvm/DerivedTypes.h"
22 #include "llvm/Type.h"
23
24
25 //************************ Internal Functions ******************************/
26
27
28 static inline MachineInstr*
29 CreateIntSetInstruction(int64_t C, bool isSigned, Value* dest,
30                         vector<TmpInstruction*>& tempVec)
31 {
32   MachineInstr* minstr;
33   uint64_t absC = (C >= 0)? C : -C;
34   if (absC > (unsigned int) ~0)
35     { // C does not fit in 32 bits
36       TmpInstruction* tmpReg =
37         new TmpInstruction(Instruction::UserOp1, Type::IntTy, NULL, NULL);
38       tempVec.push_back(tmpReg);
39       
40       minstr = new MachineInstr(SETX);
41       minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, C);
42       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, tmpReg,
43                                    /*isdef*/ true);
44       minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,dest);
45     }
46   if (isSigned)
47     {
48       minstr = new MachineInstr(SETSW);
49       minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, C);
50       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, dest);
51     }
52   else
53     {
54       minstr = new MachineInstr(SETUW);
55       minstr->SetMachineOperand(0, MachineOperand::MO_UnextendedImmed, C);
56       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, dest);
57     }
58   
59   return minstr;
60 }
61
62 //************************* External Classes *******************************/
63
64 //---------------------------------------------------------------------------
65 // class UltraSparcInstrInfo 
66 // 
67 // Purpose:
68 //   Information about individual instructions.
69 //   Most information is stored in the SparcMachineInstrDesc array above.
70 //   Other information is computed on demand, and most such functions
71 //   default to member functions in base class MachineInstrInfo. 
72 //---------------------------------------------------------------------------
73
74 /*ctor*/
75 UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
76   : MachineInstrInfo(tgt, SparcMachineInstrDesc,
77                      /*descSize = */ NUM_TOTAL_OPCODES,
78                      /*numRealOpCodes = */ NUM_REAL_OPCODES)
79 {
80 }
81
82
83 // Create an instruction sequence to put the constant `val' into
84 // the virtual register `dest'.  `val' may be a Constant or a
85 // GlobalValue, viz., the constant address of a global variable or function.
86 // The generated instructions are returned in `minstrVec'.
87 // Any temp. registers (TmpInstruction) created are returned in `tempVec'.
88 // 
89 void
90 UltraSparcInstrInfo::CreateCodeToLoadConst(Value* val,
91                                        Instruction* dest,
92                                        vector<MachineInstr*>& minstrVec,
93                                        vector<TmpInstruction*>& tempVec) const
94 {
95   MachineInstr* minstr;
96   
97   assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
98          "I only know about constant values and global addresses");
99   
100   // Use a "set" instruction for known constants that can go in an integer reg.
101   // Use a "load" instruction for all other constants, in particular,
102   // floating point constants and addresses of globals.
103   // 
104   const Type* valType = val->getType();
105   
106   if (valType->isIntegral() || valType == Type::BoolTy)
107     {
108       bool isValidConstant;
109       int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
110       assert(isValidConstant && "Unrecognized constant");
111       minstr = CreateIntSetInstruction(C, valType->isSigned(), dest, tempVec);
112       minstrVec.push_back(minstr);
113     }
114   else
115     {
116       // Make an instruction sequence to load the constant, viz:
117       //            SETX <addr-of-constant>, tmpReg, addrReg
118       //            LOAD  /*addr*/ addrReg, /*offset*/ 0, dest
119       // Only the SETX is needed if `val' is a GlobalValue, i.e,. it is
120       // itself a constant address.  Otherwise, both are needed.
121       
122       Value* addrVal;
123       int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
124       
125       TmpInstruction* tmpReg =
126         new TmpInstruction(Instruction::UserOp1,
127                            PointerType::get(val->getType()), val, NULL);
128       tempVec.push_back(tmpReg);
129       
130       if (isa<Constant>(val))
131         {
132           // Create another TmpInstruction for the hidden integer register
133           TmpInstruction* addrReg =
134             new TmpInstruction(Instruction::UserOp1,
135                                PointerType::get(val->getType()), val, NULL);
136           tempVec.push_back(addrReg);
137           addrVal = addrReg;
138         }
139       else
140         addrVal = dest;
141       
142       minstr = new MachineInstr(SETX);
143       minstr->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp, val);
144       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, tmpReg,
145                                    /*isdef*/ true);
146       minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,addrVal);
147       minstrVec.push_back(minstr);
148       
149       if (isa<Constant>(val))
150         {
151           // addrVal->addMachineInstruction(minstr);
152       
153           minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
154           minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
155                                        addrVal);
156           minstr->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
157                                        zeroOffset);
158           minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
159                                        dest);
160           minstrVec.push_back(minstr);
161         }
162     }
163 }
164
165
166 // Create an instruction sequence to copy an integer value `val'
167 // to a floating point value `dest' by copying to memory and back.
168 // val must be an integral type.  dest must be a Float or Double.
169 // The generated instructions are returned in `minstrVec'.
170 // Any temp. registers (TmpInstruction) created are returned in `tempVec'.
171 // 
172 void
173 UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Method* method,
174                                               Value* val,
175                                               Instruction* dest,
176                                               vector<MachineInstr*>& minstrVec,
177                                               vector<TmpInstruction*>& tempVec,
178                                               TargetMachine& target) const
179 {
180   assert((val->getType()->isIntegral() || val->getType()->isPointerType())
181          && "Source type must be integral");
182   assert((dest->getType() ==Type::FloatTy || dest->getType() ==Type::DoubleTy)
183          && "Dest type must be float/double");
184   
185   const MachineFrameInfo& frameInfo = ((UltraSparc&) target).getFrameInfo();
186   
187   MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(method);
188   int offset = mcinfo.allocateLocalVar(target, val); 
189   
190   // Store instruction stores `val' to [%fp+offset].
191   // The store and load opCodes are based on the value being copied, and
192   // they use integer and float types that accomodate the
193   // larger of the source type and the destination type:
194   // On SparcV9: int for float, long for double.
195   // 
196   Type* tmpType = (dest->getType() == Type::FloatTy)? Type::IntTy
197                                                     : Type::LongTy;
198   MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
199   store->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, val);
200   store->SetMachineOperand(1, target.getRegInfo().getFramePointer());
201   store->SetMachineOperand(2, MachineOperand::MO_SignExtendedImmed, offset);
202   minstrVec.push_back(store);
203
204   // Load instruction loads [%fp+offset] to `dest'.
205   // 
206   MachineInstr* load =new MachineInstr(ChooseLoadInstruction(dest->getType()));
207   load->SetMachineOperand(0, target.getRegInfo().getFramePointer());
208   load->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed, offset);
209   load->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, dest);
210   minstrVec.push_back(load);
211 }
212
213
214 // Similarly, create an instruction sequence to copy an FP value
215 // `val' to an integer value `dest' by copying to memory and back.
216 // See the previous function for information about return values.
217 // 
218 void
219 UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Method* method,
220                                               Value* val,
221                                               Instruction* dest,
222                                               vector<MachineInstr*>& minstrVec,
223                                               vector<TmpInstruction*>& tempVec,
224                                               TargetMachine& target) const
225 {
226   assert((val->getType() ==Type::FloatTy || val->getType() ==Type::DoubleTy)
227          && "Source type must be float/double");
228   assert((dest->getType()->isIntegral() || dest->getType()->isPointerType())
229          && "Dest type must be integral");
230   
231   const MachineFrameInfo& frameInfo = ((UltraSparc&) target).getFrameInfo();
232   
233   MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(method);
234   int offset = mcinfo.allocateLocalVar(target, val); 
235   
236   // Store instruction stores `val' to [%fp+offset].
237   // The store and load opCodes are based on the value being copied, and
238   // they use the integer type that matches the source type in size:
239   // On SparcV9: int for float, long for double.
240   // 
241   Type* tmpType = (val->getType() == Type::FloatTy)? Type::IntTy
242                                                    : Type::LongTy;
243   MachineInstr* store=new MachineInstr(ChooseStoreInstruction(val->getType()));
244   store->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, val);
245   store->SetMachineOperand(1, target.getRegInfo().getFramePointer());
246   store->SetMachineOperand(2, MachineOperand::MO_SignExtendedImmed, offset);
247   minstrVec.push_back(store);
248   
249   // Load instruction loads [%fp+offset] to `dest'.
250   // 
251   MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
252   load->SetMachineOperand(0, target.getRegInfo().getFramePointer());
253   load->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed, offset);
254   load->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, dest);
255   minstrVec.push_back(load);
256 }