mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-10-27 09:17:11 +00:00
Split SelectionDAGISel::IsLegalAndProfitableToFold to
IsLegalToFold and IsProfitableToFold. The generic version of the later simply checks whether the folding candidate has a single use. This allows the target isel routines more flexibility in deciding whether folding makes sense. The specific case we are interested in is folding constant pool loads with multiple uses. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@96255 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -85,11 +85,13 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// IsLegalAndProfitableToFold - Returns true if the specific operand node N of
|
/// IsProfitableToFold - Returns true if it's profitable to fold the specific
|
||||||
/// U can be folded during instruction selection that starts at Root and
|
/// operand node N of U during instruction selection that starts at Root.
|
||||||
/// folding N is profitable.
|
virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const;
|
||||||
virtual
|
|
||||||
bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U, SDNode *Root) const;
|
/// IsLegalToFold - Returns true if the specific operand node N of
|
||||||
|
/// U can be folded during instruction selection that starts at Root.
|
||||||
|
virtual bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const;
|
||||||
|
|
||||||
/// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer
|
/// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer
|
||||||
/// to use for this target when scheduling the DAG.
|
/// to use for this target when scheduling the DAG.
|
||||||
|
|||||||
@@ -1341,8 +1341,7 @@ static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse,
|
|||||||
/// isNonImmUse - Start searching from Root up the DAG to check is Def can
|
/// isNonImmUse - Start searching from Root up the DAG to check is Def can
|
||||||
/// be reached. Return true if that's the case. However, ignore direct uses
|
/// be reached. Return true if that's the case. However, ignore direct uses
|
||||||
/// by ImmedUse (which would be U in the example illustrated in
|
/// by ImmedUse (which would be U in the example illustrated in
|
||||||
/// IsLegalAndProfitableToFold) and by Root (which can happen in the store
|
/// IsLegalToFold) and by Root (which can happen in the store case).
|
||||||
/// case).
|
|
||||||
/// FIXME: to be really generic, we should allow direct use by any node
|
/// FIXME: to be really generic, we should allow direct use by any node
|
||||||
/// that is being folded. But realisticly since we only fold loads which
|
/// that is being folded. But realisticly since we only fold loads which
|
||||||
/// have one non-chain use, we only need to watch out for load/op/store
|
/// have one non-chain use, we only need to watch out for load/op/store
|
||||||
@@ -1353,11 +1352,17 @@ static inline bool isNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse) {
|
|||||||
return findNonImmUse(Root, Def, ImmedUse, Root, Visited);
|
return findNonImmUse(Root, Def, ImmedUse, Root, Visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// IsLegalAndProfitableToFold - Returns true if the specific operand node N of
|
/// IsProfitableToFold - Returns true if it's profitable to fold the specific
|
||||||
/// U can be folded during instruction selection that starts at Root and
|
/// operand node N of U during instruction selection that starts at Root.
|
||||||
/// folding N is profitable.
|
bool SelectionDAGISel::IsProfitableToFold(SDValue N, SDNode *U,
|
||||||
bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
|
SDNode *Root) const {
|
||||||
SDNode *Root) const {
|
if (OptLevel == CodeGenOpt::None) return false;
|
||||||
|
return N.hasOneUse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// IsLegalToFold - Returns true if the specific operand node N of
|
||||||
|
/// U can be folded during instruction selection that starts at Root.
|
||||||
|
bool SelectionDAGISel::IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const {
|
||||||
if (OptLevel == CodeGenOpt::None) return false;
|
if (OptLevel == CodeGenOpt::None) return false;
|
||||||
|
|
||||||
// If Root use can somehow reach N through a path that that doesn't contain
|
// If Root use can somehow reach N through a path that that doesn't contain
|
||||||
@@ -1411,7 +1416,7 @@ bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
|
|||||||
VT = Root->getValueType(Root->getNumValues()-1);
|
VT = Root->getValueType(Root->getNumValues()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !isNonImmUse(Root, N, U);
|
return !isNonImmUse(Root, N.getNode(), U);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) {
|
SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) {
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ public:
|
|||||||
return "ARM Instruction Selection";
|
return "ARM Instruction Selection";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void InstructionSelect();
|
||||||
|
|
||||||
/// getI32Imm - Return a target constant of type i32 with the specified
|
/// getI32Imm - Return a target constant of type i32 with the specified
|
||||||
/// value.
|
/// value.
|
||||||
inline SDValue getI32Imm(unsigned Imm) {
|
inline SDValue getI32Imm(unsigned Imm) {
|
||||||
@@ -65,7 +67,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDNode *Select(SDNode *N);
|
SDNode *Select(SDNode *N);
|
||||||
virtual void InstructionSelect();
|
|
||||||
bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A,
|
bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A,
|
||||||
SDValue &B, SDValue &C);
|
SDValue &B, SDValue &C);
|
||||||
bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base,
|
bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base,
|
||||||
|
|||||||
@@ -133,8 +133,7 @@ namespace {
|
|||||||
bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
|
bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
|
||||||
bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
|
bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
|
||||||
|
|
||||||
bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
|
bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const;
|
||||||
SDNode *Root) const;
|
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
|
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
|
||||||
@@ -336,8 +335,8 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MSP430DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
|
bool MSP430DAGToDAGISel::IsLegalToFold(SDValue N, SDNode *U,
|
||||||
SDNode *Root) const {
|
SDNode *Root) const {
|
||||||
if (OptLevel == CodeGenOpt::None) return false;
|
if (OptLevel == CodeGenOpt::None) return false;
|
||||||
|
|
||||||
/// RMW preprocessing creates the following code:
|
/// RMW preprocessing creates the following code:
|
||||||
@@ -364,11 +363,11 @@ bool MSP430DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
|
|||||||
/// during preprocessing) to determine whether it's legal to introduce such
|
/// during preprocessing) to determine whether it's legal to introduce such
|
||||||
/// "cycle" for a moment.
|
/// "cycle" for a moment.
|
||||||
DenseMap<SDNode*, SDNode*>::const_iterator I = RMWStores.find(Root);
|
DenseMap<SDNode*, SDNode*>::const_iterator I = RMWStores.find(Root);
|
||||||
if (I != RMWStores.end() && I->second == N)
|
if (I != RMWStores.end() && I->second == N.getNode())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Proceed to 'generic' cycle finder code
|
// Proceed to 'generic' cycle finder code
|
||||||
return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root);
|
return SelectionDAGISel::IsLegalToFold(N, U, Root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -656,7 +655,7 @@ SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op,
|
|||||||
unsigned Opc8, unsigned Opc16) {
|
unsigned Opc8, unsigned Opc16) {
|
||||||
if (N1.getOpcode() == ISD::LOAD &&
|
if (N1.getOpcode() == ISD::LOAD &&
|
||||||
N1.hasOneUse() &&
|
N1.hasOneUse() &&
|
||||||
IsLegalAndProfitableToFold(N1.getNode(), Op, Op)) {
|
IsLegalToFold(N1, Op, Op)) {
|
||||||
LoadSDNode *LD = cast<LoadSDNode>(N1);
|
LoadSDNode *LD = cast<LoadSDNode>(N1);
|
||||||
if (!isValidIndexedLoad(LD))
|
if (!isValidIndexedLoad(LD))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -1513,8 +1513,7 @@ bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp,
|
|||||||
// Direct load operands are folded in binary operations. But before folding
|
// Direct load operands are folded in binary operations. But before folding
|
||||||
// verify if this folding is legal. Fold only if it is legal otherwise
|
// verify if this folding is legal. Fold only if it is legal otherwise
|
||||||
// convert this direct load to a separate memory operation.
|
// convert this direct load to a separate memory operation.
|
||||||
if(ISel->IsLegalAndProfitableToFold(Op.getOperand(0).getNode(),
|
if(ISel->IsLegalToFold(Op.getOperand(0), Op.getNode(), Op.getNode()))
|
||||||
Op.getNode(), Op.getNode()))
|
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
MemOp = 0;
|
MemOp = 0;
|
||||||
|
|||||||
@@ -594,8 +594,7 @@ bool SystemZDAGToDAGISel::SelectLAAddr(SDNode *Op, SDValue Addr,
|
|||||||
bool SystemZDAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N,
|
bool SystemZDAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N,
|
||||||
SDValue &Base, SDValue &Disp, SDValue &Index) {
|
SDValue &Base, SDValue &Disp, SDValue &Index) {
|
||||||
if (ISD::isNON_EXTLoad(N.getNode()) &&
|
if (ISD::isNON_EXTLoad(N.getNode()) &&
|
||||||
N.hasOneUse() &&
|
IsLegalToFold(N, P, P))
|
||||||
IsLegalAndProfitableToFold(N.getNode(), P, P))
|
|
||||||
return SelectAddrRRI20(P, N.getOperand(1), Base, Disp, Index);
|
return SelectAddrRRI20(P, N.getOperand(1), Base, Disp, Index);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,8 +183,9 @@ namespace {
|
|||||||
|
|
||||||
virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
|
virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
|
||||||
|
|
||||||
virtual
|
virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const;
|
||||||
bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U, SDNode *Root) const;
|
|
||||||
|
virtual bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const;
|
||||||
|
|
||||||
// Include the pieces autogenerated from the target description.
|
// Include the pieces autogenerated from the target description.
|
||||||
#include "X86GenDAGISel.inc"
|
#include "X86GenDAGISel.inc"
|
||||||
@@ -303,11 +304,18 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool X86DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
|
bool
|
||||||
SDNode *Root) const {
|
X86DAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const {
|
||||||
if (OptLevel == CodeGenOpt::None) return false;
|
if (OptLevel == CodeGenOpt::None) return false;
|
||||||
|
|
||||||
if (U == Root)
|
if (!N.hasOneUse())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (N.getOpcode() != ISD::LOAD)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// If N is a load, do additional profitability checks.
|
||||||
|
if (U == Root) {
|
||||||
switch (U->getOpcode()) {
|
switch (U->getOpcode()) {
|
||||||
default: break;
|
default: break;
|
||||||
case X86ISD::ADD:
|
case X86ISD::ADD:
|
||||||
@@ -354,9 +362,17 @@ bool X86DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool X86DAGToDAGISel::IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const {
|
||||||
|
if (OptLevel == CodeGenOpt::None) return false;
|
||||||
|
|
||||||
// Proceed to 'generic' cycle finder code
|
// Proceed to 'generic' cycle finder code
|
||||||
return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root);
|
return SelectionDAGISel::IsLegalToFold(N, U, Root);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
|
/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
|
||||||
@@ -1311,8 +1327,8 @@ bool X86DAGToDAGISel::SelectScalarSSELoad(SDNode *Op, SDValue Pred,
|
|||||||
InChain = N.getOperand(0).getValue(1);
|
InChain = N.getOperand(0).getValue(1);
|
||||||
if (ISD::isNON_EXTLoad(InChain.getNode()) &&
|
if (ISD::isNON_EXTLoad(InChain.getNode()) &&
|
||||||
InChain.getValue(0).hasOneUse() &&
|
InChain.getValue(0).hasOneUse() &&
|
||||||
N.hasOneUse() &&
|
IsProfitableToFold(N, Pred.getNode(), Op) &&
|
||||||
IsLegalAndProfitableToFold(N.getNode(), Pred.getNode(), Op)) {
|
IsLegalToFold(N, Pred.getNode(), Op)) {
|
||||||
LoadSDNode *LD = cast<LoadSDNode>(InChain);
|
LoadSDNode *LD = cast<LoadSDNode>(InChain);
|
||||||
if (!SelectAddr(Op, LD->getBasePtr(), Base, Scale, Index, Disp, Segment))
|
if (!SelectAddr(Op, LD->getBasePtr(), Base, Scale, Index, Disp, Segment))
|
||||||
return false;
|
return false;
|
||||||
@@ -1436,8 +1452,8 @@ bool X86DAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N,
|
|||||||
SDValue &Index, SDValue &Disp,
|
SDValue &Index, SDValue &Disp,
|
||||||
SDValue &Segment) {
|
SDValue &Segment) {
|
||||||
if (ISD::isNON_EXTLoad(N.getNode()) &&
|
if (ISD::isNON_EXTLoad(N.getNode()) &&
|
||||||
N.hasOneUse() &&
|
IsProfitableToFold(N, P, P) &&
|
||||||
IsLegalAndProfitableToFold(N.getNode(), P, P))
|
IsLegalToFold(N, P, P))
|
||||||
return SelectAddr(P, N.getOperand(1), Base, Scale, Index, Disp, Segment);
|
return SelectAddr(P, N.getOperand(1), Base, Scale, Index, Disp, Segment);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -566,8 +566,11 @@ void PatternCodeEmitter::EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
|
|||||||
if (NodeHasChain)
|
if (NodeHasChain)
|
||||||
OpNo = 1;
|
OpNo = 1;
|
||||||
if (!isRoot) {
|
if (!isRoot) {
|
||||||
// Multiple uses of actual result?
|
// Check if it's profitable to fold the node. e.g. Check for multiple uses
|
||||||
emitCheck(getValueName(RootName) + ".hasOneUse()");
|
// of actual result?
|
||||||
|
std::string ParentName(RootName.begin(), RootName.end()-1);
|
||||||
|
emitCheck("IsProfitableToFold(" + getValueName(RootName) +
|
||||||
|
", " + getNodeName(ParentName) + ", N)");
|
||||||
EmittedUseCheck = true;
|
EmittedUseCheck = true;
|
||||||
if (NodeHasChain) {
|
if (NodeHasChain) {
|
||||||
// If the immediate use can somehow reach this node through another
|
// If the immediate use can somehow reach this node through another
|
||||||
@@ -597,8 +600,7 @@ void PatternCodeEmitter::EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (NeedCheck) {
|
if (NeedCheck) {
|
||||||
std::string ParentName(RootName.begin(), RootName.end()-1);
|
emitCheck("IsLegalToFold(" + getValueName(RootName) +
|
||||||
emitCheck("IsLegalAndProfitableToFold(" + getNodeName(RootName) +
|
|
||||||
", " + getNodeName(ParentName) + ", N)");
|
", " + getNodeName(ParentName) + ", N)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user