xref: /llvm-project/llvm/lib/CodeGen/MachineInstr.cpp (revision 4ac2975f5aa133ad339d0baf062b69373e1a3ddb)
1 // $Id$
2 //***************************************************************************
3 // File:
4 //	MachineInstr.cpp
5 //
6 // Purpose:
7 //
8 //
9 // Strategy:
10 //
11 // History:
12 //	7/2/01	 -  Vikram Adve  -  Created
13 //**************************************************************************/
14 
15 #include "llvm/CodeGen/MachineInstr.h"
16 #include "llvm/ConstPoolVals.h"
17 #include "llvm/Instruction.h"
18 #include <strstream>
19 
20 //************************ Class Implementations **************************/
21 
22 // Constructor for instructions with fixed #operands (nearly all)
23 MachineInstr::MachineInstr(MachineOpCode _opCode,
24 			   OpCodeMask    _opCodeMask)
25   : opCode(_opCode),
26     opCodeMask(_opCodeMask),
27     operands(TargetInstrDescriptors[_opCode].numOperands)
28 {
29   assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
30 }
31 
32 // Constructor for instructions with variable #operands
33 MachineInstr::MachineInstr(MachineOpCode _opCode,
34 			   unsigned	 numOperands,
35 			   OpCodeMask    _opCodeMask)
36   : opCode(_opCode),
37     opCodeMask(_opCodeMask),
38     operands(numOperands)
39 {
40 }
41 
42 void
43 MachineInstr::SetMachineOperand(unsigned int i,
44 				MachineOperand::MachineOperandType operandType,
45 				Value* _val, bool isdef=false)
46 {
47   assert(i < operands.size());
48   operands[i].Initialize(operandType, _val);
49   operands[i].isDef = isdef;
50 }
51 
52 void
53 MachineInstr::SetMachineOperand(unsigned int i,
54 				MachineOperand::MachineOperandType operandType,
55 				int64_t intValue, bool isdef=false)
56 {
57   assert(i < operands.size());
58   operands[i].InitializeConst(operandType, intValue);
59   operands[i].isDef = isdef;
60 }
61 
62 void
63 MachineInstr::SetMachineOperand(unsigned int i,
64 				unsigned int regNum, bool isdef=false)
65 {
66   assert(i < operands.size());
67   operands[i].InitializeReg(regNum);
68   operands[i].isDef = isdef;
69 }
70 
71 void
72 MachineInstr::dump(unsigned int indent)
73 {
74   for (unsigned i=0; i < indent; i++)
75     cout << "    ";
76 
77   cout << *this;
78 }
79 
80 ostream&
81 operator<< (ostream& os, const MachineInstr& minstr)
82 {
83   os << TargetInstrDescriptors[minstr.opCode].opCodeString;
84 
85   for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++)
86     os << "\t" << minstr.getOperand(i);
87 
88 #undef DEBUG_VAL_OP_ITERATOR
89 #ifdef DEBUG_VAL_OP_ITERATOR
90   os << endl << "\tValue operands are: ";
91   for (MachineInstr::val_op_const_iterator vo(&minstr); ! vo.done(); ++vo)
92     {
93       const Value* val = *vo;
94       os << val << (vo.isDef()? "(def), " : ", ");
95     }
96   os << endl;
97 #endif
98 
99   return os;
100 }
101 
102 ostream&
103 operator<< (ostream& os, const MachineOperand& mop)
104 {
105   strstream regInfo;
106   if (mop.opType == MachineOperand::MO_VirtualRegister)
107     regInfo << "(val " << mop.value << ")" << ends;
108   else if (mop.opType == MachineOperand::MO_MachineRegister)
109     regInfo << "("       << mop.regNum << ")" << ends;
110   else if (mop.opType == MachineOperand::MO_CCRegister)
111     regInfo << "(val " << mop.value << ")" << ends;
112 
113   switch(mop.opType)
114     {
115     case MachineOperand::MO_VirtualRegister:
116     case MachineOperand::MO_MachineRegister:
117       os << "%reg" << regInfo.str();
118       free(regInfo.str());
119       break;
120 
121     case MachineOperand::MO_CCRegister:
122       os << "%ccreg" << regInfo.str();
123       free(regInfo.str());
124       break;
125 
126     case MachineOperand::MO_SignExtendedImmed:
127       os << mop.immedVal;
128       break;
129 
130     case MachineOperand::MO_UnextendedImmed:
131       os << mop.immedVal;
132       break;
133 
134     case MachineOperand::MO_PCRelativeDisp:
135       os << "%disp(label " << mop.value << ")";
136       break;
137 
138     default:
139       assert(0 && "Unrecognized operand type");
140       break;
141     }
142 
143   return os;
144 }
145 
146 
147 //---------------------------------------------------------------------------
148 // Target-independent utility routines for creating machine instructions
149 //---------------------------------------------------------------------------
150 
151 
152 //------------------------------------------------------------------------
153 // Function Set2OperandsFromInstr
154 // Function Set3OperandsFromInstr
155 //
156 // For the common case of 2- and 3-operand arithmetic/logical instructions,
157 // set the m/c instr. operands directly from the VM instruction's operands.
158 // Check whether the first or second operand is 0 and can use a dedicated "0" register.
159 // Check whether the second operand should use an immediate field or register.
160 // (First and third operands are never immediates for such instructions.)
161 //
162 // Arguments:
163 // canDiscardResult: Specifies that the result operand can be discarded
164 //		     by using the dedicated "0"
165 //
166 // op1position, op2position and resultPosition: Specify in which position
167 //		     in the machine instruction the 3 operands (arg1, arg2
168 //		     and result) should go.
169 //
170 // RETURN VALUE: unsigned int flags, where
171 //	flags & 0x01	=> operand 1 is constant and needs a register
172 //	flags & 0x02	=> operand 2 is constant and needs a register
173 //------------------------------------------------------------------------
174 
175 void
176 Set2OperandsFromInstr(MachineInstr* minstr,
177 		      InstructionNode* vmInstrNode,
178 		      const TargetMachine& target,
179 		      bool canDiscardResult,
180 		      int op1Position,
181 		      int resultPosition)
182 {
183   Set3OperandsFromInstr(minstr, vmInstrNode, target,
184 			canDiscardResult, op1Position,
185 			/*op2Position*/ -1, resultPosition);
186 }
187 
188 #undef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
189 #ifdef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
190 unsigned
191 Set3OperandsFromInstrJUNK(MachineInstr* minstr,
192 		      InstructionNode* vmInstrNode,
193 		      const TargetMachine& target,
194 		      bool canDiscardResult,
195 		      int op1Position,
196 		      int op2Position,
197 		      int resultPosition)
198 {
199   assert(op1Position >= 0);
200   assert(resultPosition >= 0);
201 
202   unsigned returnFlags = 0x0;
203 
204   // Check if operand 1 is 0 and if so, try to use the register that gives 0, if any.
205   Value* op1Value = vmInstrNode->leftChild()->getValue();
206   bool isValidConstant;
207   int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant);
208   if (isValidConstant && intValue == 0 && target.zeroRegNum >= 0)
209     minstr->SetMachineOperand(op1Position, /*regNum*/ target.zeroRegNum);
210   else
211     {
212       if (op1Value->getValueType() == Value::ConstantVal)
213 	{// value is constant and must be loaded from constant pool
214 	  returnFlags = returnFlags | (1 << op1Position);
215 	}
216       minstr->SetMachineOperand(op1Position,MachineOperand::MO_VirtualRegister,
217 					    op1Value);
218     }
219 
220   // Check if operand 2 (if any) fits in the immediate field of the instruction,
221   // of if it is 0 and can use a dedicated machine register
222   if (op2Position >= 0)
223     {
224       Value* op2Value = vmInstrNode->rightChild()->getValue();
225       int64_t immedValue;
226       unsigned int machineRegNum;
227 
228       MachineOperand::MachineOperandType
229 	op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(), target,
230 				   /*canUseImmed*/ true,
231 				   machineRegNum, immedValue);
232 
233       if (op2type == MachineOperand::MO_MachineRegister)
234 	minstr->SetMachineOperand(op2Position, machineRegNum);
235       else if (op2type == MachineOperand::MO_VirtualRegister)
236 	{
237 	  if (op2Value->getValueType() == Value::ConstantVal)
238 	    {// value is constant and must be loaded from constant pool
239 	      returnFlags = returnFlags | (1 << op2Position);
240 	    }
241 	  minstr->SetMachineOperand(op2Position, op2type, op2Value);
242 	}
243       else
244 	{
245 	  assert(op2type != MO_CCRegister);
246 	  minstr->SetMachineOperand(op2Position, op2type, immedValue);
247 	}
248     }
249 
250   // If operand 3 (result) can be discarded, use a dead register if one exists
251   if (canDiscardResult && target.zeroRegNum >= 0)
252     minstr->SetMachineOperand(resultPosition, target.zeroRegNum);
253   else
254     minstr->SetMachineOperand(resultPosition, MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
255 
256   return returnFlags;
257 }
258 #endif
259 
260 
261 void
262 Set3OperandsFromInstr(MachineInstr* minstr,
263 		      InstructionNode* vmInstrNode,
264 		      const TargetMachine& target,
265 		      bool canDiscardResult,
266 		      int op1Position,
267 		      int op2Position,
268 		      int resultPosition)
269 {
270   assert(op1Position >= 0);
271   assert(resultPosition >= 0);
272 
273   // operand 1
274   minstr->SetMachineOperand(op1Position, MachineOperand::MO_VirtualRegister,
275 			    vmInstrNode->leftChild()->getValue());
276 
277   // operand 2 (if any)
278   if (op2Position >= 0)
279     minstr->SetMachineOperand(op2Position, MachineOperand::MO_VirtualRegister,
280 			      vmInstrNode->rightChild()->getValue());
281 
282   // result operand: if it can be discarded, use a dead register if one exists
283   if (canDiscardResult && target.zeroRegNum >= 0)
284     minstr->SetMachineOperand(resultPosition, target.zeroRegNum);
285   else
286     minstr->SetMachineOperand(resultPosition, MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
287 }
288 
289 
290 MachineOperand::MachineOperandType
291 ChooseRegOrImmed(Value* val,
292 		 MachineOpCode opCode,
293 		 const TargetMachine& target,
294 		 bool canUseImmed,
295 		 unsigned int& getMachineRegNum,
296 		 int64_t& getImmedValue)
297 {
298   MachineOperand::MachineOperandType opType =
299     MachineOperand::MO_VirtualRegister;
300   getMachineRegNum = 0;
301   getImmedValue = 0;
302 
303   // Check for the common case first: argument is not constant
304   //
305   if (val->getValueType() != Value::ConstantVal)
306     return opType;
307 
308   // Now get the constant value and check if it fits in the IMMED field.
309   // Take advantage of the fact that the max unsigned value will rarely
310   // fit into any IMMED field and ignore that case (i.e., cast smaller
311   // unsigned constants to signed).
312   //
313   bool isValidConstant;
314   int64_t intValue = GetConstantValueAsSignedInt(val, isValidConstant);
315 
316   if (isValidConstant)
317     {
318       if (intValue == 0 && target.zeroRegNum >= 0)
319 	{
320 	  opType = MachineOperand::MO_MachineRegister;
321 	  getMachineRegNum = target.zeroRegNum;
322 	}
323       else if (canUseImmed &&
324 	       target.getInstrInfo().constantFitsInImmedField(opCode,intValue))
325 	{
326 	  opType = MachineOperand::MO_SignExtendedImmed;
327 	  getImmedValue = intValue;
328 	}
329     }
330 
331   return opType;
332 }
333