// For now, hack this using a little static cache of TmpInstructions.
// Eventually the entire BURG instruction selection should be put
// into a separate class that can hold such information.
-// The static cache is not too bad because that memory for these
-// TmpInstructions will be freed elsewhere in any case.
+// The static cache is not too bad because the memory for these
+// TmpInstructions will be freed along with the rest of the Method anyway.
//
static TmpInstruction*
-GetTmpForCC(Value* boolVal, const Method* method)
+GetTmpForCC(Value* boolVal, const Method* method, const Type* ccType)
{
typedef hash_map<const Value*, TmpInstruction*> BoolTmpCache;
static BoolTmpCache boolToTmpCache; // Map boolVal -> TmpInstruction*
boolToTmpCache.clear();
}
- // Look for tmpI and create a new one otherswise.
- // new value is directly written to map using
+ // Look for tmpI and create a new one otherwise. The new value is
+ // directly written to map using the ref returned by operator[].
TmpInstruction*& tmpI = boolToTmpCache[boolVal];
if (tmpI == NULL)
- tmpI = new TmpInstruction(TMP_INSTRUCTION_OPCODE, boolVal, NULL);
+ tmpI = new TmpInstruction(TMP_INSTRUCTION_OPCODE, ccType, boolVal, NULL);
return tmpI;
}
break;
case ToDoubleTy:
- if (opType == Type::SByteTy || opType == Type::ShortTy || opType == Type::IntTy)
- opCode = FITOD;
- else if (opType == Type::LongTy)
+ // Use FXTOD for all integer-to-double conversions. This has to be
+ // consistent with the code in CreateCodeToCopyIntToFloat() since
+ // that will be used to load the integer into an FP register.
+ //
+ if (opType == Type::SByteTy || opType == Type::ShortTy ||
+ opType == Type::IntTy || opType == Type::LongTy)
opCode = FXTOD;
else if (opType == Type::FloatTy)
opCode = FSTOD;
{
int64_t s0=0; // used to avoid overloading ambiguity below
+ const MachineFrameInfo& frameInfo = target.getFrameInfo();
+
// The second operand is the stack size. If it does not fit in the
// immediate field, we either have to find an unused register in the
// caller's window or move some elements to the dynamically allocated
// area of the stack frame (just above save area and method args).
Method* method = entryBB->getParent();
- MachineCodeForMethod& mcodeInfo = method->getMachineCode();
- unsigned int staticStackSize = mcodeInfo.getStaticStackSize();
+ MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(method);
+ unsigned int staticStackSize = mcInfo.getStaticStackSize();
+
+ if (staticStackSize < (unsigned) frameInfo.getMinStackFrameSize())
+ staticStackSize = (unsigned) frameInfo.getMinStackFrameSize();
+
+ if (unsigned padsz = (staticStackSize %
+ (unsigned) frameInfo.getStackFrameSizeAlignment()))
+ staticStackSize += padsz;
assert(target.getInstrInfo().constantFitsInImmedField(SAVE, staticStackSize)
&& "Stack size too large for immediate field of SAVE instruction. Need additional work as described in the comment above");
mvec[0] = new MachineInstr(SAVE);
mvec[0]->SetMachineOperand(0, target.getRegInfo().getStackPointer());
mvec[0]->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
- - staticStackSize);
+ - (int) staticStackSize);
mvec[0]->SetMachineOperand(2, target.getRegInfo().getStackPointer());
return 1;
GetInstructionsByRule(InstructionNode* subtreeRoot,
int ruleForNode,
short* nts,
- TargetMachine &tgt,
+ TargetMachine &target,
MachineInstr** mvec)
{
int numInstr = 1; // initialize for common case
int64_t s0=0, s8=8; // variables holding constants to avoid
uint64_t u0=0; // overloading ambiguities below
- UltraSparc& target = (UltraSparc&) tgt;
-
for (unsigned i=0; i < MAX_INSTR_PER_VMINSTR; i++)
mvec[i] = NULL;
mvec[0] = new MachineInstr(ChooseBccInstruction(subtreeRoot,
isFPBranch));
- Value* ccValue = isFPBranch? subtreeRoot->leftChild()->getValue()
- : GetTmpForCC(subtreeRoot->leftChild()->getValue(),
- brInst->getParent()->getParent());
+ Value* ccValue = GetTmpForCC(subtreeRoot->leftChild()->getValue(),
+ brInst->getParent()->getParent(),
+ isFPBranch? Type::FloatTy : Type::IntTy);
mvec[0]->SetMachineOperand(0, MachineOperand::MO_CCRegister, ccValue);
mvec[0]->SetMachineOperand(1, MachineOperand::MO_PCRelativeDisp,
assert(0 && "VRegList should never be the topmost non-chain rule");
break;
- case 21: // reg: Not(reg): Implemented as reg = reg XOR-NOT 0
+ case 21: // bool: Not(bool): Both these are implemented as:
+ case 321: // reg: BNot(reg) : reg = reg XOR-NOT 0
mvec[0] = new MachineInstr(XNOR);
mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
subtreeRoot->leftChild()->getValue());
}
else
{
- opType = subtreeRoot->leftChild()->getValue()->getType();
+ leftVal = subtreeRoot->leftChild()->getValue();
+ opType = leftVal->getType();
MachineOpCode opCode=ChooseConvertToFloatInstr(subtreeRoot,opType);
if (opCode == INVALID_OPCODE) // no conversion needed
{
}
else
{
- mvec[0] = new MachineInstr(opCode);
- Set2OperandsFromInstr(mvec[0], subtreeRoot, target);
+ // If the source operand is a non-FP type it must be
+ // first copied from int to float register via memory!
+ Instruction *dest = subtreeRoot->getInstruction();
+ Value* srcForCast;
+ int n = 0;
+ if (opType != Type::FloatTy && opType != Type::DoubleTy)
+ {
+ // Create a temporary to represent the FP register
+ // into which the integer will be copied via memory.
+ srcForCast = new TmpInstruction(TMP_INSTRUCTION_OPCODE,
+ dest, NULL);
+ dest->getMachineInstrVec().addTempValue(srcForCast);
+
+ vector<MachineInstr*> minstrVec;
+ vector<TmpInstruction*> tempVec;
+ target.getInstrInfo().CreateCodeToCopyIntToFloat(
+ dest->getParent()->getParent(),
+ leftVal, (TmpInstruction*) srcForCast,
+ minstrVec, tempVec, target);
+
+ for (unsigned i=0; i < minstrVec.size(); ++i)
+ mvec[n++] = minstrVec[i];
+
+ for (unsigned i=0; i < tempVec.size(); ++i)
+ dest->getMachineInstrVec().addTempValue(tempVec[i]);
+ }
+ else
+ srcForCast = leftVal;
+
+ MachineInstr* castI = new MachineInstr(opCode);
+ castI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
+ srcForCast);
+ castI->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
+ dest);
+ mvec[n++] = castI;
+ numInstr = n;
}
}
break;
break;
}
- case 38: // reg: And(reg, reg)
- case 238: // reg: And(reg, Constant)
+ case 38: // bool: And(bool, bool)
+ case 238: // bool: And(bool, boolconst)
+ case 338: // reg : BAnd(reg, reg)
+ case 538: // reg : BAnd(reg, Constant)
mvec[0] = new MachineInstr(AND);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
- case 138: // reg: And(reg, not)
+ case 138: // bool: And(bool, not)
+ case 438: // bool: BAnd(bool, not)
mvec[0] = new MachineInstr(ANDN);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
- case 39: // reg: Or(reg, reg)
- case 239: // reg: Or(reg, Constant)
+ case 39: // bool: Or(bool, bool)
+ case 239: // bool: Or(bool, boolconst)
+ case 339: // reg : BOr(reg, reg)
+ case 539: // reg : BOr(reg, Constant)
mvec[0] = new MachineInstr(ORN);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
- case 139: // reg: Or(reg, not)
+ case 139: // bool: Or(bool, not)
+ case 439: // bool: BOr(bool, not)
mvec[0] = new MachineInstr(ORN);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
- case 40: // reg: Xor(reg, reg)
- case 240: // reg: Xor(reg, Constant)
+ case 40: // bool: Xor(bool, bool)
+ case 240: // bool: Xor(bool, boolconst)
+ case 340: // reg : BXor(reg, reg)
+ case 540: // reg : BXor(reg, Constant)
mvec[0] = new MachineInstr(XOR);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
- case 140: // reg: Xor(reg, not)
+ case 140: // bool: Xor(bool, not)
+ case 440: // bool: BXor(bool, not)
mvec[0] = new MachineInstr(XNOR);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
break;
bool mustClearReg;
int valueToMove;
MachineOpCode movOpCode = 0;
- Value* ccValue = NULL;
+
+ // Mark the 4th operand as being a CC register, and as a def
+ // A TmpInstruction is created to represent the CC "result".
+ // Unlike other instances of TmpInstruction, this one is used
+ // by machine code of multiple LLVM instructions, viz.,
+ // the SetCC and the branch. Make sure to get the same one!
+ // Note that we do this even for FP CC registers even though they
+ // are explicit operands, because the type of the operand
+ // needs to be a floating point condition code, not an integer
+ // condition code. Think of this as casting the bool result to
+ // a FP condition code register.
+ //
+ leftVal = subtreeRoot->leftChild()->getValue();
+ bool isFPCompare = (leftVal->getType() == Type::FloatTy ||
+ leftVal->getType() == Type::DoubleTy);
+
+ TmpInstruction* tmpForCC = GetTmpForCC(setCCInstr,
+ setCCInstr->getParent()->getParent(),
+ isFPCompare? Type::FloatTy : Type::IntTy);
+ setCCInstr->getMachineInstrVec().addTempValue(tmpForCC);
- if (subtreeRoot->leftChild()->getValue()->getType()->isIntegral() ||
- subtreeRoot->leftChild()->getValue()->getType()->isPointerType())
+ if (! isFPCompare)
{
// Integer condition: dest. should be %g0 or an integer register.
// If result must be saved but condition is not SetEQ then we need
mvec[0] = new MachineInstr(SUBcc);
Set3OperandsFromInstr(mvec[0], subtreeRoot, target, ! keepSubVal);
- // Mark the 4th operand as being a CC register, and as a def
- // A TmpInstruction is created to represent the int CC "result".
- // Unlike other instances of TmpInstruction, this one is used by
- // used by machine code of multiple LLVM instructions, viz.,
- // the SetCC and the branch. Make sure to get the same one!
- //
- TmpInstruction* tmpForCC = GetTmpForCC(setCCInstr,
- setCCInstr->getParent()->getParent());
- setCCInstr->getMachineInstrVec().addTempValue(tmpForCC);
-
mvec[0]->SetMachineOperand(3, MachineOperand::MO_CCRegister,
tmpForCC, /*def*/true);
{ // recompute bool using the integer condition codes
movOpCode =
ChooseMovpccAfterSub(subtreeRoot,mustClearReg,valueToMove);
- ccValue = tmpForCC;
}
}
else
// FP condition: dest of FCMP should be some FCCn register
mvec[0] = new MachineInstr(ChooseFcmpInstruction(subtreeRoot));
mvec[0]->SetMachineOperand(0, MachineOperand::MO_CCRegister,
- setCCInstr);
+ tmpForCC);
mvec[0]->SetMachineOperand(1,MachineOperand::MO_VirtualRegister,
subtreeRoot->leftChild()->getValue());
mvec[0]->SetMachineOperand(2,MachineOperand::MO_VirtualRegister,
mustClearReg = true;
valueToMove = 1;
movOpCode = ChooseMovFpccInstruction(subtreeRoot);
- ccValue = setCCInstr;
}
}
if (computeBoolVal)
{
- assert(ccValue && "Inconsistent logic above and here");
-
if (mustClearReg)
{// Unconditionally set register to 0
int n = numInstr++;
int n = numInstr++;
mvec[n] = new MachineInstr(movOpCode);
mvec[n]->SetMachineOperand(0, MachineOperand::MO_CCRegister,
- ccValue);
+ tmpForCC);
mvec[n]->SetMachineOperand(1, MachineOperand::MO_UnextendedImmed,
valueToMove);
mvec[n]->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
assert(tsize != 0 && "Just to check when this can happen");
Method* method = instr->getParent()->getParent();
- MachineCodeForMethod& mcode = method->getMachineCode();
- int offsetFromFP =
- target.getFrameInfo().getFirstAutomaticVarOffsetFromFP(method)
- - (tsize + mcode.getAutomaticVarsSize());
-
- mcode.putLocalVarAtOffsetFromFP(instr, offsetFromFP, tsize);
+ MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(method);
+ int offsetFromFP = mcInfo.allocateLocalVar(target, instr);
// Create a temporary Value to hold the constant offset.
// This is needed because it may not fit in the immediate field.
// Create a temporary Value to hold the constant offset from SP
Method* method = instr->getParent()->getParent();
- MachineCodeForMethod& mcode = method->getMachineCode();
- int frameSizeBelowDynamicArea =
- target.getFrameInfo().getFrameSizeBelowDynamicArea(method);
- ConstPoolSInt* lowerAreaSizeVal = ConstPoolSInt::get(Type::IntTy,
- frameSizeBelowDynamicArea);
- cerr << "***" << endl
- << "*** Variable-size ALLOCA operation needs more work:" << endl
- << "*** We have to precompute the size of "
- << " optional arguments in the stack frame" << endl
- << "***" << endl;
- assert(0 && "SEE MESSAGE ABOVE");
+ bool ignore; // we don't need this
+ ConstPoolSInt* dynamicAreaOffset = ConstPoolSInt::get(Type::IntTy,
+ target.getFrameInfo().getDynamicAreaOffset(MachineCodeForMethod::get(method),
+ ignore));
// Create a temporary value to hold `tmp'
Instruction* tmpInstr = new TmpInstruction(TMP_INSTRUCTION_OPCODE,
mvec[2] = new MachineInstr(ADD);
mvec[2]->SetMachineOperand(0, target.getRegInfo().getStackPointer());
mvec[2]->SetMachineOperand(1, MachineOperand::MO_VirtualRegister,
- lowerAreaSizeVal);
+ dynamicAreaOffset);
mvec[2]->SetMachineOperand(2,MachineOperand::MO_VirtualRegister,instr);
break;
}