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