aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/MachineInstr.cpp
diff options
context:
space:
mode:
authorVikram S. Adve <vadve@cs.uiuc.edu>2001-07-21 12:41:50 +0000
committerVikram S. Adve <vadve@cs.uiuc.edu>2001-07-21 12:41:50 +0000
commit70bc4b5d1a3795a8f41be96723cfcbccac8e1671 (patch)
tree76f1cec318278964f0acaa93539fc8748aa14d56 /lib/CodeGen/MachineInstr.cpp
parent05f4745c01db6705edc0c08f12a8da7c3d4f5910 (diff)
downloadexternal_llvm-70bc4b5d1a3795a8f41be96723cfcbccac8e1671.zip
external_llvm-70bc4b5d1a3795a8f41be96723cfcbccac8e1671.tar.gz
external_llvm-70bc4b5d1a3795a8f41be96723cfcbccac8e1671.tar.bz2
Instruction selection via pattern matching on instruction trees using BURG.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/MachineInstr.cpp')
-rw-r--r--lib/CodeGen/MachineInstr.cpp344
1 files changed, 344 insertions, 0 deletions
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
new file mode 100644
index 0000000..1b6f25a
--- /dev/null
+++ b/lib/CodeGen/MachineInstr.cpp
@@ -0,0 +1,344 @@
+// $Id$
+//***************************************************************************
+// File:
+// MachineInstr.cpp
+//
+// Purpose:
+//
+//
+// Strategy:
+//
+// History:
+// 7/2/01 - Vikram Adve - Created
+//**************************************************************************/
+
+
+//************************** System Include Files **************************/
+
+#include <strstream.h>
+#include <string>
+#include <vector>
+
+//*************************** User Include Files ***************************/
+
+#include "llvm/Type.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/ConstPoolVals.h"
+#include "llvm/Value.h"
+#include "llvm/Instruction.h"
+#include "llvm/Codegen/InstrForest.h"
+#include "llvm/Codegen/MachineInstr.h"
+
+//************************ Class Implementations **************************/
+
+
+bool
+MachineInstrInfo::constantFitsInImmedField(int64_t intValue) const
+{
+ // First, check if opCode has an immed field.
+ bool isSignExtended;
+ uint64_t maxImmedValue = this->maxImmedConstant(isSignExtended);
+ if (maxImmedValue != 0)
+ {
+ // Now check if the constant fits
+ if (intValue <= (int64_t) maxImmedValue &&
+ intValue >= -((int64_t) maxImmedValue+1))
+ return true;
+ }
+
+ return false;
+}
+
+MachineInstr::MachineInstr(MachineOpCode _opCode,
+ OpCodeMask _opCodeMask)
+ : opCode(_opCode),
+ opCodeMask(_opCodeMask),
+ operands(TargetMachineInstrInfo[_opCode].numOperands)
+{
+}
+
+MachineInstr::~MachineInstr()
+{
+}
+
+void
+MachineInstr::SetMachineOperand(unsigned int i,
+ MachineOperand::MachineOperandType operandType,
+ Value* _val)
+{
+ assert(i < TargetMachineInstrInfo[opCode].numOperands);
+ operands[i].Initialize(operandType, _val);
+}
+
+void
+MachineInstr::SetMachineOperand(unsigned int i,
+ MachineOperand::MachineOperandType operandType,
+ int64_t intValue)
+{
+ assert(i < TargetMachineInstrInfo[opCode].numOperands);
+ operands[i].InitializeConst(operandType, intValue);
+}
+
+void
+MachineInstr::SetMachineOperand(unsigned int i,
+ unsigned int regNum)
+{
+ assert(i < TargetMachineInstrInfo[opCode].numOperands);
+ operands[i].InitializeReg(regNum);
+}
+
+void
+MachineInstr::dump(unsigned int indent)
+{
+ for (unsigned i=0; i < indent; i++)
+ cout << " ";
+
+ cout << *this;
+}
+
+ostream&
+operator<< (ostream& os, const MachineInstr& minstr)
+{
+ os << TargetMachineInstrInfo[minstr.opCode].opCodeString;
+
+ for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++)
+ os << "\t" << minstr.getOperand(i);
+
+ return os;
+}
+
+ostream&
+operator<< (ostream& os, const MachineOperand& mop)
+{
+ strstream regInfo;
+ if (mop.machineOperandType == MachineOperand::MO_Register)
+ {
+ if (mop.vregType == MachineOperand::MO_VirtualReg)
+ regInfo << "(val " << mop.value << ")" << ends;
+ else
+ regInfo << "(" << mop.regNum << ")" << ends;
+ }
+ else if (mop.machineOperandType == MachineOperand::MO_CCRegister)
+ regInfo << "(val " << mop.value << ")" << ends;
+
+ switch(mop.machineOperandType)
+ {
+ case MachineOperand::MO_Register:
+ os << "%reg" << regInfo.str();
+ free(regInfo.str());
+ break;
+
+ case MachineOperand::MO_CCRegister:
+ os << "%ccreg" << regInfo.str();
+ free(regInfo.str());
+ break;
+
+ case MachineOperand::MO_SignExtendedImmed:
+ os << mop.immedVal;
+ break;
+
+ case MachineOperand::MO_UnextendedImmed:
+ os << mop.immedVal;
+ break;
+
+ case MachineOperand::MO_PCRelativeDisp:
+ os << "%disp(label " << mop.value << ")";
+ break;
+
+ default:
+ assert(0 && "Unrecognized operand type");
+ break;
+ }
+
+ return os;
+}
+
+
+//---------------------------------------------------------------------------
+// Target-independent utility routines for creating machine instructions
+//---------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------
+// Function Set2OperandsFromInstr
+// Function Set3OperandsFromInstr
+//
+// For the common case of 2- and 3-operand arithmetic/logical instructions,
+// set the m/c instr. operands directly from the VM instruction's operands.
+// Check whether the first or second operand is 0 and can use a dedicated "0" register.
+// Check whether the second operand should use an immediate field or register.
+// (First and third operands are never immediates for such instructions.)
+//
+// Arguments:
+// canDiscardResult: Specifies that the result operand can be discarded
+// by using the dedicated "0"
+//
+// op1position, op2position and resultPosition: Specify in which position
+// in the machine instruction the 3 operands (arg1, arg2
+// and result) should go.
+//
+// RETURN VALUE: unsigned int flags, where
+// flags & 0x01 => operand 1 is constant and needs a register
+// flags & 0x02 => operand 2 is constant and needs a register
+//------------------------------------------------------------------------
+
+void
+Set2OperandsFromInstr(MachineInstr* minstr,
+ InstructionNode* vmInstrNode,
+ const TargetMachine& targetMachine,
+ bool canDiscardResult,
+ int op1Position,
+ int resultPosition)
+{
+ Set3OperandsFromInstr(minstr, vmInstrNode, targetMachine,
+ canDiscardResult, op1Position,
+ /*op2Position*/ -1, resultPosition);
+}
+
+
+unsigned
+Set3OperandsFromInstrJUNK(MachineInstr* minstr,
+ InstructionNode* vmInstrNode,
+ const TargetMachine& targetMachine,
+ bool canDiscardResult,
+ int op1Position,
+ int op2Position,
+ int resultPosition)
+{
+ assert(op1Position >= 0);
+ assert(resultPosition >= 0);
+
+ unsigned returnFlags = 0x0;
+
+ // Check if operand 1 is 0 and if so, try to use the register that gives 0, if any.
+ Value* op1Value = vmInstrNode->leftChild()->getValue();
+ bool isValidConstant;
+ int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant);
+ if (isValidConstant && intValue == 0 && targetMachine.zeroRegNum >= 0)
+ minstr->SetMachineOperand(op1Position, /*regNum*/ targetMachine.zeroRegNum);
+ else
+ {
+ if (op1Value->getValueType() == Value::ConstantVal)
+ {// value is constant and must be loaded from constant pool
+ returnFlags = returnFlags | (1 << op1Position);
+ }
+ minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register,
+ op1Value);
+ }
+
+ // Check if operand 2 (if any) fits in the immediate field of the instruction,
+ // of if it is 0 and can use a dedicated machine register
+ if (op2Position >= 0)
+ {
+ Value* op2Value = vmInstrNode->rightChild()->getValue();
+ int64_t immedValue;
+ MachineOperand::VirtualRegisterType vregType;
+ unsigned int machineRegNum;
+
+ MachineOperand::MachineOperandType
+ op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(),targetMachine,
+ /*canUseImmed*/ true,
+ vregType, machineRegNum, immedValue);
+
+ if (op2type == MachineOperand::MO_Register)
+ {
+ if (vregType == MachineOperand::MO_MachineReg)
+ minstr->SetMachineOperand(op2Position, machineRegNum);
+ else
+ {
+ if (op2Value->getValueType() == Value::ConstantVal)
+ {// value is constant and must be loaded from constant pool
+ returnFlags = returnFlags | (1 << op2Position);
+ }
+ minstr->SetMachineOperand(op2Position, op2type, op2Value);
+ }
+ }
+ else
+ minstr->SetMachineOperand(op2Position, op2type, immedValue);
+ }
+
+ // If operand 3 (result) can be discarded, use a dead register if one exists
+ if (canDiscardResult && targetMachine.zeroRegNum >= 0)
+ minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum);
+ else
+ minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register,
+ vmInstrNode->getValue());
+
+ return returnFlags;
+}
+
+
+void
+Set3OperandsFromInstr(MachineInstr* minstr,
+ InstructionNode* vmInstrNode,
+ const TargetMachine& targetMachine,
+ bool canDiscardResult,
+ int op1Position,
+ int op2Position,
+ int resultPosition)
+{
+ assert(op1Position >= 0);
+ assert(resultPosition >= 0);
+
+ // operand 1
+ minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register,
+ vmInstrNode->leftChild()->getValue());
+
+ // operand 2 (if any)
+ if (op2Position >= 0)
+ minstr->SetMachineOperand(op2Position, MachineOperand::MO_Register,
+ vmInstrNode->rightChild()->getValue());
+
+ // result operand: if it can be discarded, use a dead register if one exists
+ if (canDiscardResult && targetMachine.zeroRegNum >= 0)
+ minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum);
+ else
+ minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register,
+ vmInstrNode->getValue());
+}
+
+
+MachineOperand::MachineOperandType
+ChooseRegOrImmed(Value* val,
+ MachineOpCode opCode,
+ const TargetMachine& targetMachine,
+ bool canUseImmed,
+ MachineOperand::VirtualRegisterType& getVRegType,
+ unsigned int& getMachineRegNum,
+ int64_t& getImmedValue)
+{
+ MachineOperand::MachineOperandType opType = MachineOperand::MO_Register;
+ getVRegType = MachineOperand::MO_VirtualReg;
+ getMachineRegNum = 0;
+ getImmedValue = 0;
+
+ // Check for the common case first: argument is not constant
+ //
+ if (val->getValueType() != Value::ConstantVal)
+ return opType;
+
+ // Now get the constant value and check if it fits in the IMMED field.
+ // Take advantage of the fact that the max unsigned value will rarely
+ // fit into any IMMED field and ignore that case (i.e., cast smaller
+ // unsigned constants to signed).
+ //
+ bool isValidConstant;
+ int64_t intValue = GetConstantValueAsSignedInt(val, isValidConstant);
+
+ if (isValidConstant)
+ {
+ if (intValue == 0 && targetMachine.zeroRegNum >= 0)
+ {
+ getVRegType = MachineOperand::MO_MachineReg;
+ getMachineRegNum = targetMachine.zeroRegNum;
+ }
+ else if (canUseImmed &&
+ targetMachine.machineInstrInfo[opCode].constantFitsInImmedField(intValue))
+ {
+ opType = MachineOperand::MO_SignExtendedImmed;
+ getImmedValue = intValue;
+ }
+ }
+
+ return opType;
+}