MachineInstr.cpp revision 45c171ee25619f6650e90fa5e3102d9969fd82b3
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)
23MachineInstr::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
33MachineInstr::MachineInstr(MachineOpCode _opCode,
34			   unsigned	 numOperands,
35			   OpCodeMask    _opCodeMask)
36  : opCode(_opCode),
37    opCodeMask(_opCodeMask),
38    operands(numOperands)
39{
40}
41
42void
43MachineInstr::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
52void
53MachineInstr::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
62void
63MachineInstr::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
71void
72MachineInstr::dump(unsigned int indent)
73{
74  for (unsigned i=0; i < indent; i++)
75    cout << "    ";
76
77  cout << *this;
78}
79
80ostream&
81operator<< (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
102ostream&
103operator<< (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
175void
176Set2OperandsFromInstr(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
190unsigned
191Set3OperandsFromInstrJUNK(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
261void
262Set3OperandsFromInstr(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
290MachineOperand::MachineOperandType
291ChooseRegOrImmed(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