- 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());
-}
-
-
-static inline MachineInstr*
-CreateIntSetInstruction(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;
-}
-
-
-// Create an instruction sequence to load a constant into a register.
-// This always creates either one or two instructions.
-// If two instructions are created, the second one is returned in getMinstr2
-//
-static MachineInstr*
-CreateLoadConstInstr(const TargetMachine &target,
- Instruction* vmInstr,
- Value* val,
- Instruction* dest,
- MachineInstr*& getMinstr2)
-{
- assert(isa<ConstPoolVal>(val));
-
- MachineInstr* minstr1 = NULL;
-
- getMinstr2 = NULL;
-
- // 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 == Type::BoolTy)
- {
- bool isValidConstant;
- int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
- assert(isValidConstant && "Unrecognized constant");
- minstr1 = CreateIntSetInstruction(C, valType->isSigned(), dest);
- }
- else
- {
-
-#undef MOVE_INT_TO_FP_REG_AVAILABLE
-#ifdef MOVE_INT_TO_FP_REG_AVAILABLE
- //
- // This code was written to generate the following sequence:
- // SET[SU]W <int-const> <int-reg>
- // FITO[SD] <int-reg> <fp-reg>
- // (it really should have moved the int-reg to an fp-reg and then FITOS).
- // But for now the only way to move a value from an int-reg to an fp-reg
- // is via memory. Leave this code here but unused.
- //
- 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* addrReg = NULL;
- if (dval != 0.0)
- { // First, create an integer constant of the same value as dval
- ConstPoolSInt* ival = ConstPoolSInt::get(Type::IntTy,
- (int64_t) dval);
- // Create another TmpInstruction for the hidden integer register
- addrReg = new TmpInstruction(Instruction::UserOp1, ival, NULL);
- vmInstr->getMachineInstrVec().addTempValue(addrReg);
-
- // Create the `SET' instruction
- minstr1 = CreateIntSetInstruction((int64_t)dval, true, addrReg);
- addrReg->addMachineInstruction(minstr1);
- }
-
- // In which variable do we put the second instruction?
- MachineInstr*& instr2 = (minstr1)? getMinstr2 : minstr1;
-
- // Create the int-to-float instruction
- instr2 = new MachineInstr(valType == Type::FloatTy? FITOS : FITOD);
-
- if (dval == 0.0)
- instr2->SetMachineOperand(0, target.getRegInfo().getZeroRegNum());
- else
- instr2->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
- addrReg);
-
- instr2->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
- dest);
- }
- else
-#endif MOVE_INT_TO_FP_REG_AVAILABLE
-
- {
- // Make an instruction sequence to load the constant, viz:
- // SETSW <addr-of-constant>, addrReg
- // LOAD /*addr*/ addrReg, /*offset*/ 0, dest
- // set the offset field to 0.
- //
- int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
-
- // Create another TmpInstruction for the hidden integer register
- TmpInstruction* addrReg =
- new TmpInstruction(Instruction::UserOp1, val, NULL);
- vmInstr->getMachineInstrVec().addTempValue(addrReg);
-
- minstr1 = new MachineInstr(SETUW);
- minstr1->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp,val);
- minstr1->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
- addrReg);
- addrReg->addMachineInstruction(minstr1);
-
- getMinstr2 = new MachineInstr(ChooseLoadInstruction(val->getType()));
- getMinstr2->SetMachineOperand(0,MachineOperand::MO_VirtualRegister,
- addrReg);
- getMinstr2->SetMachineOperand(1,MachineOperand::MO_SignExtendedImmed,
- zeroOffset);
- getMinstr2->SetMachineOperand(2,MachineOperand::MO_VirtualRegister,
- dest);
- }
- }
-
- assert(minstr1);
- return minstr1;
-}
-
-
-TmpInstruction*
-InsertCodeToLoadConstant(ConstPoolVal* opValue,
- Instruction* vmInstr,
- vector<MachineInstr*> loadConstVec,
- TargetMachine& target)
-{
- // value is constant and must be loaded into a register.
- // First, create a tmp virtual register (TmpInstruction)
- // to hold the constant.
- // This will replace the constant operand in `minstr'.
- TmpInstruction* tmpReg =
- new TmpInstruction(Instruction::UserOp1, opValue, NULL);
- vmInstr->getMachineInstrVec().addTempValue(tmpReg);
-
- MachineInstr *minstr1, *minstr2;
- minstr1 = CreateLoadConstInstr(target, vmInstr,
- opValue, tmpReg, minstr2);
-
- loadConstVec.push_back(minstr1);
- if (minstr2 != NULL)
- loadConstVec.push_back(minstr2);
-
- tmpReg->addMachineInstruction(loadConstVec.back());
-
- return tmpReg;
-}
-
-
-// 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)
-{
- vector<MachineInstr*> loadConstVec;
- loadConstVec.reserve(MAX_INSTR_PER_VMINSTR);
-
- 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)
- {
- continue;
- }
-
- Value* opValue = mop.getVRegValue();
-
- if (isa<ConstPoolVal>(opValue))
- {
- 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)
- {
- TmpInstruction* tmpReg =
- InsertCodeToLoadConstant((ConstPoolVal*) opValue,
- vmInstr, loadConstVec, target);
- minstr->SetMachineOperand(op, opType, tmpReg);
- }
- else
- minstr->SetMachineOperand(op, opType, immedValue);
- }
- }
-
- //
- // Also, check for implicit operands used (not those defined) by the
- // machine instruction. These include:
- // -- arguments to a Call
- // -- return value of a Return
- // Any such operand that is a constant value needs to be fixed also.
- // The current instructions with implicit refs (viz., Call and Return)
- // have no immediate fields, so the constant always needs to be loaded
- // into a register.
- //
- for (unsigned i=1, N=minstr->getNumImplicitRefs(); i < N; ++i)
- if (isa<ConstPoolVal>(minstr->getImplicitRef(i)))
- {
- TmpInstruction* tmpReg = InsertCodeToLoadConstant((ConstPoolVal*)
- minstr->getImplicitRef(i),
- vmInstr, loadConstVec, target);
- minstr->setImplicitRef(i, tmpReg);
- }
- }
-
- //
- // Finally, inserted the generated instructions in the vector
- // to be returned.
- //
- unsigned numNew = loadConstVec.size();
- 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);