aboutsummaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2009-06-01 23:27:20 +0000
committerDale Johannesen <dalej@apple.com>2009-06-01 23:27:20 +0000
commitd6758f98bfa1f02e5218ed484002ea120a691a44 (patch)
treef6d49f1a1eadb573ca9969173c76b891c035eb53 /utils
parent9e5d3156100faa4deec87fa3c5bbaabc323a420b (diff)
downloadexternal_llvm-d6758f98bfa1f02e5218ed484002ea120a691a44.zip
external_llvm-d6758f98bfa1f02e5218ed484002ea120a691a44.tar.gz
external_llvm-d6758f98bfa1f02e5218ed484002ea120a691a44.tar.bz2
Make the implicit inputs and outputs of target-independent
ADDC/ADDE use MVT::i1 (later, whatever it gets legalized to) instead of MVT::Flag. Remove CARRY_FALSE in favor of 0; adjust all target-independent code to use this format. Most targets will still produce a Flag-setting target-dependent version when selection is done. X86 is converted to use i32 instead, which means TableGen needs to produce different code in xxxGenDAGISel.inc. This keys off the new supportsHasI1 bit in xxxInstrInfo, currently set only for X86; in principle this is temporary and should go away when all other targets have been converted. All relevant X86 instruction patterns are modified to represent setting and using EFLAGS explicitly. The same can be done on other targets. The immediate behavior change is that an ADC/ADD pair are no longer tightly coupled in the X86 scheduler; they can be separated by instructions that don't clobber the flags (MOV). I will soon add some peephole optimizations based on using other instructions that set the flags to feed into ADC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72707 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp14
-rw-r--r--utils/TableGen/CodeGenTarget.cpp7
-rw-r--r--utils/TableGen/CodeGenTarget.h8
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp64
4 files changed, 75 insertions, 18 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index db76dab..a03224c 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -399,9 +399,13 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
} else if (PropList[i]->getName() == "SDNPHasChain") {
Properties |= 1 << SDNPHasChain;
} else if (PropList[i]->getName() == "SDNPOutFlag") {
- Properties |= 1 << SDNPOutFlag;
+ Properties |= 1 << SDNPOutFlag;
+ assert(!(Properties & (1<<SDNPOutI1)) &&
+ "Can't handle OutFlag and OutI1");
} else if (PropList[i]->getName() == "SDNPInFlag") {
Properties |= 1 << SDNPInFlag;
+ assert(!(Properties & (1<<SDNPInI1)) &&
+ "Can't handle InFlag and InI1");
} else if (PropList[i]->getName() == "SDNPOptInFlag") {
Properties |= 1 << SDNPOptInFlag;
} else if (PropList[i]->getName() == "SDNPMayStore") {
@@ -412,6 +416,14 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
Properties |= 1 << SDNPSideEffect;
} else if (PropList[i]->getName() == "SDNPMemOperand") {
Properties |= 1 << SDNPMemOperand;
+ } else if (PropList[i]->getName() == "SDNPInI1") {
+ Properties |= 1 << SDNPInI1;
+ assert(!(Properties & (1<<SDNPInFlag)) &&
+ "Can't handle InFlag and InI1");
+ } else if (PropList[i]->getName() == "SDNPOutI1") {
+ Properties |= 1 << SDNPOutI1;
+ assert(!(Properties & (1<<SDNPOutFlag)) &&
+ "Can't handle OutFlag and OutI1");
} else {
cerr << "Unknown SD Node property '" << PropList[i]->getName()
<< "' on node '" << R->getName() << "'!\n";
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index aad1be9..a64aef9 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -385,6 +385,13 @@ bool CodeGenTarget::isLittleEndianEncoding() const {
return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
}
+/// supportsHasI1 - Return whether this target supports the implicit I1,
+/// rather than Flags, for ADDC/ADDE
+///
+bool CodeGenTarget::supportsHasI1() const {
+ return getInstructionSet()->getValueAsBit("supportsHasI1");
+}
+
//===----------------------------------------------------------------------===//
// ComplexPattern implementation
//
diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index c7cc77c..c44c6f0 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/utils/TableGen/CodeGenTarget.h
@@ -43,7 +43,9 @@ enum SDNP {
SDNPMayLoad,
SDNPMayStore,
SDNPSideEffect,
- SDNPMemOperand
+ SDNPMemOperand,
+ SDNPInI1,
+ SDNPOutI1
};
// ComplexPattern attributes.
@@ -209,10 +211,12 @@ public:
void getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
&NumberedInstructions);
-
/// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]?
///
bool isLittleEndianEncoding() const;
+
+ /// supportsHasI1 - does this target understand HasI1 for ADDE and ADDC?
+ bool supportsHasI1() const;
};
/// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 0e2e615..4f92011 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -670,7 +670,8 @@ public:
HasChain = true;
FoldedChains.push_back(std::make_pair(RootName, CInfo.getNumResults()));
}
- if (NodeHasProperty(Child, SDNPOutFlag, CGP)) {
+ if (NodeHasProperty(Child, SDNPOutFlag, CGP) ||
+ NodeHasProperty(Child, SDNPOutI1, CGP)) {
assert(FoldedFlag.first == "" && FoldedFlag.second == 0 &&
"Pattern folded multiple nodes which produce flags?");
FoldedFlag = std::make_pair(RootName,
@@ -969,6 +970,10 @@ public:
PatternHasProperty(Pattern, SDNPInFlag, CGP);
bool NodeHasOutFlag = isRoot &&
PatternHasProperty(Pattern, SDNPOutFlag, CGP);
+ bool NodeHasInI1 = isRoot &&
+ PatternHasProperty(Pattern, SDNPInI1, CGP);
+ bool NodeHasOutI1 = isRoot &&
+ PatternHasProperty(Pattern, SDNPOutI1, CGP);
bool NodeHasChain = InstPatNode &&
PatternHasProperty(InstPatNode, SDNPHasChain, CGP);
bool InputHasChain = isRoot &&
@@ -1054,10 +1059,13 @@ public:
// Emit all the chain and CopyToReg stuff.
bool ChainEmitted = NodeHasChain;
- if (NodeHasInFlag || HasImpInputs)
+ // InFlag and InI1 cannot both be set (checked in
+ // CodeGenDAGPatterns), so use the same variables for both.
+ if (NodeHasInFlag || HasImpInputs || NodeHasInI1)
EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
InFlagDecled, ResNodeDecled, true);
- if (NodeHasOptInFlag || NodeHasInFlag || HasImpInputs) {
+ if (NodeHasOptInFlag || NodeHasInFlag || HasImpInputs ||
+ NodeHasInI1) {
if (!InFlagDecled) {
emitCode("SDValue InFlag(0, 0);");
InFlagDecled = true;
@@ -1113,7 +1121,7 @@ public:
}
if (NodeHasChain)
Code += ", MVT::Other";
- if (NodeHasOutFlag)
+ if (NodeHasOutFlag || (NodeHasOutI1 && !CGT.supportsHasI1()))
Code += ", MVT::Flag";
// Inputs.
@@ -1173,7 +1181,8 @@ public:
}
Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
".size()";
- } else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
+ } else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs ||
+ NodeHasInI1)
AllOps.push_back("InFlag");
unsigned NumOps = AllOps.size();
@@ -1207,7 +1216,7 @@ public:
NodeOps.push_back("Tmp" + utostr(ResNo));
} else {
- if (NodeHasOutFlag) {
+ if (NodeHasOutFlag || NodeHasOutI1) {
if (!InFlagDecled) {
After.push_back("SDValue InFlag(ResNode, " +
utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
@@ -1228,13 +1237,15 @@ public:
utostr(NumResults+NumDstRegs) + ")");
}
- if (NodeHasOutFlag) {
+ if (NodeHasOutFlag || NodeHasOutI1) {
if (FoldedFlag.first != "") {
- ReplaceFroms.push_back("SDValue(" + FoldedFlag.first + ".getNode(), " +
+ ReplaceFroms.push_back("SDValue(" + FoldedFlag.first +
+ ".getNode(), " +
utostr(FoldedFlag.second) + ")");
ReplaceTos.push_back("InFlag");
} else {
- assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
+ assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP) ||
+ NodeHasProperty(Pattern, SDNPOutI1, CGP));
ReplaceFroms.push_back("SDValue(N.getNode(), " +
utostr(NumPatResults + (unsigned)InputHasChain)
+ ")");
@@ -1251,7 +1262,8 @@ public:
}
// User does not expect the instruction would produce a chain!
- if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
+ if ((!InputHasChain && NodeHasChain) &&
+ (NodeHasOutFlag || NodeHasOutI1)) {
;
} else if (InputHasChain && !NodeHasChain) {
// One of the inner node produces a chain.
@@ -1391,6 +1403,8 @@ private:
unsigned OpNo =
(unsigned) NodeHasProperty(N, SDNPHasChain, CGP);
bool HasInFlag = NodeHasProperty(N, SDNPInFlag, CGP);
+ bool HasInI1 = NodeHasProperty(N, SDNPInI1, CGP);
+ bool InFlagDefined = false;
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
TreePatternNode *Child = N->getChild(i);
if (!Child->isLeaf()) {
@@ -1424,21 +1438,41 @@ private:
emitCode("SDValue InFlag(0, 0);");
InFlagDecled = true;
}
- std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
- emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
+ if (HasInI1) {
+ if (!ResNodeDecled) {
+ emitCode("SDNode * ResNode;");
+ }
+ if (T.supportsHasI1())
+ emitCode("ResNode = CurDAG->getCopyToReg(" + ChainName +
+ ", " + RootName + ".getDebugLoc()" +
+ ", " + getEnumName(RVT) +
+ ", " + getQualifiedName(RR) +
+ ", " + RootName + utostr(OpNo) + ").getNode();");
+ else
+ emitCode("ResNode = CurDAG->getCopyToReg(" + ChainName +
+ ", " + RootName + ".getDebugLoc()" +
+ ", " + getQualifiedName(RR) +
+ ", " + RootName + utostr(OpNo) +
+ ", InFlag).getNode();");
+ InFlagDefined = true;
+ } else {
+ std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
+ emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
", " + RootName + ".getDebugLoc()" +
", " + getQualifiedName(RR) +
- ", " + RootName + utostr(OpNo) + ", InFlag).getNode();");
- ResNodeDecled = true;
+ ", " + RootName + utostr(OpNo) +
+ ", InFlag).getNode();");
+ }
emitCode(ChainName + " = SDValue(ResNode, 0);");
emitCode("InFlag = SDValue(ResNode, 1);");
+ ResNodeDecled = true;
}
}
}
}
}
- if (HasInFlag) {
+ if (HasInFlag || (HasInI1 && !InFlagDefined)) {
if (!InFlagDecled) {
emitCode("SDValue InFlag = " + RootName +
".getOperand(" + utostr(OpNo) + ");");