Major changes too hard to document :-)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@400 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/TargetMachine/Sparc/SparcInstrSelection.cpp b/lib/CodeGen/TargetMachine/Sparc/SparcInstrSelection.cpp
index 8396253..088d089 100644
--- a/lib/CodeGen/TargetMachine/Sparc/SparcInstrSelection.cpp
+++ b/lib/CodeGen/TargetMachine/Sparc/SparcInstrSelection.cpp
@@ -7,8 +7,9 @@
//
// History:
// 7/02/01 - Vikram Adve - Created
-//***************************************************************************
+//**************************************************************************/
+#include "llvm/Support/MathExtras.h"
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/SymbolTable.h"
@@ -94,21 +95,17 @@
unsigned numInstr,
TargetMachine& target);
-static unsigned InsertLoadConstInstructions(unsigned loadConstFlags,
- const InstructionNode* vmInstrNode,
- MachineInstr** mvec,
- unsigned numInstr);
-
-static MachineInstr* MakeOneLoadConstInstr(Instruction* vmInstr,
- Value* val,
- TmpInstruction*& tmpReg);
+static MachineInstr* MakeLoadConstInstr(Instruction* vmInstr,
+ Value* val,
+ TmpInstruction*& tmpReg,
+ MachineInstr*& getMinstr2);
static void ForwardOperand (InstructionNode* treeNode,
InstructionNode* parent,
int operandNum);
-//******************* Externally Visible Functions *************************/
+//************************ Internal Functions ******************************/
//------------------------------------------------------------------------
@@ -145,6 +142,1151 @@
}
}
+
+static inline MachineOpCode
+ChooseBprInstruction(const InstructionNode* instrNode)
+{
+ MachineOpCode opCode;
+
+ Instruction* setCCInstr =
+ ((InstructionNode*) instrNode->leftChild())->getInstruction();
+
+ switch(setCCInstr->getOpcode())
+ {
+ case Instruction::SetEQ: opCode = BRZ; break;
+ case Instruction::SetNE: opCode = BRNZ; break;
+ case Instruction::SetLE: opCode = BRLEZ; break;
+ case Instruction::SetGE: opCode = BRGEZ; break;
+ case Instruction::SetLT: opCode = BRLZ; break;
+ case Instruction::SetGT: opCode = BRGZ; break;
+ default:
+ assert(0 && "Unrecognized VM instruction!");
+ opCode = INVALID_OPCODE;
+ break;
+ }
+
+ return opCode;
+}
+
+
+static inline MachineOpCode
+ChooseBccInstruction(const InstructionNode* instrNode,
+ bool& isFPBranch)
+{
+ InstructionNode* setCCNode = (InstructionNode*) instrNode->leftChild();
+ BinaryOperator* setCCInstr = (BinaryOperator*) setCCNode->getInstruction();
+ const Type* setCCType = setCCInstr->getOperand(0)->getType();
+
+ isFPBranch = (setCCType == Type::FloatTy || setCCType == Type::DoubleTy);
+
+ if (isFPBranch)
+ return ChooseBFpccInstruction(instrNode, setCCInstr);
+ else
+ return ChooseBpccInstruction(instrNode, setCCInstr);
+}
+
+
+static inline MachineOpCode
+ChooseBpccInstruction(const InstructionNode* instrNode,
+ const BinaryOperator* setCCInstr)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ bool isSigned = setCCInstr->getOperand(0)->getType()->isSigned();
+
+ if (isSigned)
+ {
+ switch(setCCInstr->getOpcode())
+ {
+ case Instruction::SetEQ: opCode = BE; break;
+ case Instruction::SetNE: opCode = BNE; break;
+ case Instruction::SetLE: opCode = BLE; break;
+ case Instruction::SetGE: opCode = BGE; break;
+ case Instruction::SetLT: opCode = BL; break;
+ case Instruction::SetGT: opCode = BG; break;
+ default:
+ assert(0 && "Unrecognized VM instruction!");
+ break;
+ }
+ }
+ else
+ {
+ switch(setCCInstr->getOpcode())
+ {
+ case Instruction::SetEQ: opCode = BE; break;
+ case Instruction::SetNE: opCode = BNE; break;
+ case Instruction::SetLE: opCode = BLEU; break;
+ case Instruction::SetGE: opCode = BCC; break;
+ case Instruction::SetLT: opCode = BCS; break;
+ case Instruction::SetGT: opCode = BGU; break;
+ default:
+ assert(0 && "Unrecognized VM instruction!");
+ break;
+ }
+ }
+
+ return opCode;
+}
+
+static inline MachineOpCode
+ChooseBFpccInstruction(const InstructionNode* instrNode,
+ const BinaryOperator* setCCInstr)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ switch(setCCInstr->getOpcode())
+ {
+ case Instruction::SetEQ: opCode = FBE; break;
+ case Instruction::SetNE: opCode = FBNE; break;
+ case Instruction::SetLE: opCode = FBLE; break;
+ case Instruction::SetGE: opCode = FBGE; break;
+ case Instruction::SetLT: opCode = FBL; break;
+ case Instruction::SetGT: opCode = FBG; break;
+ default:
+ assert(0 && "Unrecognized VM instruction!");
+ break;
+ }
+
+ return opCode;
+}
+
+
+static inline MachineOpCode
+ChooseMovFpccInstruction(const InstructionNode* instrNode)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ switch(instrNode->getInstruction()->getOpcode())
+ {
+ case Instruction::SetEQ: opCode = MOVFE; break;
+ case Instruction::SetNE: opCode = MOVFNE; break;
+ case Instruction::SetLE: opCode = MOVFLE; break;
+ case Instruction::SetGE: opCode = MOVFGE; break;
+ case Instruction::SetLT: opCode = MOVFL; break;
+ case Instruction::SetGT: opCode = MOVFG; break;
+ default:
+ assert(0 && "Unrecognized VM instruction!");
+ break;
+ }
+
+ return opCode;
+}
+
+
+// Assumes that SUBcc v1, v2 -> v3 has been executed.
+// In most cases, we want to clear v3 and then follow it by instruction
+// MOVcc 1 -> v3.
+// Set mustClearReg=false if v3 need not be cleared before conditional move.
+// Set valueToMove=0 if we want to conditionally move 0 instead of 1
+// (i.e., we want to test inverse of a condition)
+//
+//
+static MachineOpCode
+ChooseMovpccAfterSub(const InstructionNode* instrNode,
+ bool& mustClearReg,
+ int& valueToMove)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+ mustClearReg = true;
+ valueToMove = 1;
+
+ switch(instrNode->getInstruction()->getOpcode())
+ {
+ case Instruction::SetEQ: opCode = MOVNE; mustClearReg = false;
+ valueToMove = 0; break;
+ case Instruction::SetLE: opCode = MOVLE; break;
+ case Instruction::SetGE: opCode = MOVGE; break;
+ case Instruction::SetLT: opCode = MOVL; break;
+ case Instruction::SetGT: opCode = MOVG; break;
+
+ case Instruction::SetNE: assert(0 && "No move required!");
+
+ default:
+ assert(0 && "Unrecognized VM instruction!");
+ break;
+ }
+
+ return opCode;
+}
+
+
+static inline MachineOpCode
+ChooseConvertToFloatInstr(const InstructionNode* instrNode,
+ const Type* opType)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ switch(instrNode->getOpLabel())
+ {
+ case ToFloatTy:
+ if (opType == Type::SByteTy || opType == Type::ShortTy || opType == Type::IntTy)
+ opCode = FITOS;
+ else if (opType == Type::LongTy)
+ opCode = FXTOS;
+ else if (opType == Type::DoubleTy)
+ opCode = FDTOS;
+ else
+ assert(0 && "Cannot convert this type to FLOAT on SPARC");
+ break;
+
+ case ToDoubleTy:
+ if (opType == Type::SByteTy || opType == Type::ShortTy || opType == Type::IntTy)
+ opCode = FITOD;
+ else if (opType == Type::LongTy)
+ opCode = FXTOD;
+ else if (opType == Type::FloatTy)
+ opCode = FSTOD;
+ else
+ assert(0 && "Cannot convert this type to DOUBLE on SPARC");
+ break;
+
+ default:
+ break;
+ }
+
+ return opCode;
+}
+
+static inline MachineOpCode
+ChooseConvertToIntInstr(const InstructionNode* instrNode,
+ const Type* opType)
+{
+ MachineOpCode opCode = INVALID_OPCODE;;
+
+ int instrType = (int) instrNode->getOpLabel();
+
+ if (instrType == ToSByteTy || instrType == ToShortTy || instrType == ToIntTy)
+ {
+ switch (opType->getPrimitiveID())
+ {
+ case Type::FloatTyID: opCode = FSTOI; break;
+ case Type::DoubleTyID: opCode = FDTOI; break;
+ default:
+ assert(0 && "Non-numeric non-bool type cannot be converted to Int");
+ break;
+ }
+ }
+ else if (instrType == ToLongTy)
+ {
+ switch (opType->getPrimitiveID())
+ {
+ case Type::FloatTyID: opCode = FSTOX; break;
+ case Type::DoubleTyID: opCode = FDTOX; break;
+ default:
+ assert(0 && "Non-numeric non-bool type cannot be converted to Long");
+ break;
+ }
+ }
+ else
+ assert(0 && "Should not get here, Mo!");
+
+ return opCode;
+}
+
+
+static inline MachineOpCode
+ChooseAddInstruction(const InstructionNode* instrNode)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ const Type* resultType = instrNode->getInstruction()->getType();
+
+ if (resultType->isIntegral() ||
+ resultType->isPointerType() ||
+ resultType->isMethodType() ||
+ resultType->isLabelType())
+ {
+ opCode = ADD;
+ }
+ else
+ {
+ Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
+ switch(operand->getType()->getPrimitiveID())
+ {
+ case Type::FloatTyID: opCode = FADDS; break;
+ case Type::DoubleTyID: opCode = FADDD; break;
+ default: assert(0 && "Invalid type for ADD instruction"); break;
+ }
+ }
+
+ return opCode;
+}
+
+
+static inline MachineInstr*
+CreateMovFloatInstruction(const InstructionNode* instrNode,
+ const Type* resultType)
+{
+ MachineInstr* minstr = new MachineInstr((resultType == Type::FloatTy)
+ ? FMOVS : FMOVD);
+ minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ instrNode->leftChild()->getValue());
+ minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
+ instrNode->getValue());
+ return minstr;
+}
+
+static inline MachineInstr*
+CreateAddConstInstruction(const InstructionNode* instrNode)
+{
+ MachineInstr* minstr = NULL;
+
+ Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
+ assert(constOp->getValueType() == Value::ConstantVal);
+
+ // Cases worth optimizing are:
+ // (1) Add with 0 for float or double: use an FMOV of appropriate type,
+ // instead of an FADD (1 vs 3 cycles). There is no integer MOV.
+ //
+ const Type* resultType = instrNode->getInstruction()->getType();
+
+ if (resultType == Type::FloatTy ||
+ resultType == Type::DoubleTy)
+ {
+ double dval = ((ConstPoolFP*) constOp)->getValue();
+ if (dval == 0.0)
+ minstr = CreateMovFloatInstruction(instrNode, resultType);
+ }
+
+ return minstr;
+}
+
+
+static inline MachineOpCode
+ChooseSubInstruction(const InstructionNode* instrNode)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ const Type* resultType = instrNode->getInstruction()->getType();
+
+ if (resultType->isIntegral() ||
+ resultType->isPointerType())
+ {
+ opCode = SUB;
+ }
+ else
+ {
+ Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
+ switch(operand->getType()->getPrimitiveID())
+ {
+ case Type::FloatTyID: opCode = FSUBS; break;
+ case Type::DoubleTyID: opCode = FSUBD; break;
+ default: assert(0 && "Invalid type for SUB instruction"); break;
+ }
+ }
+
+ return opCode;
+}
+
+
+static inline MachineInstr*
+CreateSubConstInstruction(const InstructionNode* instrNode)
+{
+ MachineInstr* minstr = NULL;
+
+ Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
+ assert(constOp->getValueType() == Value::ConstantVal);
+
+ // Cases worth optimizing are:
+ // (1) Sub with 0 for float or double: use an FMOV of appropriate type,
+ // instead of an FSUB (1 vs 3 cycles). There is no integer MOV.
+ //
+ const Type* resultType = instrNode->getInstruction()->getType();
+
+ if (resultType == Type::FloatTy ||
+ resultType == Type::DoubleTy)
+ {
+ double dval = ((ConstPoolFP*) constOp)->getValue();
+ if (dval == 0.0)
+ minstr = CreateMovFloatInstruction(instrNode, resultType);
+ }
+
+ return minstr;
+}
+
+
+static inline MachineOpCode
+ChooseFcmpInstruction(const InstructionNode* instrNode)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
+ switch(operand->getType()->getPrimitiveID())
+ {
+ case Type::FloatTyID: opCode = FCMPS; break;
+ case Type::DoubleTyID: opCode = FCMPD; break;
+ default: assert(0 && "Invalid type for FCMP instruction"); break;
+ }
+
+ return opCode;
+}
+
+
+// Assumes that leftArg and rightArg are both cast instructions.
+//
+static inline bool
+BothFloatToDouble(const InstructionNode* instrNode)
+{
+ InstrTreeNode* leftArg = instrNode->leftChild();
+ InstrTreeNode* rightArg = instrNode->rightChild();
+ InstrTreeNode* leftArgArg = leftArg->leftChild();
+ InstrTreeNode* rightArgArg = rightArg->leftChild();
+ assert(leftArg->getValue()->getType() == rightArg->getValue()->getType());
+
+ // Check if both arguments are floats cast to double
+ return (leftArg->getValue()->getType() == Type::DoubleTy &&
+ leftArgArg->getValue()->getType() == Type::FloatTy &&
+ rightArgArg->getValue()->getType() == Type::FloatTy);
+}
+
+
+static inline MachineOpCode
+ChooseMulInstruction(const InstructionNode* instrNode,
+ bool checkCasts)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ if (checkCasts && BothFloatToDouble(instrNode))
+ {
+ return opCode = FSMULD;
+ }
+ // else fall through and use the regular multiply instructions
+
+ const Type* resultType = instrNode->getInstruction()->getType();
+
+ if (resultType->isIntegral())
+ {
+ opCode = MULX;
+ }
+ else
+ {
+ switch(instrNode->leftChild()->getValue()->getType()->getPrimitiveID())
+ {
+ case Type::FloatTyID: opCode = FMULS; break;
+ case Type::DoubleTyID: opCode = FMULD; break;
+ default: assert(0 && "Invalid type for MUL instruction"); break;
+ }
+ }
+
+ return opCode;
+}
+
+
+static inline MachineInstr*
+CreateIntNegInstruction(Value* vreg)
+{
+ MachineInstr* minstr = new MachineInstr(SUB);
+ minstr->SetMachineOperand(0, /*regNum %g0*/(unsigned int) 0);
+ minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, vreg);
+ minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, vreg);
+ return minstr;
+}
+
+
+static inline MachineInstr*
+CreateMulConstInstruction(const InstructionNode* instrNode,
+ MachineInstr*& getMinstr2)
+{
+ MachineInstr* minstr = NULL;
+ getMinstr2 = NULL;
+ bool needNeg = false;
+
+ Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
+ assert(constOp->getValueType() == Value::ConstantVal);
+
+ // Cases worth optimizing are:
+ // (1) Multiply by 0 or 1 for any type: replace with copy (ADD or FMOV)
+ // (2) Multiply by 2^x for integer types: replace with Shift
+ //
+ const Type* resultType = instrNode->getInstruction()->getType();
+
+ if (resultType->isIntegral())
+ {
+ unsigned pow;
+ bool isValidConst;
+ int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
+ if (isValidConst)
+ {
+ bool needNeg = false;
+ if (C < 0)
+ {
+ needNeg = true;
+ C = -C;
+ }
+
+ if (C == 0 || C == 1)
+ {
+ minstr = new MachineInstr(ADD);
+
+ if (C == 0)
+ minstr->SetMachineOperand(0, /*regNum %g0*/ (unsigned int) 0);
+ else
+ minstr->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
+ instrNode->leftChild()->getValue());
+ minstr->SetMachineOperand(1, /*regNum %g0*/ (unsigned int) 0);
+ }
+ else if (IsPowerOf2(C, pow))
+ {
+ minstr = new MachineInstr((resultType == Type::LongTy)
+ ? SLLX : SLL);
+ minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ instrNode->leftChild()->getValue());
+ minstr->SetMachineOperand(1, MachineOperand::MO_UnextendedImmed,
+ pow);
+ }
+
+ if (minstr && needNeg)
+ { // insert <reg = SUB 0, reg> after the instr to flip the sign
+ getMinstr2 = CreateIntNegInstruction(instrNode->getValue());
+ }
+ }
+ }
+ else
+ {
+ if (resultType == Type::FloatTy ||
+ resultType == Type::DoubleTy)
+ {
+ bool isValidConst;
+ double dval = ((ConstPoolFP*) constOp)->getValue();
+
+ if (isValidConst)
+ {
+ if (dval == 0)
+ {
+ minstr = new MachineInstr((resultType == Type::FloatTy)
+ ? FITOS : FITOD);
+ minstr->SetMachineOperand(0, /*regNum %g0*/(unsigned int) 0);
+ }
+ else if (fabs(dval) == 1)
+ {
+ bool needNeg = (dval < 0);
+
+ MachineOpCode opCode = needNeg
+ ? (resultType == Type::FloatTy? FNEGS : FNEGD)
+ : (resultType == Type::FloatTy? FMOVS : FMOVD);
+
+ minstr = new MachineInstr(opCode);
+ minstr->SetMachineOperand(0,
+ MachineOperand::MO_VirtualRegister,
+ instrNode->leftChild()->getValue());
+ }
+ }
+ }
+ }
+
+ if (minstr != NULL)
+ minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
+ instrNode->getValue());
+
+ return minstr;
+}
+
+
+static inline MachineOpCode
+ChooseDivInstruction(const InstructionNode* instrNode)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ const Type* resultType = instrNode->getInstruction()->getType();
+
+ if (resultType->isIntegral())
+ {
+ opCode = resultType->isSigned()? SDIVX : UDIVX;
+ }
+ else
+ {
+ Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
+ switch(operand->getType()->getPrimitiveID())
+ {
+ case Type::FloatTyID: opCode = FDIVS; break;
+ case Type::DoubleTyID: opCode = FDIVD; break;
+ default: assert(0 && "Invalid type for DIV instruction"); break;
+ }
+ }
+
+ return opCode;
+}
+
+
+static inline MachineInstr*
+CreateDivConstInstruction(const InstructionNode* instrNode,
+ MachineInstr*& getMinstr2)
+{
+ MachineInstr* minstr = NULL;
+ getMinstr2 = NULL;
+
+ Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
+ assert(constOp->getValueType() == Value::ConstantVal);
+
+ // Cases worth optimizing are:
+ // (1) Divide by 1 for any type: replace with copy (ADD or FMOV)
+ // (2) Divide by 2^x for integer types: replace with SR[L or A]{X}
+ //
+ const Type* resultType = instrNode->getInstruction()->getType();
+
+ if (resultType->isIntegral())
+ {
+ unsigned pow;
+ bool isValidConst;
+ int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst);
+ if (isValidConst)
+ {
+ bool needNeg = false;
+ if (C < 0)
+ {
+ needNeg = true;
+ C = -C;
+ }
+
+ if (C == 1)
+ {
+ minstr = new MachineInstr(ADD);
+ minstr->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
+ instrNode->leftChild()->getValue());
+ minstr->SetMachineOperand(1, /*regNum %g0*/ (unsigned int) 0);
+ }
+ else if (IsPowerOf2(C, pow))
+ {
+ MachineOpCode opCode= ((resultType->isSigned())
+ ? (resultType==Type::LongTy)? SRAX : SRA
+ : (resultType==Type::LongTy)? SRLX : SRL);
+ minstr = new MachineInstr(opCode);
+ minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ instrNode->leftChild()->getValue());
+ minstr->SetMachineOperand(1, MachineOperand::MO_UnextendedImmed,
+ pow);
+ }
+
+ if (minstr && needNeg)
+ { // insert <reg = SUB 0, reg> after the instr to flip the sign
+ getMinstr2 = CreateIntNegInstruction(instrNode->getValue());
+ }
+ }
+ }
+ else
+ {
+ if (resultType == Type::FloatTy ||
+ resultType == Type::DoubleTy)
+ {
+ bool isValidConst;
+ double dval = ((ConstPoolFP*) constOp)->getValue();
+
+ if (isValidConst && fabs(dval) == 1)
+ {
+ bool needNeg = (dval < 0);
+
+ MachineOpCode opCode = needNeg
+ ? (resultType == Type::FloatTy? FNEGS : FNEGD)
+ : (resultType == Type::FloatTy? FMOVS : FMOVD);
+
+ minstr = new MachineInstr(opCode);
+ minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ instrNode->leftChild()->getValue());
+ }
+ }
+ }
+
+ if (minstr != NULL)
+ minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
+ instrNode->getValue());
+
+ return minstr;
+}
+
+
+static inline MachineOpCode
+ChooseLoadInstruction(const Type* resultType)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ switch (resultType->getPrimitiveID())
+ {
+ case Type::BoolTyID: opCode = LDUB; break;
+ case Type::UByteTyID: opCode = LDUB; break;
+ case Type::SByteTyID: opCode = LDSB; break;
+ case Type::UShortTyID: opCode = LDUH; break;
+ case Type::ShortTyID: opCode = LDSH; break;
+ case Type::UIntTyID: opCode = LDUW; break;
+ case Type::IntTyID: opCode = LDSW; break;
+ case Type::ULongTyID:
+ case Type::LongTyID: opCode = LDX; break;
+ case Type::FloatTyID: opCode = LD; break;
+ case Type::DoubleTyID: opCode = LDD; break;
+ default: assert(0 && "Invalid type for Load instruction"); break;
+ }
+
+ return opCode;
+}
+
+
+static inline MachineOpCode
+ChooseStoreInstruction(const Type* valueType)
+{
+ MachineOpCode opCode = INVALID_OPCODE;
+
+ switch (valueType->getPrimitiveID())
+ {
+ case Type::BoolTyID:
+ case Type::UByteTyID:
+ case Type::SByteTyID: opCode = STB; break;
+ case Type::UShortTyID:
+ case Type::ShortTyID: opCode = STH; break;
+ case Type::UIntTyID:
+ case Type::IntTyID: opCode = STW; break;
+ case Type::ULongTyID:
+ case Type::LongTyID: opCode = STX; break;
+ case Type::FloatTyID: opCode = ST; break;
+ case Type::DoubleTyID: opCode = STD; break;
+ default: assert(0 && "Invalid type for Store instruction"); break;
+ }
+
+ return opCode;
+}
+
+
+//------------------------------------------------------------------------
+// Function SetOperandsForMemInstr
+//
+// Choose addressing mode for the given load or store instruction.
+// Use [reg+reg] if it is an indexed reference, and the index offset is
+// not a constant or if it cannot fit in the offset field.
+// Use [reg+offset] in all other cases.
+//
+// This assumes that all array refs are "lowered" to one of these forms:
+// %x = load (subarray*) ptr, constant ; single constant offset
+// %x = load (subarray*) ptr, offsetVal ; single non-constant offset
+// Generally, this should happen via strength reduction + LICM.
+// Also, strength reduction should take care of using the same register for
+// the loop index variable and an array index, when that is profitable.
+//------------------------------------------------------------------------
+
+static void
+SetOperandsForMemInstr(MachineInstr* minstr,
+ const InstructionNode* vmInstrNode,
+ const TargetMachine& target)
+{
+ MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
+
+ // Variables to hold the index vector, ptr value, and offset value.
+ // The major work here is to extract these for all 3 instruction types
+ // and then call the common function SetMemOperands_Internal().
+ //
+ const vector<ConstPoolVal*>* idxVec = & memInst->getIndexVec();
+ vector<ConstPoolVal*>* newIdxVec = NULL;
+ Value* ptrVal;
+ Value* arrayOffsetVal = NULL;
+
+ // Test if a GetElemPtr instruction is being folded into this mem instrn.
+ // If so, it will be in the left child for Load and GetElemPtr,
+ // and in the right child for Store instructions.
+ //
+ InstrTreeNode* ptrChild = (vmInstrNode->getOpLabel() == Instruction::Store
+ ? vmInstrNode->rightChild()
+ : vmInstrNode->leftChild());
+
+ if (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
+ ptrChild->getOpLabel() == GetElemPtrIdx)
+ {
+ // There is a GetElemPtr instruction and there may be a chain of
+ // more than one. Use the pointer value of the last one in the chain.
+ // Fold the index vectors from the entire chain and from the mem
+ // instruction into one single index vector.
+ // Finally, we never fold for an array instruction so make that NULL.
+
+ newIdxVec = new vector<ConstPoolVal*>;
+ ptrVal = FoldGetElemChain((InstructionNode*) ptrChild, *newIdxVec);
+
+ newIdxVec->insert(newIdxVec->end(), idxVec->begin(), idxVec->end());
+ idxVec = newIdxVec;
+
+ assert(! ((PointerType*)ptrVal->getType())->getValueType()->isArrayType()
+ && "GetElemPtr cannot be folded into array refs in selection");
+ }
+ else
+ {
+ // There is no GetElemPtr instruction.
+ // Use the pointer value and the index vector from the Mem instruction.
+ // If it is an array reference, get the array offset value.
+ //
+ ptrVal = memInst->getPtrOperand();
+
+ const Type* opType =
+ ((const PointerType*) ptrVal->getType())->getValueType();
+ if (opType->isArrayType())
+ {
+ assert((memInst->getNumOperands()
+ == (unsigned) 1 + memInst->getFirstOffsetIdx())
+ && "Array refs must be lowered before Instruction Selection");
+
+ arrayOffsetVal = memInst->getOperand(memInst->getFirstOffsetIdx());
+ }
+ }
+
+ SetMemOperands_Internal(minstr, vmInstrNode, ptrVal, arrayOffsetVal,
+ *idxVec, target);
+
+ if (newIdxVec != NULL)
+ delete newIdxVec;
+}
+
+
+static void
+SetMemOperands_Internal(MachineInstr* minstr,
+ const InstructionNode* vmInstrNode,
+ Value* ptrVal,
+ Value* arrayOffsetVal,
+ const vector<ConstPoolVal*>& idxVec,
+ const TargetMachine& target)
+{
+ MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
+
+ // Initialize so we default to storing the offset in a register.
+ int64_t smallConstOffset;
+ Value* valueForRegOffset = NULL;
+ MachineOperand::MachineOperandType offsetOpType =MachineOperand::MO_VirtualRegister;
+
+ // Check if there is an index vector and if so, if it translates to
+ // a small enough constant to fit in the immediate-offset field.
+ //
+ if (idxVec.size() > 0)
+ {
+ bool isConstantOffset = false;
+ unsigned offset;
+
+ const PointerType* ptrType = (PointerType*) ptrVal->getType();
+
+ if (ptrType->getValueType()->isStructType())
+ {
+ // the offset is always constant for structs
+ isConstantOffset = true;
+
+ // Compute the offset value using the index vector
+ offset = target.DataLayout.getIndexedOffset(ptrType, idxVec);
+ }
+ else
+ {
+ // It must be an array ref. Check if the offset is a constant,
+ // and that the indexing has been lowered to a single offset.
+ //
+ assert(ptrType->getValueType()->isArrayType());
+ assert(arrayOffsetVal != NULL
+ && "Expect to be given Value* for array offsets");
+
+ if (ConstPoolVal *CPV = arrayOffsetVal->castConstant())
+ {
+ isConstantOffset = true; // always constant for structs
+ assert(arrayOffsetVal->getType()->isIntegral());
+ offset = (CPV->getType()->isSigned()
+ ? ((ConstPoolSInt*)CPV)->getValue()
+ : (int64_t) ((ConstPoolUInt*)CPV)->getValue());
+ }
+ else
+ {
+ valueForRegOffset = arrayOffsetVal;
+ }
+ }
+
+ if (isConstantOffset)
+ {
+ // create a virtual register for the constant
+ valueForRegOffset = new ConstPoolSInt(Type::IntTy, offset);
+ }
+ }
+ else
+ {
+ offsetOpType = MachineOperand::MO_SignExtendedImmed;
+ smallConstOffset = 0;
+ }
+
+ // Operand 0 is value for STORE, ptr for LOAD or GET_ELEMENT_PTR
+ // It is the left child in the instruction tree in all cases.
+ Value* leftVal = vmInstrNode->leftChild()->getValue();
+ minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, leftVal);
+
+ // Operand 1 is ptr for STORE, offset for LOAD or GET_ELEMENT_PTR
+ // Operand 3 is offset for STORE, result reg for LOAD or GET_ELEMENT_PTR
+ //
+ unsigned offsetOpNum = (memInst->getOpcode() == Instruction::Store)? 2 : 1;
+ if (offsetOpType == MachineOperand::MO_VirtualRegister)
+ {
+ assert(valueForRegOffset != NULL);
+ minstr->SetMachineOperand(offsetOpNum, offsetOpType, valueForRegOffset);
+ }
+ else
+ minstr->SetMachineOperand(offsetOpNum, offsetOpType, smallConstOffset);
+
+ if (memInst->getOpcode() == Instruction::Store)
+ minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, ptrVal);
+ else
+ minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
+ vmInstrNode->getValue());
+}
+
+
+// Special handling for constant operands:
+// -- if the constant is 0, use the hardwired 0 register, if any;
+// -- if the constant is of float or double type but has an integer value,
+// use int-to-float conversion instruction instead of generating a load;
+// -- if the constant fits in the IMMEDIATE field, use that field;
+// -- else insert instructions to put the constant into a register, either
+// directly or by loading explicitly from the constant pool.
+//
+static unsigned
+FixConstantOperands(const InstructionNode* vmInstrNode,
+ MachineInstr** mvec,
+ unsigned numInstr,
+ TargetMachine& target)
+{
+ static MachineInstr* loadConstVec[MAX_INSTR_PER_VMINSTR];
+
+ unsigned numNew = 0;
+ Instruction* vmInstr = vmInstrNode->getInstruction();
+
+ for (unsigned i=0; i < numInstr; i++)
+ {
+ MachineInstr* minstr = mvec[i];
+ const MachineInstrDescriptor& instrDesc =
+ target.getInstrInfo().getDescriptor(minstr->getOpCode());
+
+ for (unsigned op=0; op < minstr->getNumOperands(); op++)
+ {
+ const MachineOperand& mop = minstr->getOperand(op);
+
+ // skip the result position (for efficiency below) and any other
+ // positions already marked as not a virtual register
+ if (instrDesc.resultPos == (int) op ||
+ mop.getOperandType() != MachineOperand::MO_VirtualRegister ||
+ mop.getVRegValue() == NULL)
+ {
+ break;
+ }
+
+ Value* opValue = mop.getVRegValue();
+
+ if (opValue->getValueType() == Value::ConstantVal)
+ {
+ unsigned int machineRegNum;
+ int64_t immedValue;
+ MachineOperand::MachineOperandType opType =
+ ChooseRegOrImmed(opValue, minstr->getOpCode(), target,
+ /*canUseImmed*/ (op == 1),
+ machineRegNum, immedValue);
+
+ if (opType == MachineOperand::MO_MachineRegister)
+ minstr->SetMachineOperand(op, machineRegNum);
+ else if (opType == MachineOperand::MO_VirtualRegister)
+ {
+ // value is constant and must be loaded into a register
+ TmpInstruction* tmpReg;
+ MachineInstr* minstr2;
+ loadConstVec[numNew++] = MakeLoadConstInstr(vmInstr, opValue,
+ tmpReg, minstr2);
+ minstr->SetMachineOperand(op, opType, tmpReg);
+ if (minstr2 != NULL)
+ loadConstVec[numNew++] = minstr2;
+ }
+ else
+ minstr->SetMachineOperand(op, opType, immedValue);
+ }
+ }
+ }
+
+ if (numNew > 0)
+ {
+ // Insert the new instructions *before* the old ones by moving
+ // the old ones over `numNew' positions (last-to-first, of course!).
+ // We do check *after* returning that we did not exceed the vector mvec.
+ for (int i=numInstr-1; i >= 0; i--)
+ mvec[i+numNew] = mvec[i];
+
+ for (unsigned i=0; i < numNew; i++)
+ mvec[i] = loadConstVec[i];
+ }
+
+ return (numInstr + numNew);
+}
+
+
+static inline MachineInstr*
+MakeIntSetInstruction(int64_t C, bool isSigned, Value* dest)
+{
+ MachineInstr* minstr;
+ if (isSigned)
+ {
+ minstr = new MachineInstr(SETSW);
+ minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, C);
+ }
+ else
+ {
+ minstr = new MachineInstr(SETUW);
+ minstr->SetMachineOperand(0, MachineOperand::MO_UnextendedImmed, C);
+ }
+
+ minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, dest);
+
+ return minstr;
+}
+
+
+static MachineInstr*
+MakeLoadConstInstr(Instruction* vmInstr,
+ Value* val,
+ TmpInstruction*& tmpReg,
+ MachineInstr*& getMinstr2)
+{
+ assert(val->getValueType() == Value::ConstantVal);
+
+ MachineInstr* minstr;
+
+ getMinstr2 = NULL;
+
+ // Create a TmpInstruction to mark the hidden register used for the constant
+ tmpReg = new TmpInstruction(Instruction::UserOp1, val, NULL);
+ vmInstr->getMachineInstrVec().addTempValue(tmpReg);
+
+ // Use a "set" instruction for known constants that can go in an integer reg.
+ // Use a "set" instruction followed by a int-to-float conversion for known
+ // constants that must go in a floating point reg but have an integer value.
+ // Use a "load" instruction for all other constants, in particular,
+ // floating point constants.
+ //
+ const Type* valType = val->getType();
+
+ if (valType->isIntegral() ||
+ valType->isPointerType() ||
+ valType == Type::BoolTy)
+ {
+ bool isValidConstant;
+ int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
+ assert(isValidConstant && "Unrecognized constant");
+
+ minstr = MakeIntSetInstruction(C, valType->isSigned(), tmpReg);
+ }
+ else
+ {
+ assert(valType == Type::FloatTy || valType == Type::DoubleTy);
+ double dval = ((ConstPoolFP*) val)->getValue();
+ if (dval == (int64_t) dval)
+ {
+ // The constant actually has an integer value, so use a
+ // [set; int-to-float] sequence instead of a load instruction.
+ //
+ TmpInstruction* tmpReg2 = NULL;
+ if (dval != 0.0)
+ { // First, create an integer constant of the same value as dval
+ ConstPoolSInt* ival = new ConstPoolSInt(Type::IntTy,
+ (int64_t) dval);
+ ConstantPool& cpool =
+ vmInstr->getParent()->getParent()->getConstantPool();
+ ConstPoolVal* prev = cpool.find(ival);
+ if (prev == NULL)
+ cpool.insert(ival);
+ else
+ {
+ delete ival;
+ ival = (ConstPoolSInt*) prev;
+ }
+
+ // Create another TmpInstruction for the hidden integer register
+ TmpInstruction* tmpReg2 =
+ new TmpInstruction(Instruction::UserOp1, ival, NULL);
+ vmInstr->getMachineInstrVec().addTempValue(tmpReg2);
+
+ // Create the `SET' instruction
+ minstr = MakeIntSetInstruction((int64_t)dval, true, tmpReg2);
+ }
+
+ // In which variable do we put the second instruction?
+ MachineInstr*& instr2 = (minstr)? getMinstr2 : minstr;
+
+ // Create the int-to-float instruction
+ instr2 = new MachineInstr(valType == Type::FloatTy? FITOS : FITOD);
+
+ if (dval == 0.0)
+ instr2->SetMachineOperand(0, /*regNum %g0*/ (unsigned int) 0);
+ else
+ instr2->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
+ tmpReg2);
+
+ instr2->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
+ tmpReg);
+ }
+ else
+ {
+ // Make a Load instruction, and make `val' both the ptr value *and*
+ // the result value, and set the offset field to 0. Final code
+ // generation will have to generate the base+offset for the constant.
+ //
+ int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
+ minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
+ minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,val);
+ minstr->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
+ zeroOffset);
+ minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
+ tmpReg);
+ }
+ }
+
+ tmpReg->addMachineInstruction(minstr);
+
+ assert(minstr);
+ return minstr;
+}
+
+//
+// Substitute operand `operandNum' of the instruction in node `treeNode'
+// in place the use(s) of that instruction in node `parent'.
+//
+static void
+ForwardOperand(InstructionNode* treeNode,
+ InstructionNode* parent,
+ int operandNum)
+{
+ Instruction* unusedOp = treeNode->getInstruction();
+ Value* fwdOp = unusedOp->getOperand(operandNum);
+ Instruction* userInstr = parent->getInstruction();
+ MachineCodeForVMInstr& mvec = userInstr->getMachineInstrVec();
+ for (unsigned i=0, N=mvec.size(); i < N; i++)
+ {
+ MachineInstr* minstr = mvec[i];
+ for (unsigned i=0, numOps=minstr->getNumOperands(); i < numOps; i++)
+ {
+ const MachineOperand& mop = minstr->getOperand(i);
+ if (mop.getOperandType() == MachineOperand::MO_VirtualRegister &&
+ mop.getVRegValue() == unusedOp)
+ {
+ minstr->SetMachineOperand(i, MachineOperand::MO_VirtualRegister,
+ fwdOp);
+ }
+ }
+ }
+}
+
+
+// This function is currently unused and incomplete but will be
+// used if we have a linear layout of basic blocks in LLVM code.
+// It decides which branch should fall-through, and whether an
+// extra unconditional branch is needed (when neither falls through).
+//
+void
+ChooseBranchPattern(Instruction* vmInstr, BranchPattern& brPattern)
+{
+ BranchInst* brInstr = (BranchInst*) vmInstr;
+
+ brPattern.flipCondition = false;
+ brPattern.targetBB = brInstr->getSuccessor(0);
+ brPattern.extraBranch = NULL;
+
+ assert(brInstr->getNumSuccessors() > 1 &&
+ "Unnecessary analysis for unconditional branch");
+
+ assert(0 && "Fold branches in peephole optimization");
+}
+
+
+//******************* Externally Visible Functions *************************/
+
+
//------------------------------------------------------------------------
// External Function: GetInstructionsByRule
//
@@ -205,7 +1347,8 @@
mvec[0]->SetMachineOperand(1, MachineOperand::MO_PCRelativeDisp,
((BranchInst*) subtreeRoot->getInstruction())->getSuccessor(0));
- mvec[numInstr++] = new MachineInstr(NOP); // delay slot
+ // delay slot
+ mvec[numInstr++] = new MachineInstr(NOP);
break;
case 6: // stmt: BrCond(boolconst)
@@ -239,6 +1382,10 @@
mvec[numInstr-1]->SetMachineOperand(0, MachineOperand::MO_CCRegister,
(Value*) NULL);
mvec[numInstr-1]->SetMachineOperand(1, MachineOperand::MO_PCRelativeDisp, ((BranchInst*) subtreeRoot->getInstruction())->getSuccessor(1));
+
+ // delay slot
+ mvec[numInstr++] = new MachineInstr(NOP);
+
break;
}
// ELSE FALL THROUGH
@@ -266,6 +1413,9 @@
(Value*) NULL);
mvec[numInstr-1]->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp,
((BranchInst*) subtreeRoot->getInstruction())->getSuccessor(1));
+
+ // delay slot
+ mvec[numInstr++] = new MachineInstr(NOP);
break;
}
@@ -278,7 +1428,19 @@
subtreeRoot->leftChild()->getValue());
mvec[0]->SetMachineOperand(1, MachineOperand::MO_PCRelativeDisp,
((BranchInst*) subtreeRoot->getInstruction())->getSuccessor(0));
+
+ // delay slot
mvec[numInstr++] = new MachineInstr(NOP); // delay slot
+
+ // false branch
+ mvec[numInstr++] = new MachineInstr(BA);
+ mvec[numInstr-1]->SetMachineOperand(0, MachineOperand::MO_CCRegister,
+ (Value*) NULL);
+ mvec[numInstr-1]->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp,
+ ((BranchInst*) subtreeRoot->getInstruction())->getSuccessor(1));
+
+ // delay slot
+ mvec[numInstr++] = new MachineInstr(NOP);
break;
case 9: // stmt: Switch(reg)
@@ -364,11 +1526,23 @@
forwardOperandNum = 0;
break;
+ case 233: // reg: Add(reg, Constant)
+ mvec[0] = CreateAddConstInstruction(subtreeRoot);
+ if (mvec[0] != NULL)
+ break;
+ // ELSE FALL THROUGH
+
case 33: // reg: Add(reg, reg)
mvec[0] = new MachineInstr(ChooseAddInstruction(subtreeRoot));
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
+ case 234: // reg: Sub(reg, Constant)
+ mvec[0] = CreateSubConstInstruction(subtreeRoot);
+ if (mvec[0] != NULL)
+ break;
+ // ELSE FALL THROUGH
+
case 34: // reg: Sub(reg, reg)
mvec[0] = new MachineInstr(ChooseSubInstruction(subtreeRoot));
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
@@ -382,17 +1556,45 @@
mvec[0] = new MachineInstr(ChooseMulInstruction(subtreeRoot, checkCast));
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
+
+ case 335: // reg: Mul(todouble, todoubleConst)
+ checkCast = true;
+ // FALL THROUGH
+
+ case 235: // reg: Mul(reg, Constant)
+ mvec[0] = CreateMulConstInstruction(subtreeRoot, mvec[1]);
+ if (mvec[0] == NULL)
+ {
+ mvec[0]=new MachineInstr(ChooseMulInstruction(subtreeRoot, checkCast));
+ Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
+ }
+ else
+ if (mvec[1] != NULL)
+ ++numInstr;
+ break;
+
+ case 236: // reg: Div(reg, Constant)
+ mvec[0] = CreateDivConstInstruction(subtreeRoot, mvec[1]);
+ if (mvec[0] != NULL)
+ {
+ if (mvec[1] != NULL)
+ ++numInstr;
+ }
+ else
+ // ELSE FALL THROUGH
case 36: // reg: Div(reg, reg)
mvec[0] = new MachineInstr(ChooseDivInstruction(subtreeRoot));
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
- case 37: // reg: Rem(reg, reg)
+ case 37: // reg: Rem(reg, reg)
+ case 237: // reg: Rem(reg, Constant)
assert(0 && "REM instruction unimplemented for the SPARC.");
break;
- case 38: // reg: And(reg, reg)
+ case 38: // reg: And(reg, reg)
+ case 238: // reg: And(reg, Constant)
mvec[0] = new MachineInstr(AND);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
@@ -402,7 +1604,8 @@
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
- case 39: // reg: Or(reg, reg)
+ case 39: // reg: Or(reg, reg)
+ case 239: // reg: Or(reg, Constant)
mvec[0] = new MachineInstr(ORN);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
@@ -412,7 +1615,8 @@
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
- case 40: // reg: Xor(reg, reg)
+ case 40: // reg: Xor(reg, reg)
+ case 240: // reg: Xor(reg, Constant)
mvec[0] = new MachineInstr(XOR);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
@@ -717,7 +1921,7 @@
Instruction* phi = subtreeRoot->getInstruction();
mvec[0] = new MachineInstr(PHI, 1 + phi->getNumOperands());
mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
- subtreeRoot->getValue(), true);
+ subtreeRoot->getValue());
for (unsigned i=0, N=phi->getNumOperands(); i < N; i++)
mvec[0]->SetMachineOperand(i+1, MachineOperand::MO_VirtualRegister,
phi->getOperand(i));
@@ -790,858 +1994,3 @@
}
-//---------------------------------------------------------------------------
-// Private helper routines for SPARC instruction selection.
-//---------------------------------------------------------------------------
-
-
-static MachineOpCode
-ChooseBprInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode;
-
- Instruction* setCCInstr =
- ((InstructionNode*) instrNode->leftChild())->getInstruction();
-
- switch(setCCInstr->getOpcode())
- {
- case Instruction::SetEQ: opCode = BRZ; break;
- case Instruction::SetNE: opCode = BRNZ; break;
- case Instruction::SetLE: opCode = BRLEZ; break;
- case Instruction::SetGE: opCode = BRGEZ; break;
- case Instruction::SetLT: opCode = BRLZ; break;
- case Instruction::SetGT: opCode = BRGZ; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- opCode = INVALID_OPCODE;
- break;
- }
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseBccInstruction(const InstructionNode* instrNode,
- bool& isFPBranch)
-{
- InstructionNode* setCCNode = (InstructionNode*) instrNode->leftChild();
- BinaryOperator* setCCInstr = (BinaryOperator*) setCCNode->getInstruction();
- const Type* setCCType = setCCInstr->getOperand(0)->getType();
-
- isFPBranch = (setCCType == Type::FloatTy || setCCType == Type::DoubleTy);
-
- if (isFPBranch)
- return ChooseBFpccInstruction(instrNode, setCCInstr);
- else
- return ChooseBpccInstruction(instrNode, setCCInstr);
-}
-
-
-static MachineOpCode
-ChooseBpccInstruction(const InstructionNode* instrNode,
- const BinaryOperator* setCCInstr)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- bool isSigned = setCCInstr->getOperand(0)->getType()->isSigned();
-
- if (isSigned)
- {
- switch(setCCInstr->getOpcode())
- {
- case Instruction::SetEQ: opCode = BE; break;
- case Instruction::SetNE: opCode = BNE; break;
- case Instruction::SetLE: opCode = BLE; break;
- case Instruction::SetGE: opCode = BGE; break;
- case Instruction::SetLT: opCode = BL; break;
- case Instruction::SetGT: opCode = BG; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
- }
- else
- {
- switch(setCCInstr->getOpcode())
- {
- case Instruction::SetEQ: opCode = BE; break;
- case Instruction::SetNE: opCode = BNE; break;
- case Instruction::SetLE: opCode = BLEU; break;
- case Instruction::SetGE: opCode = BCC; break;
- case Instruction::SetLT: opCode = BCS; break;
- case Instruction::SetGT: opCode = BGU; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
- }
-
- return opCode;
-}
-
-static MachineOpCode
-ChooseBFpccInstruction(const InstructionNode* instrNode,
- const BinaryOperator* setCCInstr)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- switch(setCCInstr->getOpcode())
- {
- case Instruction::SetEQ: opCode = FBE; break;
- case Instruction::SetNE: opCode = FBNE; break;
- case Instruction::SetLE: opCode = FBLE; break;
- case Instruction::SetGE: opCode = FBGE; break;
- case Instruction::SetLT: opCode = FBL; break;
- case Instruction::SetGT: opCode = FBG; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseMovFpccInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- switch(instrNode->getInstruction()->getOpcode())
- {
- case Instruction::SetEQ: opCode = MOVFE; break;
- case Instruction::SetNE: opCode = MOVFNE; break;
- case Instruction::SetLE: opCode = MOVFLE; break;
- case Instruction::SetGE: opCode = MOVFGE; break;
- case Instruction::SetLT: opCode = MOVFL; break;
- case Instruction::SetGT: opCode = MOVFG; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
-
- return opCode;
-}
-
-
-// Assumes that SUBcc v1, v2 -> v3 has been executed.
-// In most cases, we want to clear v3 and then follow it by instruction
-// MOVcc 1 -> v3.
-// Set mustClearReg=false if v3 need not be cleared before conditional move.
-// Set valueToMove=0 if we want to conditionally move 0 instead of 1
-// (i.e., we want to test inverse of a condition)
-//
-//
-static MachineOpCode
-ChooseMovpccAfterSub(const InstructionNode* instrNode,
- bool& mustClearReg,
- int& valueToMove)
-{
- MachineOpCode opCode = INVALID_OPCODE;
- mustClearReg = true;
- valueToMove = 1;
-
- switch(instrNode->getInstruction()->getOpcode())
- {
- case Instruction::SetEQ: opCode = MOVNE; mustClearReg = false;
- valueToMove = 0; break;
- case Instruction::SetLE: opCode = MOVLE; break;
- case Instruction::SetGE: opCode = MOVGE; break;
- case Instruction::SetLT: opCode = MOVL; break;
- case Instruction::SetGT: opCode = MOVG; break;
-
- case Instruction::SetNE: assert(0 && "No move required!");
-
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseConvertToFloatInstr(const InstructionNode* instrNode,
- const Type* opType)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- switch(instrNode->getOpLabel())
- {
- case ToFloatTy:
- if (opType == Type::SByteTy || opType == Type::ShortTy || opType == Type::IntTy)
- opCode = FITOS;
- else if (opType == Type::LongTy)
- opCode = FXTOS;
- else if (opType == Type::DoubleTy)
- opCode = FDTOS;
- else
- assert(0 && "Cannot convert this type to FLOAT on SPARC");
- break;
-
- case ToDoubleTy:
- if (opType == Type::SByteTy || opType == Type::ShortTy || opType == Type::IntTy)
- opCode = FITOD;
- else if (opType == Type::LongTy)
- opCode = FXTOD;
- else if (opType == Type::FloatTy)
- opCode = FSTOD;
- else
- assert(0 && "Cannot convert this type to DOUBLE on SPARC");
- break;
-
- default:
- break;
- }
-
- return opCode;
-}
-
-static MachineOpCode
-ChooseConvertToIntInstr(const InstructionNode* instrNode,
- const Type* opType)
-{
- MachineOpCode opCode = INVALID_OPCODE;;
-
- int instrType = (int) instrNode->getOpLabel();
-
- if (instrType == ToSByteTy || instrType == ToShortTy || instrType == ToIntTy)
- {
- switch (opType->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = FSTOI; break;
- case Type::DoubleTyID: opCode = FDTOI; break;
- default:
- assert(0 && "Non-numeric non-bool type cannot be converted to Int");
- break;
- }
- }
- else if (instrType == ToLongTy)
- {
- switch (opType->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = FSTOX; break;
- case Type::DoubleTyID: opCode = FDTOX; break;
- default:
- assert(0 && "Non-numeric non-bool type cannot be converted to Long");
- break;
- }
- }
- else
- assert(0 && "Should not get here, Mo!");
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseAddInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- const Type* resultType = instrNode->getInstruction()->getType();
-
- if (resultType->isIntegral() ||
- resultType->isPointerType() ||
- resultType->isMethodType() ||
- resultType->isLabelType())
- {
- opCode = ADD;
- }
- else
- {
- Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
- switch(operand->getType()->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = FADDS; break;
- case Type::DoubleTyID: opCode = FADDD; break;
- default: assert(0 && "Invalid type for ADD instruction"); break;
- }
- }
-
- return opCode;
-}
-
-static MachineOpCode
-ChooseSubInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- const Type* resultType = instrNode->getInstruction()->getType();
-
- if (resultType->isIntegral() ||
- resultType->isPointerType())
- {
- opCode = SUB;
- }
- else
- {
- Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
- switch(operand->getType()->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = FSUBS; break;
- case Type::DoubleTyID: opCode = FSUBD; break;
- default: assert(0 && "Invalid type for SUB instruction"); break;
- }
- }
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseFcmpInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
- switch(operand->getType()->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = FCMPS; break;
- case Type::DoubleTyID: opCode = FCMPD; break;
- default: assert(0 && "Invalid type for ADD instruction"); break;
- }
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseMulInstruction(const InstructionNode* instrNode,
- bool checkCasts)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- if (checkCasts)
- {
- // Assume that leftArg and rightArg are both cast instructions.
- //
- InstrTreeNode* leftArg = instrNode->leftChild();
- InstrTreeNode* rightArg = instrNode->rightChild();
- InstrTreeNode* leftArgArg = leftArg->leftChild();
- InstrTreeNode* rightArgArg = rightArg->leftChild();
- assert(leftArg->getValue()->getType() ==rightArg->getValue()->getType());
-
- // If both arguments are floats cast to double, use FsMULd
- if (leftArg->getValue()->getType() == Type::DoubleTy &&
- leftArgArg->getValue()->getType() == Type::FloatTy &&
- rightArgArg->getValue()->getType() == Type::FloatTy)
- {
- return opCode = FSMULD;
- }
- // else fall through and use the regular multiply instructions
- }
-
- const Type* resultType = instrNode->getInstruction()->getType();
-
- if (resultType->isIntegral())
- {
- opCode = MULX;
- }
- else
- {
- switch(instrNode->leftChild()->getValue()->getType()->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = FMULS; break;
- case Type::DoubleTyID: opCode = FMULD; break;
- default: assert(0 && "Invalid type for MUL instruction"); break;
- }
- }
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseDivInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- const Type* resultType = instrNode->getInstruction()->getType();
-
- if (resultType->isIntegral())
- {
- opCode = resultType->isSigned()? SDIVX : UDIVX;
- }
- else
- {
- Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
- switch(operand->getType()->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = FDIVS; break;
- case Type::DoubleTyID: opCode = FDIVD; break;
- default: assert(0 && "Invalid type for DIV instruction"); break;
- }
- }
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseLoadInstruction(const Type* resultType)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- switch (resultType->getPrimitiveID())
- {
- case Type::BoolTyID: opCode = LDUB; break;
- case Type::UByteTyID: opCode = LDUB; break;
- case Type::SByteTyID: opCode = LDSB; break;
- case Type::UShortTyID: opCode = LDUH; break;
- case Type::ShortTyID: opCode = LDSH; break;
- case Type::UIntTyID: opCode = LDUW; break;
- case Type::IntTyID: opCode = LDSW; break;
- case Type::ULongTyID:
- case Type::LongTyID: opCode = LDX; break;
- case Type::FloatTyID: opCode = LD; break;
- case Type::DoubleTyID: opCode = LDD; break;
- default: assert(0 && "Invalid type for Load instruction"); break;
- }
-
- return opCode;
-}
-
-
-static MachineOpCode
-ChooseStoreInstruction(const Type* valueType)
-{
- MachineOpCode opCode = INVALID_OPCODE;
-
- switch (valueType->getPrimitiveID())
- {
- case Type::BoolTyID:
- case Type::UByteTyID:
- case Type::SByteTyID: opCode = STB; break;
- case Type::UShortTyID:
- case Type::ShortTyID: opCode = STH; break;
- case Type::UIntTyID:
- case Type::IntTyID: opCode = STW; break;
- case Type::ULongTyID:
- case Type::LongTyID: opCode = STX; break;
- case Type::FloatTyID: opCode = ST; break;
- case Type::DoubleTyID: opCode = STD; break;
- default: assert(0 && "Invalid type for Store instruction"); break;
- }
-
- return opCode;
-}
-
-
-//------------------------------------------------------------------------
-// Function SetOperandsForMemInstr
-//
-// Choose addressing mode for the given load or store instruction.
-// Use [reg+reg] if it is an indexed reference, and the index offset is
-// not a constant or if it cannot fit in the offset field.
-// Use [reg+offset] in all other cases.
-//
-// This assumes that all array refs are "lowered" to one of these forms:
-// %x = load (subarray*) ptr, constant ; single constant offset
-// %x = load (subarray*) ptr, offsetVal ; single non-constant offset
-// Generally, this should happen via strength reduction + LICM.
-// Also, strength reduction should take care of using the same register for
-// the loop index variable and an array index, when that is profitable.
-//------------------------------------------------------------------------
-
-static void
-SetOperandsForMemInstr(MachineInstr* minstr,
- const InstructionNode* vmInstrNode,
- const TargetMachine& target)
-{
- MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
-
- // Variables to hold the index vector, ptr value, and offset value.
- // The major work here is to extract these for all 3 instruction types
- // and then call the common function SetMemOperands_Internal().
- //
- const vector<ConstPoolVal*>* idxVec = & memInst->getIndexVec();
- vector<ConstPoolVal*>* newIdxVec = NULL;
- Value* ptrVal;
- Value* arrayOffsetVal = NULL;
-
- // Test if a GetElemPtr instruction is being folded into this mem instrn.
- // If so, it will be in the left child for Load and GetElemPtr,
- // and in the right child for Store instructions.
- //
- InstrTreeNode* ptrChild = (vmInstrNode->getOpLabel() == Instruction::Store
- ? vmInstrNode->rightChild()
- : vmInstrNode->leftChild());
-
- if (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
- ptrChild->getOpLabel() == GetElemPtrIdx)
- {
- // There is a GetElemPtr instruction and there may be a chain of
- // more than one. Use the pointer value of the last one in the chain.
- // Fold the index vectors from the entire chain and from the mem
- // instruction into one single index vector.
- // Finally, we never fold for an array instruction so make that NULL.
-
- newIdxVec = new vector<ConstPoolVal*>;
- ptrVal = FoldGetElemChain((InstructionNode*) ptrChild, *newIdxVec);
-
- newIdxVec->insert(newIdxVec->end(), idxVec->begin(), idxVec->end());
- idxVec = newIdxVec;
-
- assert(! ((PointerType*)ptrVal->getType())->getValueType()->isArrayType()
- && "GetElemPtr cannot be folded into array refs in selection");
- }
- else
- {
- // There is no GetElemPtr instruction.
- // Use the pointer value and the index vector from the Mem instruction.
- // If it is an array reference, get the array offset value.
- //
- ptrVal = memInst->getPtrOperand();
-
- const Type* opType =
- ((const PointerType*) ptrVal->getType())->getValueType();
- if (opType->isArrayType())
- {
- assert((memInst->getNumOperands()
- == (unsigned) 1 + memInst->getFirstOffsetIdx())
- && "Array refs must be lowered before Instruction Selection");
-
- arrayOffsetVal = memInst->getOperand(memInst->getFirstOffsetIdx());
- }
- }
-
- SetMemOperands_Internal(minstr, vmInstrNode, ptrVal, arrayOffsetVal,
- *idxVec, target);
-
- if (newIdxVec != NULL)
- delete newIdxVec;
-}
-
-
-static void
-SetMemOperands_Internal(MachineInstr* minstr,
- const InstructionNode* vmInstrNode,
- Value* ptrVal,
- Value* arrayOffsetVal,
- const vector<ConstPoolVal*>& idxVec,
- const TargetMachine& target)
-{
- MemAccessInst* memInst = (MemAccessInst*) vmInstrNode->getInstruction();
-
- // Initialize so we default to storing the offset in a register.
- int64_t smallConstOffset;
- Value* valueForRegOffset = NULL;
- MachineOperand::MachineOperandType offsetOpType =MachineOperand::MO_VirtualRegister;
-
- // Check if there is an index vector and if so, if it translates to
- // a small enough constant to fit in the immediate-offset field.
- //
- if (idxVec.size() > 0)
- {
- bool isConstantOffset = false;
- unsigned offset;
-
- const PointerType* ptrType = (PointerType*) ptrVal->getType();
-
- if (ptrType->getValueType()->isStructType())
- {
- // the offset is always constant for structs
- isConstantOffset = true;
-
- // Compute the offset value using the index vector
- offset = target.DataLayout.getIndexedOffset(ptrType, idxVec);
- }
- else
- {
- // It must be an array ref. Check if the offset is a constant,
- // and that the indexing has been lowered to a single offset.
- //
- assert(ptrType->getValueType()->isArrayType());
- assert(arrayOffsetVal != NULL
- && "Expect to be given Value* for array offsets");
-
- if (ConstPoolVal *CPV = arrayOffsetVal->castConstant()) {
- isConstantOffset = true; // always constant for structs
- assert(arrayOffsetVal->getType()->isIntegral());
- offset = (CPV->getType()->isSigned())
- ? ((ConstPoolSInt*)CPV)->getValue()
- : (int64_t) ((ConstPoolUInt*)CPV)->getValue();
- }
- else
- {
- valueForRegOffset = arrayOffsetVal;
- }
- }
-
- if (isConstantOffset)
- {
- // create a virtual register for the constant
- valueForRegOffset = new ConstPoolSInt(Type::IntTy, offset);
- }
- }
- else
- {
- offsetOpType = MachineOperand::MO_SignExtendedImmed;
- smallConstOffset = 0;
- }
-
- // Operand 0 is value for STORE, ptr for LOAD or GET_ELEMENT_PTR
- // It is the left child in the instruction tree in all cases.
- Value* leftVal = vmInstrNode->leftChild()->getValue();
- minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, leftVal);
-
- // Operand 1 is ptr for STORE, offset for LOAD or GET_ELEMENT_PTR
- // Operand 3 is offset for STORE, result reg for LOAD or GET_ELEMENT_PTR
- //
- unsigned offsetOpNum = (memInst->getOpcode() == Instruction::Store)? 2 : 1;
- if (offsetOpType == MachineOperand::MO_VirtualRegister)
- {
- assert(valueForRegOffset != NULL);
- minstr->SetMachineOperand(offsetOpNum, offsetOpType, valueForRegOffset);
- }
- else
- minstr->SetMachineOperand(offsetOpNum, offsetOpType, smallConstOffset);
-
- if (memInst->getOpcode() == Instruction::Store)
- minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, ptrVal);
- else
- minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
- vmInstrNode->getValue());
-}
-
-
-// Special handling for constant operands:
-// -- if the constant is 0, use the hardwired 0 register, if any
-// -- if the constant fits in the IMMEDIATE field, use that field
-// -- else insert instructions to put the constant into a register, either
-// directly or by loading explicitly from the constant pool.
-//
-static unsigned
-FixConstantOperands(const InstructionNode* vmInstrNode,
- MachineInstr** mvec,
- unsigned numInstr,
- TargetMachine& target)
-{
- static MachineInstr* loadConstVec[MAX_INSTR_PER_VMINSTR];
-
- unsigned numNew = 0;
- Instruction* vmInstr = vmInstrNode->getInstruction();
-
- for (unsigned i=0; i < numInstr; i++)
- {
- MachineInstr* minstr = mvec[i];
- const MachineInstrDescriptor& instrDesc =
- target.getInstrInfo().getDescriptor(minstr->getOpCode());
-
- for (unsigned op=0; op < minstr->getNumOperands(); op++)
- {
- const MachineOperand& mop = minstr->getOperand(op);
-
- // skip the result position (for efficiency below) and any other
- // positions already marked as not a virtual register
- if (instrDesc.resultPos == (int) op ||
- mop.getOperandType() != MachineOperand::MO_VirtualRegister ||
- mop.getVRegValue() == NULL)
- {
- break;
- }
-
- Value* opValue = mop.getVRegValue();
-
- if (opValue->getValueType() == Value::ConstantVal)
- {
- unsigned int machineRegNum;
- int64_t immedValue;
- MachineOperand::MachineOperandType opType =
- ChooseRegOrImmed(opValue, minstr->getOpCode(), target,
- /*canUseImmed*/ (op == 1),
- machineRegNum, immedValue);
-
- if (opType == MachineOperand::MO_MachineRegister)
- minstr->SetMachineOperand(op, machineRegNum);
- else if (opType == MachineOperand::MO_VirtualRegister)
- {
- // value is constant and must be loaded into a register
- TmpInstruction* tmpReg;
- loadConstVec[numNew++] =
- MakeOneLoadConstInstr(vmInstr, opValue, tmpReg);
- minstr->SetMachineOperand(op, opType, tmpReg);
- }
- else
- minstr->SetMachineOperand(op, opType, immedValue);
- }
- }
- }
-
- if (numNew > 0)
- {
- // Insert the new instructions *before* the old ones by moving
- // the old ones over `numNew' positions (last-to-first, of course!).
- //
- for (int i=numInstr-1; i >= ((int) numInstr) - (int) numNew; i--)
- mvec[i+numNew] = mvec[i];
-
- for (unsigned i=0; i < numNew; i++)
- mvec[i] = loadConstVec[i];
- }
-
- return (numInstr + numNew);
-}
-
-
-#if 0
-// Create one or two load instructions to load constants from the
-// constant pool. The first instructions is stored in instrA;
-// the second (if any) in instrB.
-//
-static unsigned
-InsertLoadConstInstructions(unsigned loadConstFlags,
- const InstructionNode* vmInstrNode,
- MachineInstr** mvec,
- unsigned numInstr)
-{
- MachineInstr *instrA = NULL, *instrB = NULL;
-
- unsigned numNew = 0;
-
- if (loadConstFlags & 0x01)
- {
- instrA = MakeOneLoadConstInstr(vmInstrNode->getInstruction(),
- vmInstrNode->leftChild()->getValue());
- numNew++;
- }
-
- if (loadConstFlags & 0x02)
- {
- instrB = MakeOneLoadConstInstr(vmInstrNode->getInstruction(),
- vmInstrNode->rightChild()->getValue());
- numNew++;
- }
-
- // Now insert the new instructions *before* the old ones by
- // moving the old ones over `numNew' positions (last-to-first, of course!).
- //
- for (int i=numInstr-1; i >= ((int) numInstr) - (int) numNew; i--)
- mvec[i+numNew] = mvec[i];
-
- unsigned whichNew = 0;
- if (instrA != NULL)
- mvec[whichNew++] = instrA;
- if (instrB != NULL)
- mvec[whichNew++] = instrB;
- assert(whichNew == numNew);
-
- return numInstr + numNew;
-}
-#endif
-
-
-static MachineInstr*
-MakeOneLoadConstInstr(Instruction* vmInstr,
- Value* val,
- TmpInstruction*& tmpReg)
-{
- assert(val->getValueType() == Value::ConstantVal);
-
- MachineInstr* minstr;
-
- // Create a TmpInstruction to mark the hidden register used for the constant
- tmpReg = new TmpInstruction(Instruction::UserOp1, val, NULL);
- vmInstr->getMachineInstrVec().addTempValue(tmpReg);
-
- // Use a "set" instruction for known constants that can go in an integer reg.
- // Use a "load" instruction for all other constants, in particular,
- // floating point constants.
- //
- const Type* valType = val->getType();
- if (valType->isIntegral() ||
- valType->isPointerType() ||
- valType == Type::BoolTy)
- {
- bool isValidConstant;
- if (val->getType()->isSigned())
- {
- minstr = new MachineInstr(SETSW);
- minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed,
- GetSignedIntConstantValue(val, isValidConstant));
- }
- else
- {
- minstr = new MachineInstr(SETUW);
- minstr->SetMachineOperand(0, MachineOperand::MO_UnextendedImmed,
- GetUnsignedIntConstantValue(val, isValidConstant));
- }
- minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, tmpReg);
- assert(isValidConstant && "Unrecognized constant");
- }
- else
- {
- assert(valType == Type::FloatTy ||
- valType == Type::DoubleTy);
-
- int64_t zeroOffset = 0; // to avoid overloading ambiguity with (Value*) 0
-
- // Make a Load instruction, and make `val' both the ptr value *and*
- // the result value, and set the offset field to 0. Final code
- // generation will have to generate the base+offset for the constant.
- //
- minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
- minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, val);
- minstr->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
- zeroOffset);
- minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, tmpReg);
- }
-
- tmpReg->addMachineInstruction(minstr);
-
- return minstr;
-}
-
-//
-// Substitute operand `operandNum' of the instruction in node `treeNode'
-// in place the use(s) of that instruction in node `parent'.
-//
-static void
-ForwardOperand(InstructionNode* treeNode,
- InstructionNode* parent,
- int operandNum)
-{
- Instruction* unusedOp = treeNode->getInstruction();
- Value* fwdOp = unusedOp->getOperand(operandNum);
- Instruction* userInstr = parent->getInstruction();
- MachineCodeForVMInstr& mvec = userInstr->getMachineInstrVec();
- for (unsigned i=0, N=mvec.size(); i < N; i++)
- {
- MachineInstr* minstr = mvec[i];
- for (unsigned i=0, numOps=minstr->getNumOperands(); i < numOps; i++)
- {
- const MachineOperand& mop = minstr->getOperand(i);
- if (mop.getOperandType() == MachineOperand::MO_VirtualRegister &&
- mop.getVRegValue() == unusedOp)
- {
- minstr->SetMachineOperand(i, MachineOperand::MO_VirtualRegister,
- fwdOp);
- }
- }
- }
-}
-
-
-// This function is currently unused and incomplete but will be
-// used if we have a linear layout of basic blocks in LLVM code.
-// It decides which branch should fall-through, and whether an
-// extra unconditional branch is needed (when neither falls through).
-//
-void
-ChooseBranchPattern(Instruction* vmInstr, BranchPattern& brPattern)
-{
- BranchInst* brInstr = (BranchInst*) vmInstr;
-
- brPattern.flipCondition = false;
- brPattern.targetBB = brInstr->getSuccessor(0);
- brPattern.extraBranch = NULL;
-
- assert(brInstr->getNumSuccessors() > 1 &&
- "Unnecessary analysis for unconditional branch");
-
- assert(0 && "Fold branches in peephole optimization");
-}
-