Allow pointer constants as well as integer and booleans.
Skip over list nodes in ForwardOperand. llvm-svn: 617
This commit is contained in:
parent
49d908a419
commit
78d50d0f7a
|
@ -1,3 +1,4 @@
|
||||||
|
// $Id$
|
||||||
//***************************************************************************
|
//***************************************************************************
|
||||||
// File:
|
// File:
|
||||||
// SparcInstrSelection.cpp
|
// SparcInstrSelection.cpp
|
||||||
|
@ -95,7 +96,7 @@ static MachineInstr* MakeLoadConstInstr(Instruction* vmInstr,
|
||||||
MachineInstr*& getMinstr2);
|
MachineInstr*& getMinstr2);
|
||||||
|
|
||||||
static void ForwardOperand (InstructionNode* treeNode,
|
static void ForwardOperand (InstructionNode* treeNode,
|
||||||
InstructionNode* parent,
|
InstrTreeNode* parent,
|
||||||
int operandNum);
|
int operandNum);
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,14 +105,16 @@ static void ForwardOperand (InstructionNode* treeNode,
|
||||||
// Convenience function to get the value of an integer constant, for an
|
// Convenience function to get the value of an integer constant, for an
|
||||||
// appropriate integer or non-integer type that can be held in an integer.
|
// appropriate integer or non-integer type that can be held in an integer.
|
||||||
// The type of the argument must be the following:
|
// The type of the argument must be the following:
|
||||||
// GetConstantValueAsSignedInt: any of the above, but the value
|
// Signed or unsigned integer
|
||||||
// must fit into a int64_t.
|
// Boolean
|
||||||
|
// Pointer
|
||||||
//
|
//
|
||||||
// isValidConstant is set to true if a valid constant was found.
|
// isValidConstant is set to true if a valid constant was found.
|
||||||
//
|
//
|
||||||
|
static int64_t
|
||||||
static int64_t GetConstantValueAsSignedInt(const Value *V,
|
GetConstantValueAsSignedInt(const Value *V,
|
||||||
bool &isValidConstant) {
|
bool &isValidConstant)
|
||||||
|
{
|
||||||
if (!V->isConstant()) { isValidConstant = false; return 0; }
|
if (!V->isConstant()) { isValidConstant = false; return 0; }
|
||||||
isValidConstant = true;
|
isValidConstant = true;
|
||||||
|
|
||||||
|
@ -161,10 +164,20 @@ ThisIsAChainRule(int eruleno)
|
||||||
case 130:
|
case 130:
|
||||||
case 131:
|
case 131:
|
||||||
case 132:
|
case 132:
|
||||||
|
case 133:
|
||||||
case 153:
|
case 153:
|
||||||
case 155: return true; break;
|
case 155:
|
||||||
|
case 221:
|
||||||
|
case 222:
|
||||||
|
case 232:
|
||||||
|
case 241:
|
||||||
|
case 242:
|
||||||
|
case 243:
|
||||||
|
case 244:
|
||||||
|
return true; break;
|
||||||
|
|
||||||
default: return false; break;
|
default:
|
||||||
|
return false; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +318,7 @@ ChooseMovFpccInstruction(const InstructionNode* instrNode)
|
||||||
// Set mustClearReg=false if v3 need not be cleared before conditional move.
|
// 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
|
// Set valueToMove=0 if we want to conditionally move 0 instead of 1
|
||||||
// (i.e., we want to test inverse of a condition)
|
// (i.e., we want to test inverse of a condition)
|
||||||
//
|
// (The latter two cases do not seem to arise because SetNE needs nothing.)
|
||||||
//
|
//
|
||||||
static MachineOpCode
|
static MachineOpCode
|
||||||
ChooseMovpccAfterSub(const InstructionNode* instrNode,
|
ChooseMovpccAfterSub(const InstructionNode* instrNode,
|
||||||
|
@ -318,18 +331,13 @@ ChooseMovpccAfterSub(const InstructionNode* instrNode,
|
||||||
|
|
||||||
switch(instrNode->getInstruction()->getOpcode())
|
switch(instrNode->getInstruction()->getOpcode())
|
||||||
{
|
{
|
||||||
case Instruction::SetEQ: opCode = MOVNE; mustClearReg = false;
|
case Instruction::SetEQ: opCode = MOVE; break;
|
||||||
valueToMove = 0; break;
|
|
||||||
case Instruction::SetLE: opCode = MOVLE; break;
|
case Instruction::SetLE: opCode = MOVLE; break;
|
||||||
case Instruction::SetGE: opCode = MOVGE; break;
|
case Instruction::SetGE: opCode = MOVGE; break;
|
||||||
case Instruction::SetLT: opCode = MOVL; break;
|
case Instruction::SetLT: opCode = MOVL; break;
|
||||||
case Instruction::SetGT: opCode = MOVG; break;
|
case Instruction::SetGT: opCode = MOVG; break;
|
||||||
|
case Instruction::SetNE: assert(0 && "No move required!"); break;
|
||||||
case Instruction::SetNE: assert(0 && "No move required!");
|
default: assert(0 && "Unrecognized VM instr!"); break;
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0 && "Unrecognized VM instruction!");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return opCode;
|
return opCode;
|
||||||
|
@ -627,7 +635,7 @@ CreateMulConstInstruction(const InstructionNode* instrNode,
|
||||||
//
|
//
|
||||||
const Type* resultType = instrNode->getInstruction()->getType();
|
const Type* resultType = instrNode->getInstruction()->getType();
|
||||||
|
|
||||||
if (resultType->isIntegral())
|
if (resultType->isIntegral() || resultType->isPointerType())
|
||||||
{
|
{
|
||||||
unsigned pow;
|
unsigned pow;
|
||||||
bool isValidConst;
|
bool isValidConst;
|
||||||
|
@ -1247,12 +1255,23 @@ MakeLoadConstInstr(Instruction* vmInstr,
|
||||||
//
|
//
|
||||||
static void
|
static void
|
||||||
ForwardOperand(InstructionNode* treeNode,
|
ForwardOperand(InstructionNode* treeNode,
|
||||||
InstructionNode* parent,
|
InstrTreeNode* parent,
|
||||||
int operandNum)
|
int operandNum)
|
||||||
{
|
{
|
||||||
|
assert(treeNode && parent && "Invalid invocation of ForwardOperand");
|
||||||
|
|
||||||
Instruction* unusedOp = treeNode->getInstruction();
|
Instruction* unusedOp = treeNode->getInstruction();
|
||||||
Value* fwdOp = unusedOp->getOperand(operandNum);
|
Value* fwdOp = unusedOp->getOperand(operandNum);
|
||||||
Instruction* userInstr = parent->getInstruction();
|
|
||||||
|
// The parent itself may be a list node, so find the real parent instruction
|
||||||
|
while (parent->getNodeType() != InstrTreeNode::NTInstructionNode)
|
||||||
|
{
|
||||||
|
parent = parent->parent();
|
||||||
|
assert(parent && "ERROR: Non-instruction node has no parent in tree.");
|
||||||
|
}
|
||||||
|
InstructionNode* parentInstrNode = (InstructionNode*) parent;
|
||||||
|
|
||||||
|
Instruction* userInstr = parentInstrNode->getInstruction();
|
||||||
MachineCodeForVMInstr& mvec = userInstr->getMachineInstrVec();
|
MachineCodeForVMInstr& mvec = userInstr->getMachineInstrVec();
|
||||||
for (unsigned i=0, N=mvec.size(); i < N; i++)
|
for (unsigned i=0, N=mvec.size(); i < N; i++)
|
||||||
{
|
{
|
||||||
|
@ -1316,7 +1335,6 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
const Type* opType;
|
const Type* opType;
|
||||||
int nextRule;
|
int nextRule;
|
||||||
int forwardOperandNum = -1;
|
int forwardOperandNum = -1;
|
||||||
BranchPattern brPattern;
|
|
||||||
int64_t s0 = 0; // variables holding zero to avoid
|
int64_t s0 = 0; // variables holding zero to avoid
|
||||||
uint64_t u0 = 0; // overloading ambiguities below
|
uint64_t u0 = 0; // overloading ambiguities below
|
||||||
|
|
||||||
|
@ -1359,8 +1377,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
mvec[numInstr++] = new MachineInstr(NOP);
|
mvec[numInstr++] = new MachineInstr(NOP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: // stmt: BrCond(boolconst)
|
case 206: // stmt: BrCond(setCCconst)
|
||||||
// boolconst => boolean was computed with `%b = setCC type reg1 constant'
|
// setCCconst => boolean was computed with `%b = setCC type reg1 constant'
|
||||||
// If the constant is ZERO, we can use the branch-on-integer-register
|
// If the constant is ZERO, we can use the branch-on-integer-register
|
||||||
// instructions and avoid the SUBcc instruction entirely.
|
// instructions and avoid the SUBcc instruction entirely.
|
||||||
// Otherwise this is just the same as case 5, so just fall through.
|
// Otherwise this is just the same as case 5, so just fall through.
|
||||||
|
@ -1370,11 +1388,12 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
ConstPoolVal* constVal = (ConstPoolVal*) constNode->getValue();
|
ConstPoolVal* constVal = (ConstPoolVal*) constNode->getValue();
|
||||||
bool isValidConst;
|
bool isValidConst;
|
||||||
|
|
||||||
if (constVal->getType()->isIntegral()
|
if ((constVal->getType()->isIntegral()
|
||||||
|
|| constVal->getType()->isPointerType())
|
||||||
&& GetConstantValueAsSignedInt(constVal, isValidConst) == 0
|
&& GetConstantValueAsSignedInt(constVal, isValidConst) == 0
|
||||||
&& isValidConst)
|
&& isValidConst)
|
||||||
{
|
{
|
||||||
// That constant ia a zero after all...
|
// That constant is a zero after all...
|
||||||
// Use the left child of the setCC instruction as the first argument!
|
// Use the left child of the setCC instruction as the first argument!
|
||||||
mvec[0] = new MachineInstr(ChooseBprInstruction(subtreeRoot));
|
mvec[0] = new MachineInstr(ChooseBprInstruction(subtreeRoot));
|
||||||
mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
|
mvec[0]->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
|
||||||
|
@ -1399,8 +1418,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
// ELSE FALL THROUGH
|
// ELSE FALL THROUGH
|
||||||
}
|
}
|
||||||
|
|
||||||
case 7: // stmt: BrCond(bool)
|
case 6: // stmt: BrCond(bool)
|
||||||
// bool => boolean was computed with `%b = setcc type reg1 reg2'
|
// bool => boolean was computed with some boolean operator (setCC,Not,...)
|
||||||
// Need to check whether the type was a FP, signed int or unsigned int,
|
// Need to check whether the type was a FP, signed int or unsigned int,
|
||||||
// and check the branching condition in order to choose the branch to use.
|
// and check the branching condition in order to choose the branch to use.
|
||||||
//
|
//
|
||||||
|
@ -1427,8 +1446,10 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 8: // stmt: BrCond(boolreg)
|
case 8: // stmt: BrCond(boolreg)
|
||||||
// bool => boolean is stored in an existing register.
|
case 208: // stmt: BrCond(boolconst)
|
||||||
|
// boolreg => boolean is stored in an existing register.
|
||||||
|
// boolconst => boolean is a constant; can be loaded into a register.
|
||||||
// Just use the branch-on-integer-register instruction!
|
// Just use the branch-on-integer-register instruction!
|
||||||
//
|
//
|
||||||
mvec[0] = new MachineInstr(BRNZ);
|
mvec[0] = new MachineInstr(BRNZ);
|
||||||
|
@ -1439,7 +1460,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
|
|
||||||
// delay slot
|
// delay slot
|
||||||
mvec[numInstr++] = new MachineInstr(NOP); // delay slot
|
mvec[numInstr++] = new MachineInstr(NOP); // delay slot
|
||||||
|
|
||||||
// false branch
|
// false branch
|
||||||
mvec[numInstr++] = new MachineInstr(BA);
|
mvec[numInstr++] = new MachineInstr(BA);
|
||||||
mvec[numInstr-1]->SetMachineOperand(0, MachineOperand::MO_CCRegister,
|
mvec[numInstr-1]->SetMachineOperand(0, MachineOperand::MO_CCRegister,
|
||||||
|
@ -1469,6 +1490,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
subtreeRoot->getValue());
|
subtreeRoot->getValue());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 322: // reg: ToBoolTy(bool):
|
||||||
case 22: // reg: ToBoolTy(reg):
|
case 22: // reg: ToBoolTy(reg):
|
||||||
opType = subtreeRoot->leftChild()->getValue()->getType();
|
opType = subtreeRoot->leftChild()->getValue()->getType();
|
||||||
assert(opType->isIntegral() || opType == Type::BoolTy);
|
assert(opType->isIntegral() || opType == Type::BoolTy);
|
||||||
|
@ -1693,8 +1715,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
if (subtreeRoot->leftChild()->getValue()->getType()->isIntegral() ||
|
if (subtreeRoot->leftChild()->getValue()->getType()->isIntegral() ||
|
||||||
subtreeRoot->leftChild()->getValue()->getType()->isPointerType())
|
subtreeRoot->leftChild()->getValue()->getType()->isPointerType())
|
||||||
{
|
{
|
||||||
// integer condition: destination should be %g0 or integer register
|
// Integer condition: destination should be %g0 or integer register.
|
||||||
// if result must be saved but condition is not SetEQ then we need
|
// If result must be saved but condition is not SetEQ then we need
|
||||||
// a separate instruction to compute the bool result, so discard
|
// a separate instruction to compute the bool result, so discard
|
||||||
// result of SUBcc instruction anyway.
|
// result of SUBcc instruction anyway.
|
||||||
//
|
//
|
||||||
|
@ -1914,14 +1936,18 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
|
|
||||||
case 62: // reg: Shl(reg, reg)
|
case 62: // reg: Shl(reg, reg)
|
||||||
opType = subtreeRoot->leftChild()->getValue()->getType();
|
opType = subtreeRoot->leftChild()->getValue()->getType();
|
||||||
assert(opType->isIntegral() || opType == Type::BoolTy);
|
assert(opType->isIntegral()
|
||||||
|
|| opType == Type::BoolTy
|
||||||
|
|| opType->isPointerType() && "Shl unsupported for other types");
|
||||||
mvec[0] = new MachineInstr((opType == Type::LongTy)? SLLX : SLL);
|
mvec[0] = new MachineInstr((opType == Type::LongTy)? SLLX : SLL);
|
||||||
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
|
Set3OperandsFromInstr(mvec[0], subtreeRoot, target);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 63: // reg: Shr(reg, reg)
|
case 63: // reg: Shr(reg, reg)
|
||||||
opType = subtreeRoot->leftChild()->getValue()->getType();
|
opType = subtreeRoot->leftChild()->getValue()->getType();
|
||||||
assert(opType->isIntegral() || opType == Type::BoolTy);
|
assert(opType->isIntegral()
|
||||||
|
|| opType == Type::BoolTy
|
||||||
|
|| opType->isPointerType() && "Shr unsupported for other types");
|
||||||
mvec[0] = new MachineInstr((opType->isSigned()
|
mvec[0] = new MachineInstr((opType->isSigned()
|
||||||
? ((opType == Type::LongTy)? SRAX : SRA)
|
? ((opType == Type::LongTy)? SRAX : SRA)
|
||||||
: ((opType == Type::LongTy)? SRLX : SRL)));
|
: ((opType == Type::LongTy)? SRLX : SRL)));
|
||||||
|
@ -1959,8 +1985,16 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
case 130:
|
case 130:
|
||||||
case 131:
|
case 131:
|
||||||
case 132:
|
case 132:
|
||||||
|
case 133:
|
||||||
case 153:
|
case 153:
|
||||||
case 155:
|
case 155:
|
||||||
|
case 221:
|
||||||
|
case 222:
|
||||||
|
case 232:
|
||||||
|
case 241:
|
||||||
|
case 242:
|
||||||
|
case 243:
|
||||||
|
case 244:
|
||||||
//
|
//
|
||||||
// These are all chain rules, which have a single nonterminal on the RHS.
|
// These are all chain rules, which have a single nonterminal on the RHS.
|
||||||
// Get the rule that matches the RHS non-terminal and use that instead.
|
// Get the rule that matches the RHS non-terminal and use that instead.
|
||||||
|
@ -1985,8 +2019,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
|
||||||
// If not, insert a copy instruction which should get coalesced away
|
// If not, insert a copy instruction which should get coalesced away
|
||||||
// by register allocation.
|
// by register allocation.
|
||||||
if (subtreeRoot->parent() != NULL)
|
if (subtreeRoot->parent() != NULL)
|
||||||
ForwardOperand(subtreeRoot, (InstructionNode*) subtreeRoot->parent(),
|
ForwardOperand(subtreeRoot, subtreeRoot->parent(), forwardOperandNum);
|
||||||
forwardOperandNum);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int n = numInstr++;
|
int n = numInstr++;
|
||||||
|
|
Loading…
Reference in New Issue