forked from OSchip/llvm-project
Refactor the tablegen DAGISelEmitter code for outputing calls to
getTargetNode and SelectNodeTo to reduce duplication, and to make some of the getTargetNode code available to SelectNodeTo. Use SelectNodeTo instead of getTargetNode in several new interesting cases, as it mutates nodes in place instead of creating new ones. This triggers some scheduling behavior differences due to nodes being presented to the scheduler in a different order. Some of the arbitrary scheduling decisions it makes are now arbitrarily made differently. This is visible in CodeGen/PowerPC/LargeAbsoluteAddr.ll, where a trivial scheduling difference led to a trivial register allocation difference. llvm-svn: 53203
This commit is contained in:
parent
1214860a78
commit
d6ec05077f
|
@ -1,7 +1,7 @@
|
|||
; RUN: llvm-as < %s | llc -march=ppc32 -mtriple=powerpc-apple-darwin | \
|
||||
; RUN: grep {stw r3, 32751}
|
||||
; RUN: grep {stw r2, 32751}
|
||||
; RUN: llvm-as < %s | llc -march=ppc64 -mtriple=powerpc-apple-darwin | \
|
||||
; RUN: grep {stw r3, 32751}
|
||||
; RUN: grep {stw r2, 32751}
|
||||
; RUN: llvm-as < %s | llc -march=ppc64 -mtriple=powerpc-apple-darwin | \
|
||||
; RUN: grep {std r2, 9024}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1033,25 +1034,26 @@ public:
|
|||
}
|
||||
|
||||
unsigned ResNo = TmpNo++;
|
||||
if (!isRoot || InputHasChain || NodeHasChain || NodeHasOutFlag ||
|
||||
NodeHasOptInFlag || HasImpResults) {
|
||||
std::string Code;
|
||||
std::string Code2;
|
||||
|
||||
unsigned OpsNo = OpcNo;
|
||||
std::string CodePrefix;
|
||||
bool ChainAssignmentNeeded = NodeHasChain && !isRoot;
|
||||
std::deque<std::string> After;
|
||||
std::string NodeName;
|
||||
if (!isRoot) {
|
||||
NodeName = "Tmp" + utostr(ResNo);
|
||||
Code2 = "SDOperand " + NodeName + "(";
|
||||
CodePrefix = "SDOperand " + NodeName + "(";
|
||||
} else {
|
||||
NodeName = "ResNode";
|
||||
if (!ResNodeDecled) {
|
||||
Code2 = "SDNode *" + NodeName + " = ";
|
||||
CodePrefix = "SDNode *" + NodeName + " = ";
|
||||
ResNodeDecled = true;
|
||||
} else
|
||||
Code2 = NodeName + " = ";
|
||||
CodePrefix = NodeName + " = ";
|
||||
}
|
||||
|
||||
Code += "CurDAG->getTargetNode(Opc" + utostr(OpcNo);
|
||||
unsigned OpsNo = OpcNo;
|
||||
std::string Code = "Opc" + utostr(OpcNo);
|
||||
|
||||
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
|
||||
|
||||
// Output order: results, chain, flags
|
||||
|
@ -1154,61 +1156,55 @@ public:
|
|||
|
||||
if (!isRoot)
|
||||
Code += "), 0";
|
||||
emitCode(Code2 + Code + ");");
|
||||
|
||||
if (NodeHasChain) {
|
||||
// Remember which op produces the chain.
|
||||
if (!isRoot)
|
||||
emitCode(ChainName + " = SDOperand(" + NodeName +
|
||||
".Val, " + utostr(NumResults+NumDstRegs) + ");");
|
||||
else
|
||||
emitCode(ChainName + " = SDOperand(" + NodeName +
|
||||
", " + utostr(NumResults+NumDstRegs) + ");");
|
||||
}
|
||||
|
||||
if (!isRoot) {
|
||||
NodeOps.push_back("Tmp" + utostr(ResNo));
|
||||
return NodeOps;
|
||||
}
|
||||
|
||||
bool NeedReplace = false;
|
||||
if (!isRoot) {
|
||||
NodeOps.push_back("Tmp" + utostr(ResNo));
|
||||
} else {
|
||||
|
||||
if (NodeHasOutFlag) {
|
||||
if (!InFlagDecled) {
|
||||
emitCode("SDOperand InFlag(ResNode, " +
|
||||
utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) + ");");
|
||||
After.push_back("SDOperand InFlag(ResNode, " +
|
||||
utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
|
||||
");");
|
||||
InFlagDecled = true;
|
||||
} else
|
||||
emitCode("InFlag = SDOperand(ResNode, " +
|
||||
utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) + ");");
|
||||
After.push_back("InFlag = SDOperand(ResNode, " +
|
||||
utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
|
||||
");");
|
||||
}
|
||||
|
||||
if (FoldedChains.size() > 0) {
|
||||
std::string Code;
|
||||
for (unsigned j = 0, e = FoldedChains.size(); j < e; j++)
|
||||
emitCode("ReplaceUses(SDOperand(" +
|
||||
After.push_back("ReplaceUses(SDOperand(" +
|
||||
FoldedChains[j].first + ".Val, " +
|
||||
utostr(FoldedChains[j].second) + "), SDOperand(ResNode, " +
|
||||
utostr(FoldedChains[j].second) +
|
||||
"), SDOperand(ResNode, " +
|
||||
utostr(NumResults+NumDstRegs) + "));");
|
||||
NeedReplace = true;
|
||||
}
|
||||
|
||||
if (NodeHasOutFlag) {
|
||||
if (FoldedFlag.first != "") {
|
||||
emitCode("ReplaceUses(SDOperand(" + FoldedFlag.first + ".Val, " +
|
||||
After.push_back("ReplaceUses(SDOperand(" + FoldedFlag.first +
|
||||
".Val, " +
|
||||
utostr(FoldedFlag.second) + "), InFlag);");
|
||||
} else {
|
||||
assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
|
||||
emitCode("ReplaceUses(SDOperand(N.Val, " +
|
||||
After.push_back("ReplaceUses(SDOperand(N.Val, " +
|
||||
utostr(NumPatResults + (unsigned)InputHasChain)
|
||||
+"), InFlag);");
|
||||
}
|
||||
NeedReplace = true;
|
||||
}
|
||||
|
||||
if (NeedReplace && InputHasChain)
|
||||
emitCode("ReplaceUses(SDOperand(N.Val, " +
|
||||
if (NeedReplace && InputHasChain) {
|
||||
After.push_back("ReplaceUses(SDOperand(N.Val, " +
|
||||
utostr(NumPatResults) + "), SDOperand(" + ChainName
|
||||
+ ".Val, " + ChainName + ".ResNo" + "));");
|
||||
ChainAssignmentNeeded |= NodeHasChain;
|
||||
}
|
||||
|
||||
// User does not expect the instruction would produce a chain!
|
||||
if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
|
||||
|
@ -1216,46 +1212,57 @@ public:
|
|||
} else if (InputHasChain && !NodeHasChain) {
|
||||
// One of the inner node produces a chain.
|
||||
if (NodeHasOutFlag)
|
||||
emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(NumPatResults+1) +
|
||||
After.push_back("ReplaceUses(SDOperand(N.Val, " +
|
||||
utostr(NumPatResults+1) +
|
||||
"), SDOperand(ResNode, N.ResNo-1));");
|
||||
emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(NumPatResults) +
|
||||
"), " + ChainName + ");");
|
||||
After.push_back("ReplaceUses(SDOperand(N.Val, " +
|
||||
utostr(NumPatResults) + "), " + ChainName + ");");
|
||||
NeedReplace = true;
|
||||
}
|
||||
}
|
||||
|
||||
emitCode("return ResNode;");
|
||||
if (ChainAssignmentNeeded) {
|
||||
// Remember which op produces the chain.
|
||||
std::string ChainAssign;
|
||||
if (!isRoot)
|
||||
ChainAssign = ChainName + " = SDOperand(" + NodeName +
|
||||
".Val, " + utostr(NumResults+NumDstRegs) + ");";
|
||||
else
|
||||
ChainAssign = ChainName + " = SDOperand(" + NodeName +
|
||||
", " + utostr(NumResults+NumDstRegs) + ");";
|
||||
|
||||
After.push_front(ChainAssign);
|
||||
}
|
||||
|
||||
// Use getTargetNode or SelectNodeTo? The safe choice is getTargetNode,
|
||||
// but SelectNodeTo can be faster.
|
||||
//
|
||||
// SelectNodeTo is not safe in a non-root context, or if there is any
|
||||
// replacement of results needed.
|
||||
//
|
||||
// SelectNodeTo is not profitable if it would require a dynamically
|
||||
// allocated operand list in a situation where getTargetNode would be
|
||||
// able to reuse a co-allocated operand list (as in a unary, binary or
|
||||
// ternary SDNode, for example).
|
||||
//
|
||||
if (!isRoot || NeedReplace ||
|
||||
(!IsVariadic && AllOps.size() < 4 &&
|
||||
Pattern->getNumChildren() + InputHasChain + NodeHasInFlag <
|
||||
AllOps.size())) {
|
||||
Code = "CurDAG->getTargetNode(" + Code;
|
||||
} else {
|
||||
std::string Code = "return CurDAG->SelectNodeTo(N.Val, Opc" +
|
||||
utostr(OpcNo);
|
||||
if (N->getTypeNum(0) != MVT::isVoid)
|
||||
Code += ", VT" + utostr(VTNo);
|
||||
if (NodeHasOutFlag)
|
||||
Code += ", MVT::Flag";
|
||||
Code = "CurDAG->SelectNodeTo(N.Val, " + Code;
|
||||
}
|
||||
if (isRoot) {
|
||||
if (After.empty())
|
||||
CodePrefix = "return ";
|
||||
else
|
||||
After.push_back("return ResNode;");
|
||||
}
|
||||
|
||||
if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
|
||||
AllOps.push_back("InFlag");
|
||||
|
||||
unsigned NumOps = AllOps.size();
|
||||
if (NumOps) {
|
||||
if (!NodeHasOptInFlag && NumOps < 4) {
|
||||
for (unsigned i = 0; i != NumOps; ++i)
|
||||
Code += ", " + AllOps[i];
|
||||
} else {
|
||||
std::string OpsCode = "SDOperand Ops" + utostr(OpcNo) + "[] = { ";
|
||||
for (unsigned i = 0; i != NumOps; ++i) {
|
||||
OpsCode += AllOps[i];
|
||||
if (i != NumOps-1)
|
||||
OpsCode += ", ";
|
||||
}
|
||||
emitCode(OpsCode + " };");
|
||||
Code += ", Ops" + utostr(OpcNo) + ", ";
|
||||
Code += utostr(NumOps);
|
||||
}
|
||||
}
|
||||
emitCode(Code + ");");
|
||||
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
|
||||
if (N->getTypeNum(0) != MVT::isVoid)
|
||||
emitVT(getEnumName(N->getTypeNum(0)));
|
||||
}
|
||||
emitCode(CodePrefix + Code + ");");
|
||||
for (unsigned i = 0, e = After.size(); i != e; ++i)
|
||||
emitCode(After[i]);
|
||||
|
||||
return NodeOps;
|
||||
} else if (Op->isSubClassOf("SDNodeXForm")) {
|
||||
|
|
Loading…
Reference in New Issue