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