aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2008-05-29 19:57:41 +0000
committerDan Gohman <gohman@apple.com>2008-05-29 19:57:41 +0000
commit3329ffe4748f2248600a68ec489e36bded49b51d (patch)
tree167ea139429affa229aaff59e15188e662dee79e
parent8c3978613661e18d4994b7b65ad1ac222a8ee0be (diff)
downloadexternal_llvm-3329ffe4748f2248600a68ec489e36bded49b51d.zip
external_llvm-3329ffe4748f2248600a68ec489e36bded49b51d.tar.gz
external_llvm-3329ffe4748f2248600a68ec489e36bded49b51d.tar.bz2
Fix a tblgen problem handling variable_ops in tblgen instruction
definitions. This adds a new construct, "discard", for indicating that a named node in the input matching pattern is to be discarded, instead of corresponding to a node in the output pattern. This allows tblgen to know where the arguments for the varaible_ops are supposed to begin. This fixes "rdar://5791600", whatever that is ;-). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51699 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Target.td6
-rw-r--r--lib/Target/TargetSelectionDAG.td1
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp29
-rw-r--r--lib/Target/X86/X86InstrInfo.td6
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp2
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp3
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp47
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp12
8 files changed, 54 insertions, 52 deletions
diff --git a/lib/Target/Target.td b/lib/Target/Target.td
index a268e16..92c4057 100644
--- a/lib/Target/Target.td
+++ b/lib/Target/Target.td
@@ -259,6 +259,12 @@ def ins;
/// of operands.
def variable_ops;
+/// discard definition - Mark this operand as being matched in the input
+/// but omitted from the output. This is necessary in some situations
+/// involving variable_ops to help the pattern matcher determine which
+/// input nodes to forward on to the variable_ops portion of the output.
+def discard;
+
/// ptr_rc definition - Mark this operand as being a pointer value whose
/// register class is resolved dynamically via a callback to TargetInstrInfo.
/// FIXME: We should probably change this to a class which contain a list of
diff --git a/lib/Target/TargetSelectionDAG.td b/lib/Target/TargetSelectionDAG.td
index f194443..9def220 100644
--- a/lib/Target/TargetSelectionDAG.td
+++ b/lib/Target/TargetSelectionDAG.td
@@ -470,6 +470,7 @@ class PatLeaf<dag frag, code pred = [{}], SDNodeXForm xform = NOOP_SDNodeXForm>
def vtInt : PatLeaf<(vt), [{ return MVT::isInteger(N->getVT()); }]>;
def vtFP : PatLeaf<(vt), [{ return MVT::isFloatingPoint(N->getVT()); }]>;
+def immAllZeros : PatLeaf<(imm), [{ return N->isNullValue(); }]>;
def immAllOnes : PatLeaf<(imm), [{ return N->isAllOnesValue(); }]>;
def immAllOnesV: PatLeaf<(build_vector), [{
return ISD::isBuildVectorAllOnes(N);
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index 576661d..bb8c58a 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -1175,35 +1175,6 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
case X86ISD::GlobalBaseReg:
return getGlobalBaseReg();
- // FIXME: This is a workaround for a tblgen problem: rdar://5791600
- case X86ISD::RET_FLAG:
- if (ConstantSDNode *Amt = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
- if (Amt->getSignExtended() != 0) break;
-
- // Match (X86retflag 0).
- SDOperand Chain = N.getOperand(0);
- bool HasInFlag = N.getOperand(N.getNumOperands()-1).getValueType()
- == MVT::Flag;
- SmallVector<SDOperand, 8> Ops0;
- AddToISelQueue(Chain);
- SDOperand InFlag(0, 0);
- if (HasInFlag) {
- InFlag = N.getOperand(N.getNumOperands()-1);
- AddToISelQueue(InFlag);
- }
- for (unsigned i = 2, e = N.getNumOperands()-(HasInFlag?1:0); i != e;
- ++i) {
- AddToISelQueue(N.getOperand(i));
- Ops0.push_back(N.getOperand(i));
- }
- Ops0.push_back(Chain);
- if (HasInFlag)
- Ops0.push_back(InFlag);
- return CurDAG->getTargetNode(X86::RET, MVT::Other,
- &Ops0[0], Ops0.size());
- }
- break;
-
case ISD::ADD: {
// Turn ADD X, c to MOV32ri X+c. This cannot be done with tblgen'd
// code and is matched first so to prevent it from being turned into
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 843fbd0..d0bd955 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -45,7 +45,7 @@ def SDT_X86CallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
def SDT_X86CallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>,
SDTCisVT<1, i32> ]>;
-def SDT_X86Call : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
+def SDT_X86Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>;
@@ -322,9 +322,9 @@ let neverHasSideEffects = 1, isNotDuplicable = 1 in
// Return instructions.
let isTerminator = 1, isReturn = 1, isBarrier = 1,
hasCtrlDep = 1, FPForm = SpecialFP, FPFormBits = SpecialFP.Value in {
- def RET : I <0xC3, RawFrm, (outs), (ins variable_ops),
+ def RET : I <0xC3, RawFrm, (outs), (ins discard:$amt, variable_ops),
"ret",
- [/*(X86retflag 0)*/ /*FIXME: Disabled: rdar://5791600*/]>;
+ [(X86retflag immAllZeros:$amt)]>;
def RETI : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
"ret\t$amt",
[(X86retflag imm:$amt)]>;
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 8c46b35..006c067 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -916,6 +916,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP);
} else if (OperandNode->getName() == "unknown") {
MadeChange |= Child->UpdateNodeType(MVT::isUnknown, TP);
+ } else if (OperandNode->getName() == "discard") {
+ MadeChange |= Child->UpdateNodeType(MVT::isUnknown, TP);
} else {
assert(0 && "Unknown operand type!");
abort();
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 37c2069..d520378 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -163,7 +163,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
isVariadic = true;
continue;
} else if (!Rec->isSubClassOf("RegisterClass") &&
- Rec->getName() != "ptr_rc" && Rec->getName() != "unknown")
+ Rec->getName() != "ptr_rc" && Rec->getName() != "unknown" &&
+ Rec->getName() != "discard")
throw "Unknown operand class '" + Rec->getName() +
"' in instruction '" + R->getName() + "' instruction!";
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 72bd5bd..b112b7e 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -947,22 +947,20 @@ public:
// instruction operands to do this.
std::vector<std::string> AllOps;
unsigned NumEAInputs = 0; // # of synthesized 'execute always' inputs.
+ unsigned NumDiscardedInputs = 0; // # of 'discard' inputs to skip.
for (unsigned ChildNo = 0, InstOpNo = NumResults;
InstOpNo != II.OperandList.size(); ++InstOpNo) {
std::vector<std::string> Ops;
- // If this is a normal operand or a predicate operand without
- // 'execute always', emit it.
+ // Determine what to emit for this operand.
Record *OperandNode = II.OperandList[InstOpNo].Rec;
- if ((!OperandNode->isSubClassOf("PredicateOperand") &&
- !OperandNode->isSubClassOf("OptionalDefOperand")) ||
- CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
- Ops = EmitResultCode(N->getChild(ChildNo), DstRegs,
- InFlagDecled, ResNodeDecled);
- AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
- ++ChildNo;
- } else {
- // Otherwise, this is a predicate or optional def operand, emit the
+ if (OperandNode->getName() == "discard") {
+ // This is a "discard" operand; emit nothing. Just note it.
+ ++NumDiscardedInputs;
+ } else if ((OperandNode->isSubClassOf("PredicateOperand") ||
+ OperandNode->isSubClassOf("OptionalDefOperand")) &&
+ !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
+ // This is a predicate or optional def operand; emit the
// 'default ops' operands.
const DAGDefaultOperand &DefaultOp =
CGP.getDefaultOperand(II.OperandList[InstOpNo].Rec);
@@ -972,6 +970,13 @@ public:
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
NumEAInputs += Ops.size();
}
+ } else {
+ // Otherwise this is a normal operand or a predicate operand without
+ // 'execute always'; emit it.
+ Ops = EmitResultCode(N->getChild(ChildNo), DstRegs,
+ InFlagDecled, ResNodeDecled);
+ AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
+ ++ChildNo;
}
}
@@ -1049,19 +1054,23 @@ public:
if (NodeHasOutFlag)
Code += ", MVT::Flag";
- // Figure out how many fixed inputs the node has. This is important to
- // know which inputs are the variable ones if present.
- unsigned NumInputs = AllOps.size();
- NumInputs += NodeHasChain;
-
// Inputs.
if (HasVarOps) {
+ // Figure out how many fixed inputs the node has. This is important
+ // to know which inputs are the variable ones if present. Include
+ // the 'discard' and chain inputs in the count, and adjust for the
+ // number of operands that are 'execute always'. This is the index
+ // where we should start copying operands into the 'variable_ops'
+ // portion of the output.
+ unsigned InputIndex = AllOps.size() +
+ NumDiscardedInputs +
+ NodeHasChain -
+ NumEAInputs;
+
for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
AllOps.clear();
- }
- if (HasVarOps) {
// Figure out whether any operands at the end of the op list are not
// part of the variable section.
std::string EndAdjust;
@@ -1070,7 +1079,7 @@ public:
else if (NodeHasOptInFlag)
EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
- emitCode("for (unsigned i = " + utostr(NumInputs - NumEAInputs) +
+ emitCode("for (unsigned i = " + utostr(InputIndex) +
", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
emitCode(" AddToISelQueue(N.getOperand(i));");
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 028fbeb..8390c90 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -85,6 +85,10 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
Record *OpR = OperandList[j].Rec;
std::string Res;
+ // Discard "discard" operands.
+ if (OpR->getName() == "discard")
+ continue;
+
if (OpR->isSubClassOf("RegisterClass"))
Res += getQualifiedName(OpR) + "RegClassID, ";
else
@@ -201,6 +205,14 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
// Each logical operand can be multiple MI operands.
MinOperands = Inst.OperandList.back().MIOperandNo +
Inst.OperandList.back().MINumOperands;
+
+ // Subtract the number of "discard" operands, which we'll be skipping
+ // when emitting OperandInfo records.
+ for (unsigned j = 0, e = Inst.OperandList.size(); j != e; ++j) {
+ Record *OpR = Inst.OperandList[j].Rec;
+ if (OpR->getName() == "discard")
+ --MinOperands;
+ }
OS << " { ";
OS << Num << ",\t" << MinOperands << ",\t"