aboutsummaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorShih-wei Liao <sliao@google.com>2010-04-07 12:21:42 -0700
committerShih-wei Liao <sliao@google.com>2010-04-07 12:21:42 -0700
commite4454320b3cfffe926a487c33fbeb454366de2f8 (patch)
tree133c05da684edf4a3b2529bcacfa996298c455f6 /utils
parent20570085304f0a4ab4f112a01d77958bbd2827a1 (diff)
downloadexternal_llvm-e4454320b3cfffe926a487c33fbeb454366de2f8.zip
external_llvm-e4454320b3cfffe926a487c33fbeb454366de2f8.tar.gz
external_llvm-e4454320b3cfffe926a487c33fbeb454366de2f8.tar.bz2
libbcc
Change-Id: Ieaa3ebd5a38f370752495549f8870b534eeedfc5
Diffstat (limited to 'utils')
-rwxr-xr-xutils/GenLibDeps.pl2
-rw-r--r--utils/TableGen/Android.mk46
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp62
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp44
-rw-r--r--utils/TableGen/AsmWriterEmitter.h1
-rw-r--r--utils/TableGen/CMakeLists.txt4
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp346
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h47
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp3
-rw-r--r--utils/TableGen/CodeGenInstruction.h2
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp1967
-rw-r--r--utils/TableGen/DAGISelEmitter.h16
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp402
-rw-r--r--utils/TableGen/DAGISelMatcher.h1112
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp779
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp882
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp509
-rw-r--r--utils/TableGen/InstrEnumEmitter.cpp2
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp444
-rw-r--r--utils/TableGen/Record.h4
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp107
-rw-r--r--utils/buildit/GNUmakefile4
-rwxr-xr-xutils/git/find-rev50
-rw-r--r--utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp2
-rw-r--r--utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp2
-rw-r--r--utils/lit/lit/TestFormats.py7
-rw-r--r--utils/lit/lit/TestRunner.py18
-rw-r--r--utils/lit/lit/TestingConfig.py9
-rw-r--r--utils/llvm.grm1
-rw-r--r--utils/vim/llvm.vim5
-rw-r--r--utils/vim/tablegen.vim2
-rw-r--r--utils/vim/vimrc31
32 files changed, 4635 insertions, 2277 deletions
diff --git a/utils/GenLibDeps.pl b/utils/GenLibDeps.pl
index b320a91..f1f7e72 100755
--- a/utils/GenLibDeps.pl
+++ b/utils/GenLibDeps.pl
@@ -70,6 +70,8 @@ opendir DIR,$Directory;
my @files = readdir DIR;
closedir DIR;
my @libs = grep(/libLLVM.*\.(dylib|so|a)$/,sort(@files));
+# Omit the all-of-llvm shared library.
+@libs = grep(!/libLLVM-\d\.\d(svn)?\.(dylib|so)/, @libs);
my @objs = grep(/LLVM.*\.o$/,sort(@files));
# Declare the hashes we will use to keep track of the library and object file
diff --git a/utils/TableGen/Android.mk b/utils/TableGen/Android.mk
new file mode 100644
index 0000000..e600305
--- /dev/null
+++ b/utils/TableGen/Android.mk
@@ -0,0 +1,46 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ AsmMatcherEmitter.cpp \
+ AsmWriterEmitter.cpp \
+ AsmWriterInst.cpp \
+ CallingConvEmitter.cpp \
+ ClangDiagnosticsEmitter.cpp \
+ CodeEmitterGen.cpp \
+ CodeGenDAGPatterns.cpp \
+ CodeGenInstruction.cpp \
+ CodeGenTarget.cpp \
+ DAGISelEmitter.cpp \
+ DAGISelMatcher.cpp \
+ DAGISelMatcherEmitter.cpp \
+ DAGISelMatcherGen.cpp \
+ DAGISelMatcherOpt.cpp \
+ DisassemblerEmitter.cpp \
+ EDEmitter.cpp \
+ FastISelEmitter.cpp \
+ InstrEnumEmitter.cpp \
+ InstrInfoEmitter.cpp \
+ IntrinsicEmitter.cpp \
+ LLVMCConfigurationEmitter.cpp \
+ OptParserEmitter.cpp \
+ Record.cpp \
+ RegisterInfoEmitter.cpp \
+ SubtargetEmitter.cpp \
+ TGLexer.cpp \
+ TGParser.cpp \
+ TGValueTypes.cpp \
+ TableGen.cpp \
+ TableGenBackend.cpp \
+ X86DisassemblerTables.cpp \
+ X86RecognizableInstr.cpp
+
+REQUIRES_EH := 1
+REQUIRES_RTTI := 1
+
+LOCAL_STATIC_LIBRARIES := libLLVMSupport libLLVMSystem
+LOCAL_MODULE := tblgen
+LOCAL_LDLIBS += -lpthread -lm -ldl
+
+include $(LLVM_HOST_BUILD_MK)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 5b5dd2b..b823e57 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -975,6 +975,16 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
}
+static std::pair<unsigned, unsigned> *
+GetTiedOperandAtIndex(SmallVectorImpl<std::pair<unsigned, unsigned> > &List,
+ unsigned Index) {
+ for (unsigned i = 0, e = List.size(); i != e; ++i)
+ if (Index == List[i].first)
+ return &List[i];
+
+ return 0;
+}
+
static void EmitConvertToMCInst(CodeGenTarget &Target,
std::vector<InstructionInfo*> &Infos,
raw_ostream &OS) {
@@ -1051,15 +1061,12 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
//
// FIXME: This should be removed from the MCInst structure.
for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
- // See if this is a tied operand.
- unsigned i, e = TiedOperands.size();
- for (i = 0; i != e; ++i)
- if (CurIndex == TiedOperands[i].first)
- break;
- if (i == e)
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+ if (!Tie)
Signature += "__Imp";
else
- Signature += "__Tie" + utostr(TiedOperands[i].second);
+ Signature += "__Tie" + utostr(Tie->second);
}
Signature += "__";
@@ -1080,8 +1087,14 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
}
// Add any trailing implicit operands.
- for (; CurIndex != NumMIOperands; ++CurIndex)
- Signature += "Imp";
+ for (; CurIndex != NumMIOperands; ++CurIndex) {
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+ if (!Tie)
+ Signature += "__Imp";
+ else
+ Signature += "__Tie" + utostr(Tie->second);
+ }
II.ConversionFnKind = Signature;
@@ -1103,21 +1116,18 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
// Add the implicit operands.
for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
// See if this is a tied operand.
- unsigned i, e = TiedOperands.size();
- for (i = 0; i != e; ++i)
- if (CurIndex == TiedOperands[i].first)
- break;
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
- if (i == e) {
+ if (!Tie) {
// If not, this is some implicit operand. Just assume it is a register
// for now.
CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
} else {
// Copy the tied operand.
- assert(TiedOperands[i].first > TiedOperands[i].second &&
- "Tied operand preceeds its target!");
+ assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
CvtOS << " Inst.addOperand(Inst.getOperand("
- << TiedOperands[i].second << "));\n";
+ << Tie->second << "));\n";
}
}
@@ -1129,8 +1139,22 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
}
// And add trailing implicit operands.
- for (; CurIndex != NumMIOperands; ++CurIndex)
- CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ for (; CurIndex != NumMIOperands; ++CurIndex) {
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+
+ if (!Tie) {
+ // If not, this is some implicit operand. Just assume it is a register
+ // for now.
+ CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ } else {
+ // Copy the tied operand.
+ assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
+ CvtOS << " Inst.addOperand(Inst.getOperand("
+ << Tie->second << "));\n";
+ }
+ }
+
CvtOS << " break;\n";
}
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index 143a2f7..3a38dd4 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -494,11 +494,55 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
<< "}\n";
}
+void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
+ CodeGenTarget Target;
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+
+ std::vector<const CodeGenInstruction*> NumberedInstructions;
+ Target.getInstructionsByEnumValue(NumberedInstructions);
+
+ StringToOffsetTable StringTable;
+ O <<
+"\n\n#ifdef GET_INSTRUCTION_NAME\n"
+"#undef GET_INSTRUCTION_NAME\n\n"
+"/// getInstructionName: This method is automatically generated by tblgen\n"
+"/// from the instruction set description. This returns the enum name of the\n"
+"/// specified instruction.\n"
+ "const char *" << Target.getName() << ClassName
+ << "::getInstructionName(unsigned Opcode) {\n"
+ << " assert(Opcode < " << NumberedInstructions.size()
+ << " && \"Invalid instruction number!\");\n"
+ << "\n"
+ << " static const unsigned InstAsmOffset[] = {";
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ const CodeGenInstruction &Inst = *NumberedInstructions[i];
+
+ std::string AsmName = Inst.TheDef->getName();
+ if ((i % 14) == 0)
+ O << "\n ";
+
+ O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
+ }
+ O << "0\n"
+ << " };\n"
+ << "\n";
+
+ O << " const char *Strs =\n";
+ StringTable.EmitString(O);
+ O << ";\n";
+
+ O << " return Strs+InstAsmOffset[Opcode];\n"
+ << "}\n\n#endif\n";
+}
+
+
void AsmWriterEmitter::run(raw_ostream &O) {
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
EmitPrintInstruction(O);
EmitGetRegisterName(O);
+ EmitGetInstructionName(O);
}
diff --git a/utils/TableGen/AsmWriterEmitter.h b/utils/TableGen/AsmWriterEmitter.h
index 7862caa..9f7d776 100644
--- a/utils/TableGen/AsmWriterEmitter.h
+++ b/utils/TableGen/AsmWriterEmitter.h
@@ -37,6 +37,7 @@ namespace llvm {
private:
void EmitPrintInstruction(raw_ostream &o);
void EmitGetRegisterName(raw_ostream &o);
+ void EmitGetInstructionName(raw_ostream &o);
AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
assert(ID < NumberedInstructions.size());
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index f344b28..881b50a 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -9,6 +9,10 @@ add_executable(tblgen
CodeGenInstruction.cpp
CodeGenTarget.cpp
DAGISelEmitter.cpp
+ DAGISelMatcherEmitter.cpp
+ DAGISelMatcherGen.cpp
+ DAGISelMatcherOpt.cpp
+ DAGISelMatcher.cpp
DisassemblerEmitter.cpp
EDEmitter.cpp
FastISelEmitter.cpp
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index cf79365..ce737bf 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -447,6 +447,30 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
TypeConstraints.assign(ConstraintList.begin(), ConstraintList.end());
}
+/// getKnownType - If the type constraints on this node imply a fixed type
+/// (e.g. all stores return void, etc), then return it as an
+/// MVT::SimpleValueType. Otherwise, return EEVT::isUnknown.
+unsigned SDNodeInfo::getKnownType() const {
+ unsigned NumResults = getNumResults();
+ assert(NumResults <= 1 &&
+ "We only work with nodes with zero or one result so far!");
+
+ for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) {
+ // Make sure that this applies to the correct node result.
+ if (TypeConstraints[i].OperandNo >= NumResults) // FIXME: need value #
+ continue;
+
+ switch (TypeConstraints[i].ConstraintType) {
+ default: break;
+ case SDTypeConstraint::SDTCisVT:
+ return TypeConstraints[i].x.SDTCisVT_Info.VT;
+ case SDTypeConstraint::SDTCisPtrTy:
+ return MVT::iPTR;
+ }
+ }
+ return EEVT::isUnknown;
+}
+
//===----------------------------------------------------------------------===//
// TreePatternNode implementation
//
@@ -568,33 +592,36 @@ bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
return true; // unreachable
}
+static std::string GetTypeName(unsigned char TypeID) {
+ switch (TypeID) {
+ case MVT::Other: return "Other";
+ case MVT::iAny: return "iAny";
+ case MVT::fAny: return "fAny";
+ case MVT::vAny: return "vAny";
+ case EEVT::isUnknown: return "isUnknown";
+ case MVT::iPTR: return "iPTR";
+ case MVT::iPTRAny: return "iPTRAny";
+ default:
+ std::string VTName = llvm::getName((MVT::SimpleValueType)TypeID);
+ // Strip off EVT:: prefix if present.
+ if (VTName.substr(0,5) == "MVT::")
+ VTName = VTName.substr(5);
+ return VTName;
+ }
+}
+
void TreePatternNode::print(raw_ostream &OS) const {
if (isLeaf()) {
OS << *getLeafValue();
} else {
- OS << "(" << getOperator()->getName();
+ OS << '(' << getOperator()->getName();
}
// FIXME: At some point we should handle printing all the value types for
// nodes that are multiply typed.
- switch (getExtTypeNum(0)) {
- case MVT::Other: OS << ":Other"; break;
- case MVT::iAny: OS << ":iAny"; break;
- case MVT::fAny : OS << ":fAny"; break;
- case MVT::vAny: OS << ":vAny"; break;
- case EEVT::isUnknown: ; /*OS << ":?";*/ break;
- case MVT::iPTR: OS << ":iPTR"; break;
- case MVT::iPTRAny: OS << ":iPTRAny"; break;
- default: {
- std::string VTName = llvm::getName(getTypeNum(0));
- // Strip off EVT:: prefix if present.
- if (VTName.substr(0,5) == "MVT::")
- VTName = VTName.substr(5);
- OS << ":" << VTName;
- break;
- }
- }
+ if (getExtTypeNum(0) != EEVT::isUnknown)
+ OS << ':' << GetTypeName(getExtTypeNum(0));
if (!isLeaf()) {
if (getNumChildren() != 0) {
@@ -674,6 +701,15 @@ TreePatternNode *TreePatternNode::clone() const {
return New;
}
+/// RemoveAllTypes - Recursively strip all the types of this tree.
+void TreePatternNode::RemoveAllTypes() {
+ removeTypes();
+ if (isLeaf()) return;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ getChild(i)->RemoveAllTypes();
+}
+
+
/// SubstituteFormalArguments - Replace the formal arguments in this tree
/// with actual values specified by ArgMap.
void TreePatternNode::
@@ -768,7 +804,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
/// references from the register file information, for example.
///
static std::vector<unsigned char> getImplicitType(Record *R, bool NotRegisters,
- TreePattern &TP) {
+ TreePattern &TP) {
// Some common return values
std::vector<unsigned char> Unknown(1, EEVT::isUnknown);
std::vector<unsigned char> Other(1, MVT::Other);
@@ -825,6 +861,48 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const {
return &CDP.getIntrinsicInfo(IID);
}
+/// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
+/// return the ComplexPattern information, otherwise return null.
+const ComplexPattern *
+TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const {
+ if (!isLeaf()) return 0;
+
+ DefInit *DI = dynamic_cast<DefInit*>(getLeafValue());
+ if (DI && DI->getDef()->isSubClassOf("ComplexPattern"))
+ return &CGP.getComplexPattern(DI->getDef());
+ return 0;
+}
+
+/// NodeHasProperty - Return true if this node has the specified property.
+bool TreePatternNode::NodeHasProperty(SDNP Property,
+ const CodeGenDAGPatterns &CGP) const {
+ if (isLeaf()) {
+ if (const ComplexPattern *CP = getComplexPatternInfo(CGP))
+ return CP->hasProperty(Property);
+ return false;
+ }
+
+ Record *Operator = getOperator();
+ if (!Operator->isSubClassOf("SDNode")) return false;
+
+ return CGP.getSDNodeInfo(Operator).hasProperty(Property);
+}
+
+
+
+
+/// TreeHasProperty - Return true if any node in this tree has the specified
+/// property.
+bool TreePatternNode::TreeHasProperty(SDNP Property,
+ const CodeGenDAGPatterns &CGP) const {
+ if (NodeHasProperty(Property, CGP))
+ return true;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (getChild(i)->TreeHasProperty(Property, CGP))
+ return true;
+ return false;
+}
+
/// isCommutativeIntrinsic - Return true if the node corresponds to a
/// commutative intrinsic.
bool
@@ -845,7 +923,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) {
// If it's a regclass or something else known, include the type.
return UpdateNodeType(getImplicitType(DI->getDef(), NotRegisters, TP),TP);
- } else if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
+ }
+
+ if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
// Int inits are always integers. :)
bool MadeChange = UpdateNodeType(MVT::iAny, TP);
@@ -903,19 +983,25 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
}
return MadeChange;
- } else if (getOperator()->getName() == "implicit" ||
- getOperator()->getName() == "parallel") {
+ }
+
+ if (getOperator()->getName() == "implicit" ||
+ getOperator()->getName() == "parallel") {
bool MadeChange = false;
for (unsigned i = 0; i < getNumChildren(); ++i)
MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
return MadeChange;
- } else if (getOperator()->getName() == "COPY_TO_REGCLASS") {
+ }
+
+ if (getOperator()->getName() == "COPY_TO_REGCLASS") {
bool MadeChange = false;
MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
return MadeChange;
- } else if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
+ }
+
+ if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
bool MadeChange = false;
// Apply the result type to the node.
@@ -939,7 +1025,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
}
return MadeChange;
- } else if (getOperator()->isSubClassOf("SDNode")) {
+ }
+
+ if (getOperator()->isSubClassOf("SDNode")) {
const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());
bool MadeChange = NI.ApplyTypeConstraints(this, TP);
@@ -951,7 +1039,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
return MadeChange;
- } else if (getOperator()->isSubClassOf("Instruction")) {
+ }
+
+ if (getOperator()->isSubClassOf("Instruction")) {
const DAGInstruction &Inst = CDP.getInstruction(getOperator());
bool MadeChange = false;
unsigned NumResults = Inst.getNumResults();
@@ -1027,24 +1117,24 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
"' was provided too many operands!");
return MadeChange;
- } else {
- assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
-
- // Node transforms always take one operand.
- if (getNumChildren() != 1)
- TP.error("Node transform '" + getOperator()->getName() +
- "' requires one operand!");
-
- // If either the output or input of the xform does not have exact
- // type info. We assume they must be the same. Otherwise, it is perfectly
- // legal to transform from one type to a completely different type.
- if (!hasTypeSet() || !getChild(0)->hasTypeSet()) {
- bool MadeChange = UpdateNodeType(getChild(0)->getExtTypes(), TP);
- MadeChange |= getChild(0)->UpdateNodeType(getExtTypes(), TP);
- return MadeChange;
- }
- return false;
}
+
+ assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
+
+ // Node transforms always take one operand.
+ if (getNumChildren() != 1)
+ TP.error("Node transform '" + getOperator()->getName() +
+ "' requires one operand!");
+
+ // If either the output or input of the xform does not have exact
+ // type info. We assume they must be the same. Otherwise, it is perfectly
+ // legal to transform from one type to a completely different type.
+ if (!hasTypeSet() || !getChild(0)->hasTypeSet()) {
+ bool MadeChange = UpdateNodeType(getChild(0)->getExtTypes(), TP);
+ MadeChange |= getChild(0)->UpdateNodeType(getExtTypes(), TP);
+ return MadeChange;
+ }
+ return false;
}
/// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the
@@ -1317,7 +1407,6 @@ void TreePattern::dump() const { print(errs()); }
// CodeGenDAGPatterns implementation
//
-// FIXME: REMOVE OSTREAM ARGUMENT
CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) {
Intrinsics = LoadIntrinsics(Records, false);
TgtIntrinsics = LoadIntrinsics(Records, true);
@@ -1516,10 +1605,10 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
if (TPN->ContainsUnresolvedType()) {
if (iter == 0)
throw "Value #" + utostr(i) + " of PredicateOperand '" +
- DefaultOps[iter][i]->getName() + "' doesn't have a concrete type!";
+ DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!";
else
throw "Value #" + utostr(i) + " of OptionalDefOperand '" +
- DefaultOps[iter][i]->getName() + "' doesn't have a concrete type!";
+ DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!";
}
DefaultOpInfo.DefaultOps.push_back(TPN);
}
@@ -1563,21 +1652,21 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
TreePatternNode *&Slot = InstInputs[Pat->getName()];
if (!Slot) {
Slot = Pat;
+ return true;
+ }
+ Record *SlotRec;
+ if (Slot->isLeaf()) {
+ SlotRec = dynamic_cast<DefInit*>(Slot->getLeafValue())->getDef();
} else {
- Record *SlotRec;
- if (Slot->isLeaf()) {
- SlotRec = dynamic_cast<DefInit*>(Slot->getLeafValue())->getDef();
- } else {
- assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
- SlotRec = Slot->getOperator();
- }
-
- // Ensure that the inputs agree if we've already seen this input.
- if (Rec != SlotRec)
- I->error("All $" + Pat->getName() + " inputs must agree with each other");
- if (Slot->getExtTypes() != Pat->getExtTypes())
- I->error("All $" + Pat->getName() + " inputs must agree with each other");
+ assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
+ SlotRec = Slot->getOperator();
}
+
+ // Ensure that the inputs agree if we've already seen this input.
+ if (Rec != SlotRec)
+ I->error("All $" + Pat->getName() + " inputs must agree with each other");
+ if (Slot->getExtTypes() != Pat->getExtTypes())
+ I->error("All $" + Pat->getName() + " inputs must agree with each other");
return true;
}
@@ -1595,7 +1684,9 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
if (!isUse && Pat->getTransformFn())
I->error("Cannot specify a transform function for a non-input value!");
return;
- } else if (Pat->getOperator()->getName() == "implicit") {
+ }
+
+ if (Pat->getOperator()->getName() == "implicit") {
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
TreePatternNode *Dest = Pat->getChild(i);
if (!Dest->isLeaf())
@@ -1607,7 +1698,9 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
InstImpResults.push_back(Val->getDef());
}
return;
- } else if (Pat->getOperator()->getName() != "set") {
+ }
+
+ if (Pat->getOperator()->getName() != "set") {
// If this is not a set, verify that the children nodes are not void typed,
// and recurse.
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
@@ -1624,7 +1717,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
if (!isUse && Pat->getTransformFn())
I->error("Cannot specify a transform function for a non-input value!");
return;
- }
+ }
// Otherwise, this is a set, validate and collect instruction results.
if (Pat->getNumChildren() == 0)
@@ -2010,20 +2103,100 @@ void CodeGenDAGPatterns::ParseInstructions() {
SrcPattern = Pattern;
}
- std::string Reason;
- if (!SrcPattern->canPatternMatch(Reason, *this))
- I->error("Instruction can never match: " + Reason);
-
Record *Instr = II->first;
- TreePatternNode *DstPattern = TheInst.getResultPattern();
- PatternsToMatch.
- push_back(PatternToMatch(Instr->getValueAsListInit("Predicates"),
- SrcPattern, DstPattern, TheInst.getImpResults(),
- Instr->getValueAsInt("AddedComplexity")));
+ AddPatternToMatch(I,
+ PatternToMatch(Instr->getValueAsListInit("Predicates"),
+ SrcPattern,
+ TheInst.getResultPattern(),
+ TheInst.getImpResults(),
+ Instr->getValueAsInt("AddedComplexity"),
+ Instr->getID()));
}
}
+typedef std::pair<const TreePatternNode*, unsigned> NameRecord;
+
+static void FindNames(const TreePatternNode *P,
+ std::map<std::string, NameRecord> &Names,
+ const TreePattern *PatternTop) {
+ if (!P->getName().empty()) {
+ NameRecord &Rec = Names[P->getName()];
+ // If this is the first instance of the name, remember the node.
+ if (Rec.second++ == 0)
+ Rec.first = P;
+ else if (Rec.first->getExtTypes() != P->getExtTypes())
+ PatternTop->error("repetition of value: $" + P->getName() +
+ " where different uses have different types!");
+ }
+
+ if (!P->isLeaf()) {
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
+ FindNames(P->getChild(i), Names, PatternTop);
+ }
+}
+
+void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern,
+ const PatternToMatch &PTM) {
+ // Do some sanity checking on the pattern we're about to match.
+ std::string Reason;
+ if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this))
+ Pattern->error("Pattern can never match: " + Reason);
+
+ // If the source pattern's root is a complex pattern, that complex pattern
+ // must specify the nodes it can potentially match.
+ if (const ComplexPattern *CP =
+ PTM.getSrcPattern()->getComplexPatternInfo(*this))
+ if (CP->getRootNodes().empty())
+ Pattern->error("ComplexPattern at root must specify list of opcodes it"
+ " could match");
+
+
+ // Find all of the named values in the input and output, ensure they have the
+ // same type.
+ std::map<std::string, NameRecord> SrcNames, DstNames;
+ FindNames(PTM.getSrcPattern(), SrcNames, Pattern);
+ FindNames(PTM.getDstPattern(), DstNames, Pattern);
+
+ // Scan all of the named values in the destination pattern, rejecting them if
+ // they don't exist in the input pattern.
+ for (std::map<std::string, NameRecord>::iterator
+ I = DstNames.begin(), E = DstNames.end(); I != E; ++I) {
+ if (SrcNames[I->first].first == 0)
+ Pattern->error("Pattern has input without matching name in output: $" +
+ I->first);
+
+#if 0
+ const std::vector<unsigned char> &SrcTypeVec =
+ SrcNames[I->first].first->getExtTypes();
+ const std::vector<unsigned char> &DstTypeVec =
+ I->second.first->getExtTypes();
+ if (SrcTypeVec == DstTypeVec) continue;
+
+ std::string SrcType, DstType;
+ for (unsigned i = 0, e = SrcTypeVec.size(); i != e; ++i)
+ SrcType += ":" + GetTypeName(SrcTypeVec[i]);
+ for (unsigned i = 0, e = DstTypeVec.size(); i != e; ++i)
+ DstType += ":" + GetTypeName(DstTypeVec[i]);
+
+ Pattern->error("Variable $" + I->first +
+ " has different types in source (" + SrcType +
+ ") and dest (" + DstType + ") pattern!");
+#endif
+ }
+
+ // Scan all of the named values in the source pattern, rejecting them if the
+ // name isn't used in the dest, and isn't used to tie two values together.
+ for (std::map<std::string, NameRecord>::iterator
+ I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I)
+ if (DstNames[I->first].first == 0 && SrcNames[I->first].second == 1)
+ Pattern->error("Pattern has dead named input: $" + I->first);
+
+ PatternsToMatch.push_back(PTM);
+}
+
+
+
void CodeGenDAGPatterns::InferInstructionFlags() {
std::map<std::string, CodeGenInstruction> &InstrDescs =
Target.getInstructions();
@@ -2151,15 +2324,13 @@ void CodeGenDAGPatterns::ParsePatterns() {
TreePattern Temp(Result->getRecord(), DstPattern, false, *this);
Temp.InferAllTypes();
- std::string Reason;
- if (!Pattern->getTree(0)->canPatternMatch(Reason, *this))
- Pattern->error("Pattern can never match: " + Reason);
- PatternsToMatch.
- push_back(PatternToMatch(Patterns[i]->getValueAsListInit("Predicates"),
- Pattern->getTree(0),
- Temp.getOnlyTree(), InstImpResults,
- Patterns[i]->getValueAsInt("AddedComplexity")));
+ AddPatternToMatch(Pattern,
+ PatternToMatch(Patterns[i]->getValueAsListInit("Predicates"),
+ Pattern->getTree(0),
+ Temp.getOnlyTree(), InstImpResults,
+ Patterns[i]->getValueAsInt("AddedComplexity"),
+ Patterns[i]->getID()));
}
}
@@ -2181,13 +2352,13 @@ static void CombineChildVariants(TreePatternNode *Orig,
bool NotDone;
do {
#ifndef NDEBUG
- if (DebugFlag && !Idxs.empty()) {
- errs() << Orig->getOperator()->getName() << ": Idxs = [ ";
- for (unsigned i = 0; i < Idxs.size(); ++i) {
- errs() << Idxs[i] << " ";
- }
- errs() << "]\n";
- }
+ DEBUG(if (!Idxs.empty()) {
+ errs() << Orig->getOperator()->getName() << ": Idxs = [ ";
+ for (unsigned i = 0; i < Idxs.size(); ++i) {
+ errs() << Idxs[i] << " ";
+ }
+ errs() << "]\n";
+ });
#endif
// Create the variant and add it to the output list.
std::vector<TreePatternNode*> NewChildren;
@@ -2453,7 +2624,8 @@ void CodeGenDAGPatterns::GenerateVariants() {
push_back(PatternToMatch(PatternsToMatch[i].getPredicates(),
Variant, PatternsToMatch[i].getDstPattern(),
PatternsToMatch[i].getDstRegs(),
- PatternsToMatch[i].getAddedComplexity()));
+ PatternsToMatch[i].getAddedComplexity(),
+ Record::getNewUID()));
}
DEBUG(errs() << "\n");
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index c51232a..37d633e 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -125,6 +125,11 @@ public:
return TypeConstraints;
}
+ /// getKnownType - If the type constraints on this node imply a fixed type
+ /// (e.g. all stores return void, etc), then return it as an
+ /// MVT::SimpleValueType. Otherwise, return EEVT::isUnknown.
+ unsigned getKnownType() const;
+
/// hasProperty - Return true if this node has the specified property.
///
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
@@ -216,8 +221,15 @@ public:
void setChild(unsigned i, TreePatternNode *N) {
Children[i] = N;
}
+
+ /// hasChild - Return true if N is any of our children.
+ bool hasChild(const TreePatternNode *N) const {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ if (Children[i] == N) return true;
+ return false;
+ }
- const std::vector<std::string> &getPredicateFns() const { return PredicateFns; }
+ const std::vector<std::string> &getPredicateFns() const {return PredicateFns;}
void clearPredicateFns() { PredicateFns.clear(); }
void setPredicateFns(const std::vector<std::string> &Fns) {
assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
@@ -237,6 +249,18 @@ public:
/// CodeGenIntrinsic information for it, otherwise return a null pointer.
const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const;
+ /// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
+ /// return the ComplexPattern information, otherwise return null.
+ const ComplexPattern *
+ getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const;
+
+ /// NodeHasProperty - Return true if this node has the specified property.
+ bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
+
+ /// TreeHasProperty - Return true if any node in this tree has the specified
+ /// property.
+ bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
+
/// isCommutativeIntrinsic - Return true if the node is an intrinsic which is
/// marked isCommutative.
bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const;
@@ -249,6 +273,9 @@ public: // Higher level manipulation routines.
/// clone - Return a new copy of this tree.
///
TreePatternNode *clone() const;
+
+ /// RemoveAllTypes - Recursively strip all the types of this tree.
+ void RemoveAllTypes();
/// isIsomorphicTo - Return true if this node is recursively isomorphic to
/// the specified node. For this comparison, all of the state of the node
@@ -298,6 +325,11 @@ public: // Higher level manipulation routines.
bool canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP);
};
+inline raw_ostream &operator<<(raw_ostream &OS, const TreePatternNode &TPN) {
+ TPN.print(OS);
+ return OS;
+}
+
/// TreePattern - Represent a pattern, used for instructions, pattern
/// fragments, etc.
@@ -439,19 +471,21 @@ public:
/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
/// processed to produce isel.
-struct PatternToMatch {
+class PatternToMatch {
+public:
PatternToMatch(ListInit *preds,
TreePatternNode *src, TreePatternNode *dst,
const std::vector<Record*> &dstregs,
- unsigned complexity):
- Predicates(preds), SrcPattern(src), DstPattern(dst), Dstregs(dstregs),
- AddedComplexity(complexity) {}
+ unsigned complexity, unsigned uid)
+ : Predicates(preds), SrcPattern(src), DstPattern(dst),
+ Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {}
ListInit *Predicates; // Top level predicate conditions to match.
TreePatternNode *SrcPattern; // Source pattern to match.
TreePatternNode *DstPattern; // Resulting pattern.
std::vector<Record*> Dstregs; // Physical register defs being matched.
unsigned AddedComplexity; // Add to matching pattern complexity.
+ unsigned ID; // Unique ID for the record.
ListInit *getPredicates() const { return Predicates; }
TreePatternNode *getSrcPattern() const { return SrcPattern; }
@@ -547,7 +581,7 @@ public:
abort();
}
- const DAGDefaultOperand &getDefaultOperand(Record *R) {
+ const DAGDefaultOperand &getDefaultOperand(Record *R) const {
assert(DefaultOperands.count(R) &&"Isn't an analyzed default operand!");
return DefaultOperands.find(R)->second;
}
@@ -597,6 +631,7 @@ private:
void InferInstructionFlags();
void GenerateVariants();
+ void AddPatternToMatch(const TreePattern *Pattern, const PatternToMatch &PTM);
void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
std::map<std::string,
TreePatternNode*> &InstInputs,
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index d31502b1..f5b52ec 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -117,7 +117,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
isNotDuplicable = R->getValueAsBit("isNotDuplicable");
hasSideEffects = R->getValueAsBit("hasSideEffects");
- mayHaveSideEffects = R->getValueAsBit("mayHaveSideEffects");
neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
@@ -125,7 +124,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
hasOptionalDef = false;
isVariadic = false;
- if (mayHaveSideEffects + neverHasSideEffects + hasSideEffects > 1)
+ if (neverHasSideEffects + hasSideEffects > 1)
throw R->getName() + ": multiple conflicting side-effect flags set!";
DagInit *DI;
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index e81e7f4..aae2cac 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -41,6 +41,7 @@ namespace llvm {
static ConstraintInfo getEarlyClobber() {
ConstraintInfo I;
I.Kind = EarlyClobber;
+ I.OtherTiedOperand = 0;
return I;
}
@@ -132,7 +133,6 @@ namespace llvm {
bool isNotDuplicable;
bool hasOptionalDef;
bool hasSideEffects;
- bool mayHaveSideEffects;
bool neverHasSideEffects;
bool isAsCheapAsAMove;
bool hasExtraSrcRegAllocReq;
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index c97582b..e0fa7c8 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -12,63 +12,15 @@
//===----------------------------------------------------------------------===//
#include "DAGISelEmitter.h"
+#include "DAGISelMatcher.h"
#include "Record.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/Debug.h"
-#include <algorithm>
-#include <deque>
-#include <iostream>
using namespace llvm;
-static cl::opt<bool>
-GenDebug("gen-debug", cl::desc("Generate debug code"), cl::init(false));
-
//===----------------------------------------------------------------------===//
// DAGISelEmitter Helper methods
//
-/// getNodeName - The top level Select_* functions have an "SDNode* N"
-/// argument. When expanding the pattern-matching code, the intermediate
-/// variables have type SDValue. This function provides a uniform way to
-/// reference the underlying "SDNode *" for both cases.
-static std::string getNodeName(const std::string &S) {
- if (S == "N") return S;
- return S + ".getNode()";
-}
-
-/// getNodeValue - Similar to getNodeName, except it provides a uniform
-/// way to access the SDValue for both cases.
-static std::string getValueName(const std::string &S) {
- if (S == "N") return "SDValue(N, 0)";
- return S;
-}
-
-/// NodeIsComplexPattern - return true if N is a leaf node and a subclass of
-/// ComplexPattern.
-static bool NodeIsComplexPattern(TreePatternNode *N) {
- return (N->isLeaf() &&
- dynamic_cast<DefInit*>(N->getLeafValue()) &&
- static_cast<DefInit*>(N->getLeafValue())->getDef()->
- isSubClassOf("ComplexPattern"));
-}
-
-/// NodeGetComplexPattern - return the pointer to the ComplexPattern if N
-/// is a leaf node and a subclass of ComplexPattern, else it returns NULL.
-static const ComplexPattern *NodeGetComplexPattern(TreePatternNode *N,
- CodeGenDAGPatterns &CGP) {
- if (N->isLeaf() &&
- dynamic_cast<DefInit*>(N->getLeafValue()) &&
- static_cast<DefInit*>(N->getLeafValue())->getDef()->
- isSubClassOf("ComplexPattern")) {
- return &CGP.getComplexPattern(static_cast<DefInit*>(N->getLeafValue())
- ->getDef());
- }
- return NULL;
-}
-
/// getPatternSize - Return the 'size' of this pattern. We want to match large
/// patterns before small ones. This is used to determine the size of a
/// pattern.
@@ -91,7 +43,7 @@ static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
// Later we can allow complexity / cost for each pattern to be (optionally)
// specified. To get best possible pattern match we'll need to dynamically
// calculate the complexity of all patterns a dag can potentially map to.
- const ComplexPattern *AM = NodeGetComplexPattern(P, CGP);
+ const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
if (AM)
Size += AM->getNumOperands() * 3;
@@ -108,7 +60,7 @@ static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
else if (Child->isLeaf()) {
if (dynamic_cast<IntInit*>(Child->getLeafValue()))
Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
- else if (NodeIsComplexPattern(Child))
+ else if (Child->getComplexPatternInfo(CGP))
Size += getPatternSize(Child, CGP);
else if (!Child->getPredicateFns().empty())
++Size;
@@ -154,164 +106,6 @@ static unsigned getResultPatternSize(TreePatternNode *P,
return Cost;
}
-// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
-// In particular, we want to match maximal patterns first and lowest cost within
-// a particular complexity first.
-struct PatternSortingPredicate {
- PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
- CodeGenDAGPatterns &CGP;
-
- typedef std::pair<unsigned, std::string> CodeLine;
- typedef std::vector<CodeLine> CodeList;
- typedef std::vector<std::pair<const PatternToMatch*, CodeList> > PatternList;
-
- bool operator()(const std::pair<const PatternToMatch*, CodeList> &LHSPair,
- const std::pair<const PatternToMatch*, CodeList> &RHSPair) {
- const PatternToMatch *LHS = LHSPair.first;
- const PatternToMatch *RHS = RHSPair.first;
-
- unsigned LHSSize = getPatternSize(LHS->getSrcPattern(), CGP);
- unsigned RHSSize = getPatternSize(RHS->getSrcPattern(), CGP);
- LHSSize += LHS->getAddedComplexity();
- RHSSize += RHS->getAddedComplexity();
- if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
- if (LHSSize < RHSSize) return false;
-
- // If the patterns have equal complexity, compare generated instruction cost
- unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
- unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
- if (LHSCost < RHSCost) return true;
- if (LHSCost > RHSCost) return false;
-
- return getResultPatternSize(LHS->getDstPattern(), CGP) <
- getResultPatternSize(RHS->getDstPattern(), CGP);
- }
-};
-
-/// getRegisterValueType - Look up and return the ValueType of the specified
-/// register. If the register is a member of multiple register classes which
-/// have different associated types, return MVT::Other.
-static MVT::SimpleValueType getRegisterValueType(Record *R, const CodeGenTarget &T) {
- bool FoundRC = false;
- MVT::SimpleValueType VT = MVT::Other;
- const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
- std::vector<CodeGenRegisterClass>::const_iterator RC;
- std::vector<Record*>::const_iterator Element;
-
- for (RC = RCs.begin() ; RC != RCs.end() ; RC++) {
- Element = find((*RC).Elements.begin(), (*RC).Elements.end(), R);
- if (Element != (*RC).Elements.end()) {
- if (!FoundRC) {
- FoundRC = true;
- VT = (*RC).getValueTypeNum(0);
- } else {
- // In multiple RC's
- if (VT != (*RC).getValueTypeNum(0)) {
- // Types of the RC's do not agree. Return MVT::Other. The
- // target is responsible for handling this.
- return MVT::Other;
- }
- }
- }
- }
- return VT;
-}
-
-
-/// RemoveAllTypes - A quick recursive walk over a pattern which removes all
-/// type information from it.
-static void RemoveAllTypes(TreePatternNode *N) {
- N->removeTypes();
- if (!N->isLeaf())
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
- RemoveAllTypes(N->getChild(i));
-}
-
-/// NodeHasProperty - return true if TreePatternNode has the specified
-/// property.
-static bool NodeHasProperty(TreePatternNode *N, SDNP Property,
- CodeGenDAGPatterns &CGP) {
- if (N->isLeaf()) {
- const ComplexPattern *CP = NodeGetComplexPattern(N, CGP);
- if (CP)
- return CP->hasProperty(Property);
- return false;
- }
- Record *Operator = N->getOperator();
- if (!Operator->isSubClassOf("SDNode")) return false;
-
- return CGP.getSDNodeInfo(Operator).hasProperty(Property);
-}
-
-static bool PatternHasProperty(TreePatternNode *N, SDNP Property,
- CodeGenDAGPatterns &CGP) {
- if (NodeHasProperty(N, Property, CGP))
- return true;
-
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
- TreePatternNode *Child = N->getChild(i);
- if (PatternHasProperty(Child, Property, CGP))
- return true;
- }
-
- return false;
-}
-
-static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
- return CGP.getSDNodeInfo(Op).getEnumName();
-}
-
-static
-bool DisablePatternForFastISel(TreePatternNode *N, CodeGenDAGPatterns &CGP) {
- bool isStore = !N->isLeaf() &&
- getOpcodeName(N->getOperator(), CGP) == "ISD::STORE";
- if (!isStore && NodeHasProperty(N, SDNPHasChain, CGP))
- return false;
-
- bool HasChain = false;
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
- TreePatternNode *Child = N->getChild(i);
- if (PatternHasProperty(Child, SDNPHasChain, CGP)) {
- HasChain = true;
- break;
- }
- }
- return HasChain;
-}
-
-//===----------------------------------------------------------------------===//
-// Node Transformation emitter implementation.
-//
-void DAGISelEmitter::EmitNodeTransforms(raw_ostream &OS) {
- // Walk the pattern fragments, adding them to a map, which sorts them by
- // name.
- typedef std::map<std::string, CodeGenDAGPatterns::NodeXForm> NXsByNameTy;
- NXsByNameTy NXsByName;
-
- for (CodeGenDAGPatterns::nx_iterator I = CGP.nx_begin(), E = CGP.nx_end();
- I != E; ++I)
- NXsByName.insert(std::make_pair(I->first->getName(), I->second));
-
- OS << "\n// Node transformations.\n";
-
- for (NXsByNameTy::iterator I = NXsByName.begin(), E = NXsByName.end();
- I != E; ++I) {
- Record *SDNode = I->second.first;
- std::string Code = I->second.second;
-
- if (Code.empty()) continue; // Empty code? Skip it.
-
- std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName();
- const char *C2 = ClassName == "SDNode" ? "N" : "inN";
-
- OS << "inline SDValue Transform_" << I->first << "(SDNode *" << C2
- << ") {\n";
- if (ClassName != "SDNode")
- OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
- OS << Code << "\n}\n";
- }
-}
-
//===----------------------------------------------------------------------===//
// Predicate emitter implementation.
//
@@ -340,14 +134,14 @@ void DAGISelEmitter::EmitPredicateFunctions(raw_ostream &OS) {
if (P->getOnlyTree()->isLeaf())
OS << "inline bool Predicate_" << PatFragRecord->getName()
- << "(SDNode *N) {\n";
+ << "(SDNode *N) const {\n";
else {
std::string ClassName =
CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
const char *C2 = ClassName == "SDNode" ? "N" : "inN";
OS << "inline bool Predicate_" << PatFragRecord->getName()
- << "(SDNode *" << C2 << ") {\n";
+ << "(SDNode *" << C2 << ") const {\n";
if (ClassName != "SDNode")
OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
}
@@ -357,1685 +151,41 @@ void DAGISelEmitter::EmitPredicateFunctions(raw_ostream &OS) {
OS << "\n\n";
}
-
-//===----------------------------------------------------------------------===//
-// PatternCodeEmitter implementation.
-//
-class PatternCodeEmitter {
-private:
+namespace {
+// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
+// In particular, we want to match maximal patterns first and lowest cost within
+// a particular complexity first.
+struct PatternSortingPredicate {
+ PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
CodeGenDAGPatterns &CGP;
-
- // Predicates.
- std::string PredicateCheck;
- // Pattern cost.
- unsigned Cost;
- // Instruction selector pattern.
- TreePatternNode *Pattern;
- // Matched instruction.
- TreePatternNode *Instruction;
- // Node to name mapping
- std::map<std::string, std::string> VariableMap;
- // Node to operator mapping
- std::map<std::string, Record*> OperatorMap;
- // Name of the folded node which produces a flag.
- std::pair<std::string, unsigned> FoldedFlag;
- // Names of all the folded nodes which produce chains.
- std::vector<std::pair<std::string, unsigned> > FoldedChains;
- // Original input chain(s).
- std::vector<std::pair<std::string, std::string> > OrigChains;
- std::set<std::string> Duplicates;
-
- /// LSI - Load/Store information.
- /// Save loads/stores matched by a pattern, and generate a MemOperandSDNode
- /// for each memory access. This facilitates the use of AliasAnalysis in
- /// the backend.
- std::vector<std::string> LSI;
-
- /// GeneratedCode - This is the buffer that we emit code to. The first int
- /// indicates whether this is an exit predicate (something that should be
- /// tested, and if true, the match fails) [when 1], or normal code to emit
- /// [when 0], or initialization code to emit [when 2].
- std::vector<std::pair<unsigned, std::string> > &GeneratedCode;
- /// GeneratedDecl - This is the set of all SDValue declarations needed for
- /// the set of patterns for each top-level opcode.
- std::set<std::string> &GeneratedDecl;
- /// TargetOpcodes - The target specific opcodes used by the resulting
- /// instructions.
- std::vector<std::string> &TargetOpcodes;
- std::vector<std::string> &TargetVTs;
- /// OutputIsVariadic - Records whether the instruction output pattern uses
- /// variable_ops. This requires that the Emit function be passed an
- /// additional argument to indicate where the input varargs operands
- /// begin.
- bool &OutputIsVariadic;
- /// NumInputRootOps - Records the number of operands the root node of the
- /// input pattern has. This information is used in the generated code to
- /// pass to Emit functions when variable_ops processing is needed.
- unsigned &NumInputRootOps;
-
- std::string ChainName;
- unsigned TmpNo;
- unsigned OpcNo;
- unsigned VTNo;
-
- void emitCheck(const std::string &S) {
- if (!S.empty())
- GeneratedCode.push_back(std::make_pair(1, S));
- }
- void emitCode(const std::string &S) {
- if (!S.empty())
- GeneratedCode.push_back(std::make_pair(0, S));
- }
- void emitInit(const std::string &S) {
- if (!S.empty())
- GeneratedCode.push_back(std::make_pair(2, S));
- }
- void emitDecl(const std::string &S) {
- assert(!S.empty() && "Invalid declaration");
- GeneratedDecl.insert(S);
- }
- void emitOpcode(const std::string &Opc) {
- TargetOpcodes.push_back(Opc);
- OpcNo++;
- }
- void emitVT(const std::string &VT) {
- TargetVTs.push_back(VT);
- VTNo++;
- }
-public:
- PatternCodeEmitter(CodeGenDAGPatterns &cgp, std::string predcheck,
- TreePatternNode *pattern, TreePatternNode *instr,
- std::vector<std::pair<unsigned, std::string> > &gc,
- std::set<std::string> &gd,
- std::vector<std::string> &to,
- std::vector<std::string> &tv,
- bool &oiv,
- unsigned &niro)
- : CGP(cgp), PredicateCheck(predcheck), Pattern(pattern), Instruction(instr),
- GeneratedCode(gc), GeneratedDecl(gd),
- TargetOpcodes(to), TargetVTs(tv),
- OutputIsVariadic(oiv), NumInputRootOps(niro),
- TmpNo(0), OpcNo(0), VTNo(0) {}
-
- /// EmitMatchCode - Emit a matcher for N, going to the label for PatternNo
- /// if the match fails. At this point, we already know that the opcode for N
- /// matches, and the SDNode for the result has the RootName specified name.
- void EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
- const std::string &RootName, const std::string &ChainSuffix,
- bool &FoundChain) {
-
- // Save loads/stores matched by a pattern.
- if (!N->isLeaf() && N->getName().empty()) {
- if (NodeHasProperty(N, SDNPMemOperand, CGP))
- LSI.push_back(getNodeName(RootName));
- }
-
- bool isRoot = (P == NULL);
- // Emit instruction predicates. Each predicate is just a string for now.
- if (isRoot) {
- // Record input varargs info.
- NumInputRootOps = N->getNumChildren();
-
- if (DisablePatternForFastISel(N, CGP))
- emitCheck("OptLevel != CodeGenOpt::None");
-
- emitCheck(PredicateCheck);
- }
-
- if (N->isLeaf()) {
- if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
- emitCheck("cast<ConstantSDNode>(" + getNodeName(RootName) +
- ")->getSExtValue() == INT64_C(" +
- itostr(II->getValue()) + ")");
- return;
- } else if (!NodeIsComplexPattern(N)) {
- assert(0 && "Cannot match this as a leaf value!");
- abort();
- }
- }
-
- // If this node has a name associated with it, capture it in VariableMap. If
- // we already saw this in the pattern, emit code to verify dagness.
- if (!N->getName().empty()) {
- std::string &VarMapEntry = VariableMap[N->getName()];
- if (VarMapEntry.empty()) {
- VarMapEntry = RootName;
- } else {
- // If we get here, this is a second reference to a specific name. Since
- // we already have checked that the first reference is valid, we don't
- // have to recursively match it, just check that it's the same as the
- // previously named thing.
- emitCheck(VarMapEntry + " == " + RootName);
- return;
- }
-
- if (!N->isLeaf())
- OperatorMap[N->getName()] = N->getOperator();
- }
-
-
- // Emit code to load the child nodes and match their contents recursively.
- unsigned OpNo = 0;
- bool NodeHasChain = NodeHasProperty (N, SDNPHasChain, CGP);
- bool HasChain = PatternHasProperty(N, SDNPHasChain, CGP);
- bool EmittedUseCheck = false;
- if (HasChain) {
- if (NodeHasChain)
- OpNo = 1;
- if (!isRoot) {
- // Multiple uses of actual result?
- emitCheck(getValueName(RootName) + ".hasOneUse()");
- EmittedUseCheck = true;
- if (NodeHasChain) {
- // If the immediate use can somehow reach this node through another
- // path, then can't fold it either or it will create a cycle.
- // e.g. In the following diagram, XX can reach ld through YY. If
- // ld is folded into XX, then YY is both a predecessor and a successor
- // of XX.
- //
- // [ld]
- // ^ ^
- // | |
- // / \---
- // / [YY]
- // | ^
- // [XX]-------|
- bool NeedCheck = P != Pattern;
- if (!NeedCheck) {
- const SDNodeInfo &PInfo = CGP.getSDNodeInfo(P->getOperator());
- NeedCheck =
- P->getOperator() == CGP.get_intrinsic_void_sdnode() ||
- P->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
- P->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
- PInfo.getNumOperands() > 1 ||
- PInfo.hasProperty(SDNPHasChain) ||
- PInfo.hasProperty(SDNPInFlag) ||
- PInfo.hasProperty(SDNPOptInFlag);
- }
-
- if (NeedCheck) {
- std::string ParentName(RootName.begin(), RootName.end()-1);
- emitCheck("IsLegalAndProfitableToFold(" + getNodeName(RootName) +
- ", " + getNodeName(ParentName) + ", N)");
- }
- }
- }
-
- if (NodeHasChain) {
- if (FoundChain) {
- emitCheck("(" + ChainName + ".getNode() == " +
- getNodeName(RootName) + " || "
- "IsChainCompatible(" + ChainName + ".getNode(), " +
- getNodeName(RootName) + "))");
- OrigChains.push_back(std::make_pair(ChainName,
- getValueName(RootName)));
- } else
- FoundChain = true;
- ChainName = "Chain" + ChainSuffix;
- emitInit("SDValue " + ChainName + " = " + getNodeName(RootName) +
- "->getOperand(0);");
- }
- }
-
- // Don't fold any node which reads or writes a flag and has multiple uses.
- // FIXME: We really need to separate the concepts of flag and "glue". Those
- // real flag results, e.g. X86CMP output, can have multiple uses.
- // FIXME: If the optional incoming flag does not exist. Then it is ok to
- // fold it.
- if (!isRoot &&
- (PatternHasProperty(N, SDNPInFlag, CGP) ||
- PatternHasProperty(N, SDNPOptInFlag, CGP) ||
- PatternHasProperty(N, SDNPOutFlag, CGP))) {
- if (!EmittedUseCheck) {
- // Multiple uses of actual result?
- emitCheck(getValueName(RootName) + ".hasOneUse()");
- }
- }
-
- // If there are node predicates for this, emit the calls.
- for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
- emitCheck(N->getPredicateFns()[i] + "(" + getNodeName(RootName) + ")");
-
- // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
- // a constant without a predicate fn that has more that one bit set, handle
- // this as a special case. This is usually for targets that have special
- // handling of certain large constants (e.g. alpha with it's 8/16/32-bit
- // handling stuff). Using these instructions is often far more efficient
- // than materializing the constant. Unfortunately, both the instcombiner
- // and the dag combiner can often infer that bits are dead, and thus drop
- // them from the mask in the dag. For example, it might turn 'AND X, 255'
- // into 'AND X, 254' if it knows the low bit is set. Emit code that checks
- // to handle this.
- if (!N->isLeaf() &&
- (N->getOperator()->getName() == "and" ||
- N->getOperator()->getName() == "or") &&
- N->getChild(1)->isLeaf() &&
- N->getChild(1)->getPredicateFns().empty()) {
- if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
- if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
- emitInit("SDValue " + RootName + "0" + " = " +
- getNodeName(RootName) + "->getOperand(" + utostr(0) + ");");
- emitInit("SDValue " + RootName + "1" + " = " +
- getNodeName(RootName) + "->getOperand(" + utostr(1) + ");");
-
- unsigned NTmp = TmpNo++;
- emitCode("ConstantSDNode *Tmp" + utostr(NTmp) +
- " = dyn_cast<ConstantSDNode>(" +
- getNodeName(RootName + "1") + ");");
- emitCheck("Tmp" + utostr(NTmp));
- const char *MaskPredicate = N->getOperator()->getName() == "or"
- ? "CheckOrMask(" : "CheckAndMask(";
- emitCheck(MaskPredicate + getValueName(RootName + "0") +
- ", Tmp" + utostr(NTmp) +
- ", INT64_C(" + itostr(II->getValue()) + "))");
-
- EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0),
- ChainSuffix + utostr(0), FoundChain);
- return;
- }
- }
- }
-
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
- emitInit("SDValue " + getValueName(RootName + utostr(OpNo)) + " = " +
- getNodeName(RootName) + "->getOperand(" + utostr(OpNo) + ");");
-
- EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo),
- ChainSuffix + utostr(OpNo), FoundChain);
- }
-
- // Handle cases when root is a complex pattern.
- const ComplexPattern *CP;
- if (isRoot && N->isLeaf() && (CP = NodeGetComplexPattern(N, CGP))) {
- std::string Fn = CP->getSelectFunc();
- unsigned NumOps = CP->getNumOperands();
- for (unsigned i = 0; i < NumOps; ++i) {
- emitDecl("CPTmp" + RootName + "_" + utostr(i));
- emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
- }
- if (CP->hasProperty(SDNPHasChain)) {
- emitDecl("CPInChain");
- emitDecl("Chain" + ChainSuffix);
- emitCode("SDValue CPInChain;");
- emitCode("SDValue Chain" + ChainSuffix + ";");
- }
-
- std::string Code = Fn + "(" +
- getNodeName(RootName) + ", " +
- getValueName(RootName);
- for (unsigned i = 0; i < NumOps; i++)
- Code += ", CPTmp" + RootName + "_" + utostr(i);
- if (CP->hasProperty(SDNPHasChain)) {
- ChainName = "Chain" + ChainSuffix;
- Code += ", CPInChain, Chain" + ChainSuffix;
- }
- emitCheck(Code + ")");
- }
- }
-
- void EmitChildMatchCode(TreePatternNode *Child, TreePatternNode *Parent,
- const std::string &RootName,
- const std::string &ChainSuffix, bool &FoundChain) {
- if (!Child->isLeaf()) {
- // If it's not a leaf, recursively match.
- const SDNodeInfo &CInfo = CGP.getSDNodeInfo(Child->getOperator());
- emitCheck(getNodeName(RootName) + "->getOpcode() == " +
- CInfo.getEnumName());
- EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain);
- bool HasChain = false;
- if (NodeHasProperty(Child, SDNPHasChain, CGP)) {
- HasChain = true;
- FoldedChains.push_back(std::make_pair(getValueName(RootName),
- CInfo.getNumResults()));
- }
- if (NodeHasProperty(Child, SDNPOutFlag, CGP)) {
- assert(FoldedFlag.first == "" && FoldedFlag.second == 0 &&
- "Pattern folded multiple nodes which produce flags?");
- FoldedFlag = std::make_pair(getValueName(RootName),
- CInfo.getNumResults() + (unsigned)HasChain);
- }
- } else {
- // If this child has a name associated with it, capture it in VarMap. If
- // we already saw this in the pattern, emit code to verify dagness.
- if (!Child->getName().empty()) {
- std::string &VarMapEntry = VariableMap[Child->getName()];
- if (VarMapEntry.empty()) {
- VarMapEntry = getValueName(RootName);
- } else {
- // If we get here, this is a second reference to a specific name.
- // Since we already have checked that the first reference is valid,
- // we don't have to recursively match it, just check that it's the
- // same as the previously named thing.
- emitCheck(VarMapEntry + " == " + getValueName(RootName));
- Duplicates.insert(getValueName(RootName));
- return;
- }
- }
-
- // Handle leaves of various types.
- if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
- Record *LeafRec = DI->getDef();
- if (LeafRec->isSubClassOf("RegisterClass") ||
- LeafRec->isSubClassOf("PointerLikeRegClass")) {
- // Handle register references. Nothing to do here.
- } else if (LeafRec->isSubClassOf("Register")) {
- // Handle register references.
- } else if (LeafRec->isSubClassOf("ComplexPattern")) {
- // Handle complex pattern.
- const ComplexPattern *CP = NodeGetComplexPattern(Child, CGP);
- std::string Fn = CP->getSelectFunc();
- unsigned NumOps = CP->getNumOperands();
- for (unsigned i = 0; i < NumOps; ++i) {
- emitDecl("CPTmp" + RootName + "_" + utostr(i));
- emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
- }
- if (CP->hasProperty(SDNPHasChain)) {
- const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Parent->getOperator());
- FoldedChains.push_back(std::make_pair("CPInChain",
- PInfo.getNumResults()));
- ChainName = "Chain" + ChainSuffix;
- emitDecl("CPInChain");
- emitDecl(ChainName);
- emitCode("SDValue CPInChain;");
- emitCode("SDValue " + ChainName + ";");
- }
-
- std::string Code = Fn + "(N, ";
- if (CP->hasProperty(SDNPHasChain)) {
- std::string ParentName(RootName.begin(), RootName.end()-1);
- Code += getValueName(ParentName) + ", ";
- }
- Code += getValueName(RootName);
- for (unsigned i = 0; i < NumOps; i++)
- Code += ", CPTmp" + RootName + "_" + utostr(i);
- if (CP->hasProperty(SDNPHasChain))
- Code += ", CPInChain, Chain" + ChainSuffix;
- emitCheck(Code + ")");
- } else if (LeafRec->getName() == "srcvalue") {
- // Place holder for SRCVALUE nodes. Nothing to do here.
- } else if (LeafRec->isSubClassOf("ValueType")) {
- // Make sure this is the specified value type.
- emitCheck("cast<VTSDNode>(" + getNodeName(RootName) +
- ")->getVT() == MVT::" + LeafRec->getName());
- } else if (LeafRec->isSubClassOf("CondCode")) {
- // Make sure this is the specified cond code.
- emitCheck("cast<CondCodeSDNode>(" + getNodeName(RootName) +
- ")->get() == ISD::" + LeafRec->getName());
- } else {
-#ifndef NDEBUG
- Child->dump();
- errs() << " ";
-#endif
- assert(0 && "Unknown leaf type!");
- }
-
- // If there are node predicates for this, emit the calls.
- for (unsigned i = 0, e = Child->getPredicateFns().size(); i != e; ++i)
- emitCheck(Child->getPredicateFns()[i] + "(" + getNodeName(RootName) +
- ")");
- } else if (IntInit *II =
- dynamic_cast<IntInit*>(Child->getLeafValue())) {
- unsigned NTmp = TmpNo++;
- emitCode("ConstantSDNode *Tmp"+ utostr(NTmp) +
- " = dyn_cast<ConstantSDNode>("+
- getNodeName(RootName) + ");");
- emitCheck("Tmp" + utostr(NTmp));
- unsigned CTmp = TmpNo++;
- emitCode("int64_t CN"+ utostr(CTmp) +
- " = Tmp" + utostr(NTmp) + "->getSExtValue();");
- emitCheck("CN" + utostr(CTmp) + " == "
- "INT64_C(" +itostr(II->getValue()) + ")");
- } else {
-#ifndef NDEBUG
- Child->dump();
-#endif
- assert(0 && "Unknown leaf type!");
- }
- }
- }
-
- /// EmitResultCode - Emit the action for a pattern. Now that it has matched
- /// we actually have to build a DAG!
- std::vector<std::string>
- EmitResultCode(TreePatternNode *N, std::vector<Record*> DstRegs,
- bool InFlagDecled, bool ResNodeDecled,
- bool LikeLeaf = false, bool isRoot = false) {
- // List of arguments of getMachineNode() or SelectNodeTo().
- std::vector<std::string> NodeOps;
- // This is something selected from the pattern we matched.
- if (!N->getName().empty()) {
- const std::string &VarName = N->getName();
- std::string Val = VariableMap[VarName];
- bool ModifiedVal = false;
- if (Val.empty()) {
- errs() << "Variable '" << VarName << " referenced but not defined "
- << "and not caught earlier!\n";
- abort();
- }
- if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
- // Already selected this operand, just return the tmpval.
- NodeOps.push_back(getValueName(Val));
- return NodeOps;
- }
-
- const ComplexPattern *CP;
- unsigned ResNo = TmpNo++;
- if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
- assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
- std::string CastType;
- std::string TmpVar = "Tmp" + utostr(ResNo);
- switch (N->getTypeNum(0)) {
- default:
- errs() << "Cannot handle " << getEnumName(N->getTypeNum(0))
- << " type as an immediate constant. Aborting\n";
- abort();
- case MVT::i1: CastType = "bool"; break;
- case MVT::i8: CastType = "unsigned char"; break;
- case MVT::i16: CastType = "unsigned short"; break;
- case MVT::i32: CastType = "unsigned"; break;
- case MVT::i64: CastType = "uint64_t"; break;
- }
- emitCode("SDValue " + TmpVar +
- " = CurDAG->getTargetConstant(((" + CastType +
- ") cast<ConstantSDNode>(" + Val + ")->getZExtValue()), " +
- getEnumName(N->getTypeNum(0)) + ");");
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
- // value if used multiple times by this pattern result.
- Val = TmpVar;
- ModifiedVal = true;
- NodeOps.push_back(getValueName(Val));
- } else if (!N->isLeaf() && N->getOperator()->getName() == "fpimm") {
- assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
- std::string TmpVar = "Tmp" + utostr(ResNo);
- emitCode("SDValue " + TmpVar +
- " = CurDAG->getTargetConstantFP(*cast<ConstantFPSDNode>(" +
- Val + ")->getConstantFPValue(), cast<ConstantFPSDNode>(" +
- Val + ")->getValueType(0));");
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
- // value if used multiple times by this pattern result.
- Val = TmpVar;
- ModifiedVal = true;
- NodeOps.push_back(getValueName(Val));
- } else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
- Record *Op = OperatorMap[N->getName()];
- // Transform ExternalSymbol to TargetExternalSymbol
- if (Op && Op->getName() == "externalsym") {
- std::string TmpVar = "Tmp"+utostr(ResNo);
- emitCode("SDValue " + TmpVar + " = CurDAG->getTarget"
- "ExternalSymbol(cast<ExternalSymbolSDNode>(" +
- Val + ")->getSymbol(), " +
- getEnumName(N->getTypeNum(0)) + ");");
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select
- // this value if used multiple times by this pattern result.
- Val = TmpVar;
- ModifiedVal = true;
- }
- NodeOps.push_back(getValueName(Val));
- } else if (!N->isLeaf() && (N->getOperator()->getName() == "tglobaladdr"
- || N->getOperator()->getName() == "tglobaltlsaddr")) {
- Record *Op = OperatorMap[N->getName()];
- // Transform GlobalAddress to TargetGlobalAddress
- if (Op && (Op->getName() == "globaladdr" ||
- Op->getName() == "globaltlsaddr")) {
- std::string TmpVar = "Tmp" + utostr(ResNo);
- emitCode("SDValue " + TmpVar + " = CurDAG->getTarget"
- "GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
- ")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
- ");");
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select
- // this value if used multiple times by this pattern result.
- Val = TmpVar;
- ModifiedVal = true;
- }
- NodeOps.push_back(getValueName(Val));
- } else if (!N->isLeaf()
- && (N->getOperator()->getName() == "texternalsym"
- || N->getOperator()->getName() == "tconstpool")) {
- // Do not rewrite the variable name, since we don't generate a new
- // temporary.
- NodeOps.push_back(getValueName(Val));
- } else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, CGP))) {
- for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
- NodeOps.push_back(getValueName("CPTmp" + Val + "_" + utostr(i)));
- }
- } else {
- // This node, probably wrapped in a SDNodeXForm, behaves like a leaf
- // node even if it isn't one. Don't select it.
- if (!LikeLeaf) {
- if (isRoot && N->isLeaf()) {
- emitCode("ReplaceUses(SDValue(N, 0), " + Val + ");");
- emitCode("return NULL;");
- }
- }
- NodeOps.push_back(getValueName(Val));
- }
-
- if (ModifiedVal) {
- VariableMap[VarName] = Val;
- }
- return NodeOps;
- }
- if (N->isLeaf()) {
- // If this is an explicit register reference, handle it.
- if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
- unsigned ResNo = TmpNo++;
- if (DI->getDef()->isSubClassOf("Register")) {
- emitCode("SDValue Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
- getQualifiedName(DI->getDef()) + ", " +
- getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
- return NodeOps;
- } else if (DI->getDef()->getName() == "zero_reg") {
- emitCode("SDValue Tmp" + utostr(ResNo) +
- " = CurDAG->getRegister(0, " +
- getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
- return NodeOps;
- } else if (DI->getDef()->isSubClassOf("RegisterClass")) {
- // Handle a reference to a register class. This is used
- // in COPY_TO_SUBREG instructions.
- emitCode("SDValue Tmp" + utostr(ResNo) +
- " = CurDAG->getTargetConstant(" +
- getQualifiedName(DI->getDef()) + "RegClassID, " +
- "MVT::i32);");
- NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
- return NodeOps;
- }
- } else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
- unsigned ResNo = TmpNo++;
- assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
- emitCode("SDValue Tmp" + utostr(ResNo) +
- " = CurDAG->getTargetConstant(0x" +
- utohexstr((uint64_t) II->getValue()) +
- "ULL, " + getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
- return NodeOps;
- }
-
-#ifndef NDEBUG
- N->dump();
-#endif
- assert(0 && "Unknown leaf type!");
- return NodeOps;
- }
-
- Record *Op = N->getOperator();
- if (Op->isSubClassOf("Instruction")) {
- const CodeGenTarget &CGT = CGP.getTargetInfo();
- CodeGenInstruction &II = CGT.getInstruction(Op->getName());
- const DAGInstruction &Inst = CGP.getInstruction(Op);
- const TreePattern *InstPat = Inst.getPattern();
- // FIXME: Assume actual pattern comes before "implicit".
- TreePatternNode *InstPatNode =
- isRoot ? (InstPat ? InstPat->getTree(0) : Pattern)
- : (InstPat ? InstPat->getTree(0) : NULL);
- if (InstPatNode && !InstPatNode->isLeaf() &&
- InstPatNode->getOperator()->getName() == "set") {
- InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
- }
- bool IsVariadic = isRoot && II.isVariadic;
- // FIXME: fix how we deal with physical register operands.
- bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0;
- bool HasImpResults = isRoot && DstRegs.size() > 0;
- bool NodeHasOptInFlag = isRoot &&
- PatternHasProperty(Pattern, SDNPOptInFlag, CGP);
- bool NodeHasInFlag = isRoot &&
- PatternHasProperty(Pattern, SDNPInFlag, CGP);
- bool NodeHasOutFlag = isRoot &&
- PatternHasProperty(Pattern, SDNPOutFlag, CGP);
- bool NodeHasChain = InstPatNode &&
- PatternHasProperty(InstPatNode, SDNPHasChain, CGP);
- bool InputHasChain = isRoot &&
- NodeHasProperty(Pattern, SDNPHasChain, CGP);
- unsigned NumResults = Inst.getNumResults();
- unsigned NumDstRegs = HasImpResults ? DstRegs.size() : 0;
-
- // Record output varargs info.
- OutputIsVariadic = IsVariadic;
-
- if (NodeHasOptInFlag) {
- emitCode("bool HasInFlag = "
- "(N->getOperand(N->getNumOperands()-1).getValueType() == "
- "MVT::Flag);");
- }
- if (IsVariadic)
- emitCode("SmallVector<SDValue, 8> Ops" + utostr(OpcNo) + ";");
-
- // How many results is this pattern expected to produce?
- unsigned NumPatResults = 0;
- for (unsigned i = 0, e = Pattern->getExtTypes().size(); i != e; i++) {
- MVT::SimpleValueType VT = Pattern->getTypeNum(i);
- if (VT != MVT::isVoid && VT != MVT::Flag)
- NumPatResults++;
- }
-
- if (OrigChains.size() > 0) {
- // The original input chain is being ignored. If it is not just
- // pointing to the op that's being folded, we should create a
- // TokenFactor with it and the chain of the folded op as the new chain.
- // We could potentially be doing multiple levels of folding, in that
- // case, the TokenFactor can have more operands.
- emitCode("SmallVector<SDValue, 8> InChains;");
- for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) {
- emitCode("if (" + OrigChains[i].first + ".getNode() != " +
- OrigChains[i].second + ".getNode()) {");
- emitCode(" InChains.push_back(" + OrigChains[i].first + ");");
- emitCode("}");
- }
- emitCode("InChains.push_back(" + ChainName + ");");
- emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, "
- "N->getDebugLoc(), MVT::Other, "
- "&InChains[0], InChains.size());");
- if (GenDebug) {
- emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"yellow\");");
- emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"black\");");
- }
- }
-
- // Loop over all of the operands of the instruction pattern, emitting code
- // to fill them all in. The node 'N' usually has number children equal to
- // the number of input operands of the instruction. However, in cases
- // where there are predicate operands for an instruction, we need to fill
- // in the 'execute always' values. Match up the node operands to the
- // instruction operands to do this.
- std::vector<std::string> AllOps;
- for (unsigned ChildNo = 0, InstOpNo = NumResults;
- InstOpNo != II.OperandList.size(); ++InstOpNo) {
- std::vector<std::string> Ops;
-
- // 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()) {
- // This is a predicate or optional def operand; emit the
- // 'default ops' operands.
- const DAGDefaultOperand &DefaultOp =
- CGP.getDefaultOperand(II.OperandList[InstOpNo].Rec);
- for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i) {
- Ops = EmitResultCode(DefaultOp.DefaultOps[i], DstRegs,
- InFlagDecled, ResNodeDecled);
- AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
- }
- } 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;
- }
- }
-
- // Emit all the chain and CopyToReg stuff.
- bool ChainEmitted = NodeHasChain;
- if (NodeHasInFlag || HasImpInputs)
- EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
- InFlagDecled, ResNodeDecled, true);
- if (NodeHasOptInFlag || NodeHasInFlag || HasImpInputs) {
- if (!InFlagDecled) {
- emitCode("SDValue InFlag(0, 0);");
- InFlagDecled = true;
- }
- if (NodeHasOptInFlag) {
- emitCode("if (HasInFlag) {");
- emitCode(" InFlag = N->getOperand(N->getNumOperands()-1);");
- emitCode("}");
- }
- }
-
- unsigned ResNo = TmpNo++;
-
- unsigned OpsNo = OpcNo;
- std::string CodePrefix;
- bool ChainAssignmentNeeded = NodeHasChain && !isRoot;
- std::deque<std::string> After;
- std::string NodeName;
- if (!isRoot) {
- NodeName = "Tmp" + utostr(ResNo);
- CodePrefix = "SDValue " + NodeName + "(";
- } else {
- NodeName = "ResNode";
- if (!ResNodeDecled) {
- CodePrefix = "SDNode *" + NodeName + " = ";
- ResNodeDecled = true;
- } else
- CodePrefix = NodeName + " = ";
- }
-
- std::string Code = "Opc" + utostr(OpcNo);
-
- if (!isRoot || (InputHasChain && !NodeHasChain))
- // For call to "getMachineNode()".
- Code += ", N->getDebugLoc()";
-
- emitOpcode(II.Namespace + "::" + II.TheDef->getName());
-
- // Output order: results, chain, flags
- // Result types.
- if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) {
- Code += ", VT" + utostr(VTNo);
- emitVT(getEnumName(N->getTypeNum(0)));
- }
- // Add types for implicit results in physical registers, scheduler will
- // care of adding copyfromreg nodes.
- for (unsigned i = 0; i < NumDstRegs; i++) {
- Record *RR = DstRegs[i];
- if (RR->isSubClassOf("Register")) {
- MVT::SimpleValueType RVT = getRegisterValueType(RR, CGT);
- Code += ", " + getEnumName(RVT);
- }
- }
- if (NodeHasChain)
- Code += ", MVT::Other";
- if (NodeHasOutFlag)
- Code += ", MVT::Flag";
-
- // Inputs.
- if (IsVariadic) {
- for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
- AllOps.clear();
-
- // Figure out whether any operands at the end of the op list are not
- // part of the variable section.
- std::string EndAdjust;
- if (NodeHasInFlag || HasImpInputs)
- EndAdjust = "-1"; // Always has one flag.
- else if (NodeHasOptInFlag)
- EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
-
- emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
- ", e = N->getNumOperands()" + EndAdjust + "; i != e; ++i) {");
-
- emitCode(" Ops" + utostr(OpsNo) + ".push_back(N->getOperand(i));");
- emitCode("}");
- }
-
- // Populate MemRefs with entries for each memory accesses covered by
- // this pattern.
- if (isRoot && !LSI.empty()) {
- std::string MemRefs = "MemRefs" + utostr(OpsNo);
- emitCode("MachineSDNode::mmo_iterator " + MemRefs + " = "
- "MF->allocateMemRefsArray(" + utostr(LSI.size()) + ");");
- for (unsigned i = 0, e = LSI.size(); i != e; ++i)
- emitCode(MemRefs + "[" + utostr(i) + "] = "
- "cast<MemSDNode>(" + LSI[i] + ")->getMemOperand();");
- After.push_back("cast<MachineSDNode>(ResNode)->setMemRefs(" +
- MemRefs + ", " + MemRefs + " + " + utostr(LSI.size()) +
- ");");
- }
-
- if (NodeHasChain) {
- if (IsVariadic)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
- else
- AllOps.push_back(ChainName);
- }
-
- if (IsVariadic) {
- if (NodeHasInFlag || HasImpInputs)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
- else if (NodeHasOptInFlag) {
- emitCode("if (HasInFlag)");
- emitCode(" Ops" + utostr(OpsNo) + ".push_back(InFlag);");
- }
- Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
- ".size()";
- } else 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 = "SDValue Ops" + utostr(OpsNo) + "[] = { ";
- for (unsigned i = 0; i != NumOps; ++i) {
- OpsCode += AllOps[i];
- if (i != NumOps-1)
- OpsCode += ", ";
- }
- emitCode(OpsCode + " };");
- Code += ", Ops" + utostr(OpsNo) + ", ";
- if (NodeHasOptInFlag) {
- Code += "HasInFlag ? ";
- Code += utostr(NumOps) + " : " + utostr(NumOps-1);
- } else
- Code += utostr(NumOps);
- }
- }
-
- if (!isRoot)
- Code += "), 0";
-
- std::vector<std::string> ReplaceFroms;
- std::vector<std::string> ReplaceTos;
- if (!isRoot) {
- NodeOps.push_back("Tmp" + utostr(ResNo));
- } else {
-
- if (NodeHasOutFlag) {
- if (!InFlagDecled) {
- After.push_back("SDValue InFlag(ResNode, " +
- utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
- ");");
- InFlagDecled = true;
- } else
- After.push_back("InFlag = SDValue(ResNode, " +
- utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
- ");");
- }
-
- for (unsigned j = 0, e = FoldedChains.size(); j < e; j++) {
- ReplaceFroms.push_back("SDValue(" +
- FoldedChains[j].first + ".getNode(), " +
- utostr(FoldedChains[j].second) +
- ")");
- ReplaceTos.push_back("SDValue(ResNode, " +
- utostr(NumResults+NumDstRegs) + ")");
- }
-
- if (NodeHasOutFlag) {
- if (FoldedFlag.first != "") {
- ReplaceFroms.push_back("SDValue(" + FoldedFlag.first + ".getNode(), " +
- utostr(FoldedFlag.second) + ")");
- ReplaceTos.push_back("InFlag");
- } else {
- assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
- ReplaceFroms.push_back("SDValue(N, " +
- utostr(NumPatResults + (unsigned)InputHasChain)
- + ")");
- ReplaceTos.push_back("InFlag");
- }
- }
-
- if (!ReplaceFroms.empty() && InputHasChain) {
- ReplaceFroms.push_back("SDValue(N, " +
- utostr(NumPatResults) + ")");
- ReplaceTos.push_back("SDValue(" + ChainName + ".getNode(), " +
- ChainName + ".getResNo()" + ")");
- ChainAssignmentNeeded |= NodeHasChain;
- }
-
- // User does not expect the instruction would produce a chain!
- if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
- ;
- } else if (InputHasChain && !NodeHasChain) {
- // One of the inner node produces a chain.
- assert(!NodeHasOutFlag && "Node has flag but not chain!");
- ReplaceFroms.push_back("SDValue(N, " +
- utostr(NumPatResults) + ")");
- ReplaceTos.push_back(ChainName);
- }
- }
-
- if (ChainAssignmentNeeded) {
- // Remember which op produces the chain.
- std::string ChainAssign;
- if (!isRoot)
- ChainAssign = ChainName + " = SDValue(" + NodeName +
- ".getNode(), " + utostr(NumResults+NumDstRegs) + ");";
- else
- ChainAssign = ChainName + " = SDValue(" + NodeName +
- ", " + utostr(NumResults+NumDstRegs) + ");";
-
- After.push_front(ChainAssign);
- }
-
- if (ReplaceFroms.size() == 1) {
- After.push_back("ReplaceUses(" + ReplaceFroms[0] + ", " +
- ReplaceTos[0] + ");");
- } else if (!ReplaceFroms.empty()) {
- After.push_back("const SDValue Froms[] = {");
- for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
- After.push_back(" " + ReplaceFroms[i] + (i + 1 != e ? "," : ""));
- After.push_back("};");
- After.push_back("const SDValue Tos[] = {");
- for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
- After.push_back(" " + ReplaceTos[i] + (i + 1 != e ? "," : ""));
- After.push_back("};");
- After.push_back("ReplaceUses(Froms, Tos, " +
- itostr(ReplaceFroms.size()) + ");");
- }
-
- // We prefer to use SelectNodeTo since it avoids allocation when
- // possible and it avoids CSE map recalculation for the node's
- // users, however it's tricky to use in a non-root context.
- //
- // We also don't use SelectNodeTo if the pattern replacement is being
- // used to jettison a chain result, since morphing the node in place
- // would leave users of the chain dangling.
- //
- if (!isRoot || (InputHasChain && !NodeHasChain)) {
- Code = "CurDAG->getMachineNode(" + Code;
- } else {
- Code = "CurDAG->SelectNodeTo(N, " + Code;
- }
- if (isRoot) {
- if (After.empty())
- CodePrefix = "return ";
- else
- After.push_back("return ResNode;");
- }
-
- emitCode(CodePrefix + Code + ");");
-
- if (GenDebug) {
- if (!isRoot) {
- emitCode("CurDAG->setSubgraphColor(" + NodeName +".getNode(), \"yellow\");");
- emitCode("CurDAG->setSubgraphColor(" + NodeName +".getNode(), \"black\");");
- }
- else {
- emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"yellow\");");
- emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"black\");");
- }
- }
-
- for (unsigned i = 0, e = After.size(); i != e; ++i)
- emitCode(After[i]);
-
- return NodeOps;
- }
- if (Op->isSubClassOf("SDNodeXForm")) {
- assert(N->getNumChildren() == 1 && "node xform should have one child!");
- // PatLeaf node - the operand may or may not be a leaf node. But it should
- // behave like one.
- std::vector<std::string> Ops =
- EmitResultCode(N->getChild(0), DstRegs, InFlagDecled,
- ResNodeDecled, true);
- unsigned ResNo = TmpNo++;
- emitCode("SDValue Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
- + "(" + Ops.back() + ".getNode());");
- NodeOps.push_back("Tmp" + utostr(ResNo));
- if (isRoot)
- emitCode("return Tmp" + utostr(ResNo) + ".getNode();");
- return NodeOps;
- }
-
- N->dump();
- errs() << "\n";
- throw std::string("Unknown node in result pattern!");
- }
-
- /// InsertOneTypeCheck - Insert a type-check for an unresolved type in 'Pat'
- /// and add it to the tree. 'Pat' and 'Other' are isomorphic trees except that
- /// 'Pat' may be missing types. If we find an unresolved type to add a check
- /// for, this returns true otherwise false if Pat has all types.
- bool InsertOneTypeCheck(TreePatternNode *Pat, TreePatternNode *Other,
- const std::string &Prefix, bool isRoot = false) {
- // Did we find one?
- if (Pat->getExtTypes() != Other->getExtTypes()) {
- // Move a type over from 'other' to 'pat'.
- Pat->setTypes(Other->getExtTypes());
- // The top level node type is checked outside of the select function.
- if (!isRoot)
- emitCheck(Prefix + ".getValueType() == " +
- getName(Pat->getTypeNum(0)));
- return true;
- }
-
- unsigned OpNo =
- (unsigned) NodeHasProperty(Pat, SDNPHasChain, CGP);
- for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i, ++OpNo)
- if (InsertOneTypeCheck(Pat->getChild(i), Other->getChild(i),
- Prefix + utostr(OpNo)))
- return true;
- return false;
- }
-
-private:
- /// EmitInFlagSelectCode - Emit the flag operands for the DAG that is
- /// being built.
- void EmitInFlagSelectCode(TreePatternNode *N, const std::string &RootName,
- bool &ChainEmitted, bool &InFlagDecled,
- bool &ResNodeDecled, bool isRoot = false) {
- const CodeGenTarget &T = CGP.getTargetInfo();
- unsigned OpNo =
- (unsigned) NodeHasProperty(N, SDNPHasChain, CGP);
- bool HasInFlag = NodeHasProperty(N, SDNPInFlag, CGP);
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
- TreePatternNode *Child = N->getChild(i);
- if (!Child->isLeaf()) {
- EmitInFlagSelectCode(Child, RootName + utostr(OpNo), ChainEmitted,
- InFlagDecled, ResNodeDecled);
- } else {
- if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
- if (!Child->getName().empty()) {
- std::string Name = RootName + utostr(OpNo);
- if (Duplicates.find(Name) != Duplicates.end())
- // A duplicate! Do not emit a copy for this node.
- continue;
- }
-
- Record *RR = DI->getDef();
- if (RR->isSubClassOf("Register")) {
- MVT::SimpleValueType RVT = getRegisterValueType(RR, T);
- if (RVT == MVT::Flag) {
- if (!InFlagDecled) {
- emitCode("SDValue InFlag = " +
- getValueName(RootName + utostr(OpNo)) + ";");
- InFlagDecled = true;
- } else
- emitCode("InFlag = " +
- getValueName(RootName + utostr(OpNo)) + ";");
- } else {
- if (!ChainEmitted) {
- emitCode("SDValue Chain = CurDAG->getEntryNode();");
- ChainName = "Chain";
- ChainEmitted = true;
- }
- if (!InFlagDecled) {
- emitCode("SDValue InFlag(0, 0);");
- InFlagDecled = true;
- }
- std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
- emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
- ", " + getNodeName(RootName) + "->getDebugLoc()" +
- ", " + getQualifiedName(RR) +
- ", " + getValueName(RootName + utostr(OpNo)) +
- ", InFlag).getNode();");
- ResNodeDecled = true;
- emitCode(ChainName + " = SDValue(ResNode, 0);");
- emitCode("InFlag = SDValue(ResNode, 1);");
- }
- }
- }
- }
- }
-
- if (HasInFlag) {
- if (!InFlagDecled) {
- emitCode("SDValue InFlag = " + getNodeName(RootName) +
- "->getOperand(" + utostr(OpNo) + ");");
- InFlagDecled = true;
- } else
- emitCode("InFlag = " + getNodeName(RootName) +
- "->getOperand(" + utostr(OpNo) + ");");
- }
- }
-};
-
-/// EmitCodeForPattern - Given a pattern to match, emit code to the specified
-/// stream to match the pattern, and generate the code for the match if it
-/// succeeds. Returns true if the pattern is not guaranteed to match.
-void DAGISelEmitter::GenerateCodeForPattern(const PatternToMatch &Pattern,
- std::vector<std::pair<unsigned, std::string> > &GeneratedCode,
- std::set<std::string> &GeneratedDecl,
- std::vector<std::string> &TargetOpcodes,
- std::vector<std::string> &TargetVTs,
- bool &OutputIsVariadic,
- unsigned &NumInputRootOps) {
- OutputIsVariadic = false;
- NumInputRootOps = 0;
-
- PatternCodeEmitter Emitter(CGP, Pattern.getPredicateCheck(),
- Pattern.getSrcPattern(), Pattern.getDstPattern(),
- GeneratedCode, GeneratedDecl,
- TargetOpcodes, TargetVTs,
- OutputIsVariadic, NumInputRootOps);
-
- // Emit the matcher, capturing named arguments in VariableMap.
- bool FoundChain = false;
- Emitter.EmitMatchCode(Pattern.getSrcPattern(), NULL, "N", "", FoundChain);
-
- // TP - Get *SOME* tree pattern, we don't care which.
- TreePattern &TP = *CGP.pf_begin()->second;
-
- // At this point, we know that we structurally match the pattern, but the
- // types of the nodes may not match. Figure out the fewest number of type
- // comparisons we need to emit. For example, if there is only one integer
- // type supported by a target, there should be no type comparisons at all for
- // integer patterns!
- //
- // To figure out the fewest number of type checks needed, clone the pattern,
- // remove the types, then perform type inference on the pattern as a whole.
- // If there are unresolved types, emit an explicit check for those types,
- // apply the type to the tree, then rerun type inference. Iterate until all
- // types are resolved.
- //
- TreePatternNode *Pat = Pattern.getSrcPattern()->clone();
- RemoveAllTypes(Pat);
-
- do {
- // Resolve/propagate as many types as possible.
- try {
- bool MadeChange = true;
- while (MadeChange)
- MadeChange = Pat->ApplyTypeConstraints(TP,
- true/*Ignore reg constraints*/);
- } catch (...) {
- assert(0 && "Error: could not find consistent types for something we"
- " already decided was ok!");
- abort();
- }
-
- // Insert a check for an unresolved type and add it to the tree. If we find
- // an unresolved type to add a check for, this returns true and we iterate,
- // otherwise we are done.
- } while (Emitter.InsertOneTypeCheck(Pat, Pattern.getSrcPattern(), "N", true));
-
- Emitter.EmitResultCode(Pattern.getDstPattern(), Pattern.getDstRegs(),
- false, false, false, true);
- delete Pat;
-}
-
-/// EraseCodeLine - Erase one code line from all of the patterns. If removing
-/// a line causes any of them to be empty, remove them and return true when
-/// done.
-static bool EraseCodeLine(std::vector<std::pair<const PatternToMatch*,
- std::vector<std::pair<unsigned, std::string> > > >
- &Patterns) {
- bool ErasedPatterns = false;
- for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
- Patterns[i].second.pop_back();
- if (Patterns[i].second.empty()) {
- Patterns.erase(Patterns.begin()+i);
- --i; --e;
- ErasedPatterns = true;
- }
- }
- return ErasedPatterns;
-}
-
-/// EmitPatterns - Emit code for at least one pattern, but try to group common
-/// code together between the patterns.
-void DAGISelEmitter::EmitPatterns(std::vector<std::pair<const PatternToMatch*,
- std::vector<std::pair<unsigned, std::string> > > >
- &Patterns, unsigned Indent,
- raw_ostream &OS) {
- typedef std::pair<unsigned, std::string> CodeLine;
- typedef std::vector<CodeLine> CodeList;
- typedef std::vector<std::pair<const PatternToMatch*, CodeList> > PatternList;
-
- if (Patterns.empty()) return;
-
- // Figure out how many patterns share the next code line. Explicitly copy
- // FirstCodeLine so that we don't invalidate a reference when changing
- // Patterns.
- const CodeLine FirstCodeLine = Patterns.back().second.back();
- unsigned LastMatch = Patterns.size()-1;
- while (LastMatch != 0 && Patterns[LastMatch-1].second.back() == FirstCodeLine)
- --LastMatch;
-
- // If not all patterns share this line, split the list into two pieces. The
- // first chunk will use this line, the second chunk won't.
- if (LastMatch != 0) {
- PatternList Shared(Patterns.begin()+LastMatch, Patterns.end());
- PatternList Other(Patterns.begin(), Patterns.begin()+LastMatch);
-
- // FIXME: Emit braces?
- if (Shared.size() == 1) {
- const PatternToMatch &Pattern = *Shared.back().first;
- OS << "\n" << std::string(Indent, ' ') << "// Pattern: ";
- Pattern.getSrcPattern()->print(OS);
- OS << "\n" << std::string(Indent, ' ') << "// Emits: ";
- Pattern.getDstPattern()->print(OS);
- OS << "\n";
- unsigned AddedComplexity = Pattern.getAddedComplexity();
- OS << std::string(Indent, ' ') << "// Pattern complexity = "
- << getPatternSize(Pattern.getSrcPattern(), CGP) + AddedComplexity
- << " cost = "
- << getResultPatternCost(Pattern.getDstPattern(), CGP)
- << " size = "
- << getResultPatternSize(Pattern.getDstPattern(), CGP) << "\n";
- }
- if (FirstCodeLine.first != 1) {
- OS << std::string(Indent, ' ') << "{\n";
- Indent += 2;
- }
- EmitPatterns(Shared, Indent, OS);
- if (FirstCodeLine.first != 1) {
- Indent -= 2;
- OS << std::string(Indent, ' ') << "}\n";
- }
+ bool operator()(const PatternToMatch *LHS,
+ const PatternToMatch *RHS) {
+ unsigned LHSSize = getPatternSize(LHS->getSrcPattern(), CGP);
+ unsigned RHSSize = getPatternSize(RHS->getSrcPattern(), CGP);
+ LHSSize += LHS->getAddedComplexity();
+ RHSSize += RHS->getAddedComplexity();
+ if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
+ if (LHSSize < RHSSize) return false;
- if (Other.size() == 1) {
- const PatternToMatch &Pattern = *Other.back().first;
- OS << "\n" << std::string(Indent, ' ') << "// Pattern: ";
- Pattern.getSrcPattern()->print(OS);
- OS << "\n" << std::string(Indent, ' ') << "// Emits: ";
- Pattern.getDstPattern()->print(OS);
- OS << "\n";
- unsigned AddedComplexity = Pattern.getAddedComplexity();
- OS << std::string(Indent, ' ') << "// Pattern complexity = "
- << getPatternSize(Pattern.getSrcPattern(), CGP) + AddedComplexity
- << " cost = "
- << getResultPatternCost(Pattern.getDstPattern(), CGP)
- << " size = "
- << getResultPatternSize(Pattern.getDstPattern(), CGP) << "\n";
- }
- EmitPatterns(Other, Indent, OS);
- return;
- }
-
- // Remove this code from all of the patterns that share it.
- bool ErasedPatterns = EraseCodeLine(Patterns);
-
- bool isPredicate = FirstCodeLine.first == 1;
-
- // Otherwise, every pattern in the list has this line. Emit it.
- if (!isPredicate) {
- // Normal code.
- OS << std::string(Indent, ' ') << FirstCodeLine.second << "\n";
- } else {
- OS << std::string(Indent, ' ') << "if (" << FirstCodeLine.second;
+ // If the patterns have equal complexity, compare generated instruction cost
+ unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
+ unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
+ if (LHSCost < RHSCost) return true;
+ if (LHSCost > RHSCost) return false;
- // If the next code line is another predicate, and if all of the pattern
- // in this group share the same next line, emit it inline now. Do this
- // until we run out of common predicates.
- while (!ErasedPatterns && Patterns.back().second.back().first == 1) {
- // Check that all of the patterns in Patterns end with the same predicate.
- bool AllEndWithSamePredicate = true;
- for (unsigned i = 0, e = Patterns.size(); i != e; ++i)
- if (Patterns[i].second.back() != Patterns.back().second.back()) {
- AllEndWithSamePredicate = false;
- break;
- }
- // If all of the predicates aren't the same, we can't share them.
- if (!AllEndWithSamePredicate) break;
-
- // Otherwise we can. Emit it shared now.
- OS << " &&\n" << std::string(Indent+4, ' ')
- << Patterns.back().second.back().second;
- ErasedPatterns = EraseCodeLine(Patterns);
- }
+ unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP);
+ unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP);
+ if (LHSPatSize < RHSPatSize) return true;
+ if (LHSPatSize > RHSPatSize) return false;
- OS << ") {\n";
- Indent += 2;
+ // Sort based on the UID of the pattern, giving us a deterministic ordering.
+ assert(LHS == RHS || LHS->ID != RHS->ID);
+ return LHS->ID < RHS->ID;
}
-
- EmitPatterns(Patterns, Indent, OS);
-
- if (isPredicate)
- OS << std::string(Indent-2, ' ') << "}\n";
-}
-
-static std::string getLegalCName(std::string OpName) {
- std::string::size_type pos = OpName.find("::");
- if (pos != std::string::npos)
- OpName.replace(pos, 2, "_");
- return OpName;
+};
}
-void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
- const CodeGenTarget &Target = CGP.getTargetInfo();
-
- // Get the namespace to insert instructions into.
- std::string InstNS = Target.getInstNamespace();
- if (!InstNS.empty()) InstNS += "::";
-
- // Group the patterns by their top-level opcodes.
- std::map<std::string, std::vector<const PatternToMatch*> > PatternsByOpcode;
- // All unique target node emission functions.
- std::map<std::string, unsigned> EmitFunctions;
- for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
- E = CGP.ptm_end(); I != E; ++I) {
- const PatternToMatch &Pattern = *I;
-
- TreePatternNode *Node = Pattern.getSrcPattern();
- if (!Node->isLeaf()) {
- PatternsByOpcode[getOpcodeName(Node->getOperator(), CGP)].
- push_back(&Pattern);
- } else {
- const ComplexPattern *CP;
- if (dynamic_cast<IntInit*>(Node->getLeafValue())) {
- PatternsByOpcode[getOpcodeName(CGP.getSDNodeNamed("imm"), CGP)].
- push_back(&Pattern);
- } else if ((CP = NodeGetComplexPattern(Node, CGP))) {
- std::vector<Record*> OpNodes = CP->getRootNodes();
- for (unsigned j = 0, e = OpNodes.size(); j != e; j++) {
- PatternsByOpcode[getOpcodeName(OpNodes[j], CGP)]
- .insert(PatternsByOpcode[getOpcodeName(OpNodes[j], CGP)].begin(),
- &Pattern);
- }
- } else {
- errs() << "Unrecognized opcode '";
- Node->dump();
- errs() << "' on tree pattern '";
- errs() << Pattern.getDstPattern()->getOperator()->getName() << "'!\n";
- exit(1);
- }
- }
- }
-
- // For each opcode, there might be multiple select functions, one per
- // ValueType of the node (or its first operand if it doesn't produce a
- // non-chain result.
- std::map<std::string, std::vector<std::string> > OpcodeVTMap;
-
- // Emit one Select_* method for each top-level opcode. We do this instead of
- // emitting one giant switch statement to support compilers where this will
- // result in the recursive functions taking less stack space.
- for (std::map<std::string, std::vector<const PatternToMatch*> >::iterator
- PBOI = PatternsByOpcode.begin(), E = PatternsByOpcode.end();
- PBOI != E; ++PBOI) {
- const std::string &OpName = PBOI->first;
- std::vector<const PatternToMatch*> &PatternsOfOp = PBOI->second;
- assert(!PatternsOfOp.empty() && "No patterns but map has entry?");
-
- // Split them into groups by type.
- std::map<MVT::SimpleValueType,
- std::vector<const PatternToMatch*> > PatternsByType;
- for (unsigned i = 0, e = PatternsOfOp.size(); i != e; ++i) {
- const PatternToMatch *Pat = PatternsOfOp[i];
- TreePatternNode *SrcPat = Pat->getSrcPattern();
- PatternsByType[SrcPat->getTypeNum(0)].push_back(Pat);
- }
-
- for (std::map<MVT::SimpleValueType,
- std::vector<const PatternToMatch*> >::iterator
- II = PatternsByType.begin(), EE = PatternsByType.end(); II != EE;
- ++II) {
- MVT::SimpleValueType OpVT = II->first;
- std::vector<const PatternToMatch*> &Patterns = II->second;
- typedef std::pair<unsigned, std::string> CodeLine;
- typedef std::vector<CodeLine> CodeList;
- typedef CodeList::iterator CodeListI;
-
- std::vector<std::pair<const PatternToMatch*, CodeList> > CodeForPatterns;
- std::vector<std::vector<std::string> > PatternOpcodes;
- std::vector<std::vector<std::string> > PatternVTs;
- std::vector<std::set<std::string> > PatternDecls;
- std::vector<bool> OutputIsVariadicFlags;
- std::vector<unsigned> NumInputRootOpsCounts;
- for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
- CodeList GeneratedCode;
- std::set<std::string> GeneratedDecl;
- std::vector<std::string> TargetOpcodes;
- std::vector<std::string> TargetVTs;
- bool OutputIsVariadic;
- unsigned NumInputRootOps;
- GenerateCodeForPattern(*Patterns[i], GeneratedCode, GeneratedDecl,
- TargetOpcodes, TargetVTs,
- OutputIsVariadic, NumInputRootOps);
- CodeForPatterns.push_back(std::make_pair(Patterns[i], GeneratedCode));
- PatternDecls.push_back(GeneratedDecl);
- PatternOpcodes.push_back(TargetOpcodes);
- PatternVTs.push_back(TargetVTs);
- OutputIsVariadicFlags.push_back(OutputIsVariadic);
- NumInputRootOpsCounts.push_back(NumInputRootOps);
- }
-
- // Factor target node emission code (emitted by EmitResultCode) into
- // separate functions. Uniquing and share them among all instruction
- // selection routines.
- for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
- CodeList &GeneratedCode = CodeForPatterns[i].second;
- std::vector<std::string> &TargetOpcodes = PatternOpcodes[i];
- std::vector<std::string> &TargetVTs = PatternVTs[i];
- std::set<std::string> Decls = PatternDecls[i];
- bool OutputIsVariadic = OutputIsVariadicFlags[i];
- unsigned NumInputRootOps = NumInputRootOpsCounts[i];
- std::vector<std::string> AddedInits;
- int CodeSize = (int)GeneratedCode.size();
- int LastPred = -1;
- for (int j = CodeSize-1; j >= 0; --j) {
- if (LastPred == -1 && GeneratedCode[j].first == 1)
- LastPred = j;
- else if (LastPred != -1 && GeneratedCode[j].first == 2)
- AddedInits.push_back(GeneratedCode[j].second);
- }
-
- std::string CalleeCode = "(SDNode *N";
- std::string CallerCode = "(N";
- for (unsigned j = 0, e = TargetOpcodes.size(); j != e; ++j) {
- CalleeCode += ", unsigned Opc" + utostr(j);
- CallerCode += ", " + TargetOpcodes[j];
- }
- for (unsigned j = 0, e = TargetVTs.size(); j != e; ++j) {
- CalleeCode += ", MVT::SimpleValueType VT" + utostr(j);
- CallerCode += ", " + TargetVTs[j];
- }
- for (std::set<std::string>::iterator
- I = Decls.begin(), E = Decls.end(); I != E; ++I) {
- std::string Name = *I;
- CalleeCode += ", SDValue &" + Name;
- CallerCode += ", " + Name;
- }
-
- if (OutputIsVariadic) {
- CalleeCode += ", unsigned NumInputRootOps";
- CallerCode += ", " + utostr(NumInputRootOps);
- }
-
- CallerCode += ");";
- CalleeCode += ") {\n";
-
- for (std::vector<std::string>::const_reverse_iterator
- I = AddedInits.rbegin(), E = AddedInits.rend(); I != E; ++I)
- CalleeCode += " " + *I + "\n";
-
- for (int j = LastPred+1; j < CodeSize; ++j)
- CalleeCode += " " + GeneratedCode[j].second + "\n";
- for (int j = LastPred+1; j < CodeSize; ++j)
- GeneratedCode.pop_back();
- CalleeCode += "}\n";
-
- // Uniquing the emission routines.
- unsigned EmitFuncNum;
- std::map<std::string, unsigned>::iterator EFI =
- EmitFunctions.find(CalleeCode);
- if (EFI != EmitFunctions.end()) {
- EmitFuncNum = EFI->second;
- } else {
- EmitFuncNum = EmitFunctions.size();
- EmitFunctions.insert(std::make_pair(CalleeCode, EmitFuncNum));
- // Prevent emission routines from being inlined to reduce selection
- // routines stack frame sizes.
- OS << "DISABLE_INLINE ";
- OS << "SDNode *Emit_" << utostr(EmitFuncNum) << CalleeCode;
- }
-
- // Replace the emission code within selection routines with calls to the
- // emission functions.
- if (GenDebug) {
- GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N, \"red\");"));
- }
- CallerCode = "SDNode *Result = Emit_" + utostr(EmitFuncNum) + CallerCode;
- GeneratedCode.push_back(std::make_pair(3, CallerCode));
- if (GenDebug) {
- GeneratedCode.push_back(std::make_pair(0, "if(Result) {"));
- GeneratedCode.push_back(std::make_pair(0, " CurDAG->setSubgraphColor(Result, \"yellow\");"));
- GeneratedCode.push_back(std::make_pair(0, " CurDAG->setSubgraphColor(Result, \"black\");"));
- GeneratedCode.push_back(std::make_pair(0, "}"));
- //GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N, \"black\");"));
- }
- GeneratedCode.push_back(std::make_pair(0, "return Result;"));
- }
-
- // Print function.
- std::string OpVTStr;
- if (OpVT == MVT::iPTR) {
- OpVTStr = "_iPTR";
- } else if (OpVT == MVT::iPTRAny) {
- OpVTStr = "_iPTRAny";
- } else if (OpVT == MVT::isVoid) {
- // Nodes with a void result actually have a first result type of either
- // Other (a chain) or Flag. Since there is no one-to-one mapping from
- // void to this case, we handle it specially here.
- } else {
- OpVTStr = "_" + getEnumName(OpVT).substr(5); // Skip 'MVT::'
- }
- std::map<std::string, std::vector<std::string> >::iterator OpVTI =
- OpcodeVTMap.find(OpName);
- if (OpVTI == OpcodeVTMap.end()) {
- std::vector<std::string> VTSet;
- VTSet.push_back(OpVTStr);
- OpcodeVTMap.insert(std::make_pair(OpName, VTSet));
- } else
- OpVTI->second.push_back(OpVTStr);
-
- // We want to emit all of the matching code now. However, we want to emit
- // the matches in order of minimal cost. Sort the patterns so the least
- // cost one is at the start.
- std::stable_sort(CodeForPatterns.begin(), CodeForPatterns.end(),
- PatternSortingPredicate(CGP));
-
- // Scan the code to see if all of the patterns are reachable and if it is
- // possible that the last one might not match.
- bool mightNotMatch = true;
- for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
- CodeList &GeneratedCode = CodeForPatterns[i].second;
- mightNotMatch = false;
-
- for (unsigned j = 0, e = GeneratedCode.size(); j != e; ++j) {
- if (GeneratedCode[j].first == 1) { // predicate.
- mightNotMatch = true;
- break;
- }
- }
-
- // If this pattern definitely matches, and if it isn't the last one, the
- // patterns after it CANNOT ever match. Error out.
- if (mightNotMatch == false && i != CodeForPatterns.size()-1) {
- errs() << "Pattern '";
- CodeForPatterns[i].first->getSrcPattern()->print(errs());
- errs() << "' is impossible to select!\n";
- exit(1);
- }
- }
-
- // Loop through and reverse all of the CodeList vectors, as we will be
- // accessing them from their logical front, but accessing the end of a
- // vector is more efficient.
- for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
- CodeList &GeneratedCode = CodeForPatterns[i].second;
- std::reverse(GeneratedCode.begin(), GeneratedCode.end());
- }
-
- // Next, reverse the list of patterns itself for the same reason.
- std::reverse(CodeForPatterns.begin(), CodeForPatterns.end());
-
- OS << "SDNode *Select_" << getLegalCName(OpName)
- << OpVTStr << "(SDNode *N) {\n";
-
- // Emit all of the patterns now, grouped together to share code.
- EmitPatterns(CodeForPatterns, 2, OS);
-
- // If the last pattern has predicates (which could fail) emit code to
- // catch the case where nothing handles a pattern.
- if (mightNotMatch) {
- OS << "\n";
- if (OpName != "ISD::INTRINSIC_W_CHAIN" &&
- OpName != "ISD::INTRINSIC_WO_CHAIN" &&
- OpName != "ISD::INTRINSIC_VOID")
- OS << " CannotYetSelect(N);\n";
- else
- OS << " CannotYetSelectIntrinsic(N);\n";
-
- OS << " return NULL;\n";
- }
- OS << "}\n\n";
- }
- }
-
- OS << "// The main instruction selector code.\n"
- << "SDNode *SelectCode(SDNode *N) {\n"
- << " MVT::SimpleValueType NVT = N->getValueType(0).getSimpleVT().SimpleTy;\n"
- << " switch (N->getOpcode()) {\n"
- << " default:\n"
- << " assert(!N->isMachineOpcode() && \"Node already selected!\");\n"
- << " break;\n"
- << " case ISD::EntryToken: // These nodes remain the same.\n"
- << " case ISD::BasicBlock:\n"
- << " case ISD::Register:\n"
- << " case ISD::HANDLENODE:\n"
- << " case ISD::TargetConstant:\n"
- << " case ISD::TargetConstantFP:\n"
- << " case ISD::TargetConstantPool:\n"
- << " case ISD::TargetFrameIndex:\n"
- << " case ISD::TargetExternalSymbol:\n"
- << " case ISD::TargetBlockAddress:\n"
- << " case ISD::TargetJumpTable:\n"
- << " case ISD::TargetGlobalTLSAddress:\n"
- << " case ISD::TargetGlobalAddress:\n"
- << " case ISD::TokenFactor:\n"
- << " case ISD::CopyFromReg:\n"
- << " case ISD::CopyToReg: {\n"
- << " return NULL;\n"
- << " }\n"
- << " case ISD::AssertSext:\n"
- << " case ISD::AssertZext: {\n"
- << " ReplaceUses(SDValue(N, 0), N->getOperand(0));\n"
- << " return NULL;\n"
- << " }\n"
- << " case ISD::INLINEASM: return Select_INLINEASM(N);\n"
- << " case ISD::EH_LABEL: return Select_EH_LABEL(N);\n"
- << " case ISD::UNDEF: return Select_UNDEF(N);\n";
-
- // Loop over all of the case statements, emiting a call to each method we
- // emitted above.
- for (std::map<std::string, std::vector<const PatternToMatch*> >::iterator
- PBOI = PatternsByOpcode.begin(), E = PatternsByOpcode.end();
- PBOI != E; ++PBOI) {
- const std::string &OpName = PBOI->first;
- // Potentially multiple versions of select for this opcode. One for each
- // ValueType of the node (or its first true operand if it doesn't produce a
- // result.
- std::map<std::string, std::vector<std::string> >::iterator OpVTI =
- OpcodeVTMap.find(OpName);
- std::vector<std::string> &OpVTs = OpVTI->second;
- OS << " case " << OpName << ": {\n";
- // If we have only one variant and it's the default, elide the
- // switch. Marginally faster, and makes MSVC happier.
- if (OpVTs.size()==1 && OpVTs[0].empty()) {
- OS << " return Select_" << getLegalCName(OpName) << "(N);\n";
- OS << " break;\n";
- OS << " }\n";
- continue;
- }
- // Keep track of whether we see a pattern that has an iPtr result.
- bool HasPtrPattern = false;
- bool HasDefaultPattern = false;
-
- OS << " switch (NVT) {\n";
- for (unsigned i = 0, e = OpVTs.size(); i < e; ++i) {
- std::string &VTStr = OpVTs[i];
- if (VTStr.empty()) {
- HasDefaultPattern = true;
- continue;
- }
-
- // If this is a match on iPTR: don't emit it directly, we need special
- // code.
- if (VTStr == "_iPTR") {
- HasPtrPattern = true;
- continue;
- }
- OS << " case MVT::" << VTStr.substr(1) << ":\n"
- << " return Select_" << getLegalCName(OpName)
- << VTStr << "(N);\n";
- }
- OS << " default:\n";
-
- // If there is an iPTR result version of this pattern, emit it here.
- if (HasPtrPattern) {
- OS << " if (TLI.getPointerTy() == NVT)\n";
- OS << " return Select_" << getLegalCName(OpName) <<"_iPTR(N);\n";
- }
- if (HasDefaultPattern) {
- OS << " return Select_" << getLegalCName(OpName) << "(N);\n";
- }
- OS << " break;\n";
- OS << " }\n";
- OS << " break;\n";
- OS << " }\n";
- }
-
- OS << " } // end of big switch.\n\n"
- << " if (N->getOpcode() != ISD::INTRINSIC_W_CHAIN &&\n"
- << " N->getOpcode() != ISD::INTRINSIC_WO_CHAIN &&\n"
- << " N->getOpcode() != ISD::INTRINSIC_VOID) {\n"
- << " CannotYetSelect(N);\n"
- << " } else {\n"
- << " CannotYetSelectIntrinsic(N);\n"
- << " }\n"
- << " return NULL;\n"
- << "}\n\n";
-}
void DAGISelEmitter::run(raw_ostream &OS) {
EmitSourceFileHeader("DAG Instruction Selector for the " +
@@ -2045,24 +195,45 @@ void DAGISelEmitter::run(raw_ostream &OS) {
<< "// *** instruction selector class. These functions are really "
<< "methods.\n\n";
- OS << "// Include standard, target-independent definitions and methods used\n"
- << "// by the instruction selector.\n";
- OS << "#include \"llvm/CodeGen/DAGISelHeader.h\"\n\n";
-
- EmitNodeTransforms(OS);
+ DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n";
+ for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
+ E = CGP.ptm_end(); I != E; ++I) {
+ errs() << "PATTERN: "; I->getSrcPattern()->dump();
+ errs() << "\nRESULT: "; I->getDstPattern()->dump();
+ errs() << "\n";
+ });
+
+ // FIXME: These are being used by hand written code, gross.
EmitPredicateFunctions(OS);
-
- DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n");
+
+ // Add all the patterns to a temporary list so we can sort them.
+ std::vector<const PatternToMatch*> Patterns;
for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
- I != E; ++I) {
- DEBUG(errs() << "PATTERN: "; I->getSrcPattern()->dump());
- DEBUG(errs() << "\nRESULT: "; I->getDstPattern()->dump());
- DEBUG(errs() << "\n");
- }
+ I != E; ++I)
+ Patterns.push_back(&*I);
+
+ // We want to process the matches in order of minimal cost. Sort the patterns
+ // so the least cost one is at the start.
+ std::stable_sort(Patterns.begin(), Patterns.end(),
+ PatternSortingPredicate(CGP));
- // At this point, we have full information about the 'Patterns' we need to
- // parse, both implicitly from instructions as well as from explicit pattern
- // definitions. Emit the resultant instruction selector.
- EmitInstructionSelector(OS);
+ // Convert each variant of each pattern into a Matcher.
+ std::vector<Matcher*> PatternMatchers;
+ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ for (unsigned Variant = 0; ; ++Variant) {
+ if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP))
+ PatternMatchers.push_back(M);
+ else
+ break;
+ }
+ }
+
+ Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0],
+ PatternMatchers.size());
+
+ TheMatcher = OptimizeMatcher(TheMatcher, CGP);
+ //Matcher->dump();
+ EmitMatcherTable(TheMatcher, CGP, OS);
+ delete TheMatcher;
}
diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h
index d5b889b..5ffdde8 100644
--- a/utils/TableGen/DAGISelEmitter.h
+++ b/utils/TableGen/DAGISelEmitter.h
@@ -31,24 +31,8 @@ public:
// run - Output the isel, returning true on failure.
void run(raw_ostream &OS);
-
-
private:
- void EmitNodeTransforms(raw_ostream &OS);
void EmitPredicateFunctions(raw_ostream &OS);
-
- void GenerateCodeForPattern(const PatternToMatch &Pattern,
- std::vector<std::pair<unsigned, std::string> > &GeneratedCode,
- std::set<std::string> &GeneratedDecl,
- std::vector<std::string> &TargetOpcodes,
- std::vector<std::string> &TargetVTs,
- bool &OutputIsVariadic,
- unsigned &NumInputRootOps);
- void EmitPatterns(std::vector<std::pair<const PatternToMatch*,
- std::vector<std::pair<unsigned, std::string> > > > &Patterns,
- unsigned Indent, raw_ostream &OS);
-
- void EmitInstructionSelector(raw_ostream &OS);
};
} // End llvm namespace
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
new file mode 100644
index 0000000..22d2fe8
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -0,0 +1,402 @@
+//===- DAGISelMatcher.cpp - Representation of DAG pattern matcher ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace llvm;
+
+void Matcher::dump() const {
+ print(errs(), 0);
+}
+
+void Matcher::print(raw_ostream &OS, unsigned indent) const {
+ printImpl(OS, indent);
+ if (Next)
+ return Next->print(OS, indent);
+}
+
+void Matcher::printOne(raw_ostream &OS) const {
+ printImpl(OS, 0);
+}
+
+/// unlinkNode - Unlink the specified node from this chain. If Other == this,
+/// we unlink the next pointer and return it. Otherwise we unlink Other from
+/// the list and return this.
+Matcher *Matcher::unlinkNode(Matcher *Other) {
+ if (this == Other)
+ return takeNext();
+
+ // Scan until we find the predecessor of Other.
+ Matcher *Cur = this;
+ for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext())
+ /*empty*/;
+
+ if (Cur == 0) return 0;
+ Cur->takeNext();
+ Cur->setNext(Other->takeNext());
+ return this;
+}
+
+/// canMoveBefore - Return true if this matcher is the same as Other, or if
+/// we can move this matcher past all of the nodes in-between Other and this
+/// node. Other must be equal to or before this.
+bool Matcher::canMoveBefore(const Matcher *Other) const {
+ for (;; Other = Other->getNext()) {
+ assert(Other && "Other didn't come before 'this'?");
+ if (this == Other) return true;
+
+ // We have to be able to move this node across the Other node.
+ if (!canMoveBeforeNode(Other))
+ return false;
+ }
+}
+
+/// canMoveBefore - Return true if it is safe to move the current matcher
+/// across the specified one.
+bool Matcher::canMoveBeforeNode(const Matcher *Other) const {
+ // We can move simple predicates before record nodes.
+ if (isSimplePredicateNode())
+ return Other->isSimplePredicateOrRecordNode();
+
+ // We can move record nodes across simple predicates.
+ if (isSimplePredicateOrRecordNode())
+ return isSimplePredicateNode();
+
+ // We can't move record nodes across each other etc.
+ return false;
+}
+
+
+ScopeMatcher::~ScopeMatcher() {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ delete Children[i];
+}
+
+
+// printImpl methods.
+
+void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "Scope\n";
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ if (getChild(i) == 0)
+ OS.indent(indent+1) << "NULL POINTER\n";
+ else
+ getChild(i)->print(OS, indent+2);
+ }
+}
+
+void RecordMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "Record\n";
+}
+
+void RecordChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "RecordChild: " << ChildNo << '\n';
+}
+
+void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "RecordMemRef\n";
+}
+
+void CaptureFlagInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
+ OS.indent(indent) << "CaptureFlagInput\n";
+}
+
+void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MoveChild " << ChildNo << '\n';
+}
+
+void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MoveParent\n";
+}
+
+void CheckSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckSame " << MatchNumber << '\n';
+}
+
+void CheckPatternPredicateMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n';
+}
+
+void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckPredicate " << PredName << '\n';
+}
+
+void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckOpcode " << Opcode.getEnumName() << '\n';
+}
+
+void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "SwitchOpcode: {\n";
+ for (unsigned i = 0, e = Cases.size(); i != e; ++i) {
+ OS.indent(indent) << "case " << Cases[i].first->getEnumName() << ":\n";
+ Cases[i].second->print(OS, indent+2);
+ }
+ OS.indent(indent) << "}\n";
+}
+
+
+void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckType " << getEnumName(Type) << '\n';
+}
+
+void SwitchTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "SwitchType: {\n";
+ for (unsigned i = 0, e = Cases.size(); i != e; ++i) {
+ OS.indent(indent) << "case " << getEnumName(Cases[i].first) << ":\n";
+ Cases[i].second->print(OS, indent+2);
+ }
+ OS.indent(indent) << "}\n";
+}
+
+void CheckChildTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckChildType " << ChildNo << " "
+ << getEnumName(Type) << '\n';
+}
+
+
+void CheckIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckInteger " << Value << '\n';
+}
+
+void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n';
+}
+
+void CheckValueTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckValueType MVT::" << TypeName << '\n';
+}
+
+void CheckComplexPatMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckComplexPat " << Pattern.getSelectFunc() << '\n';
+}
+
+void CheckAndImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckAndImm " << Value << '\n';
+}
+
+void CheckOrImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckOrImm " << Value << '\n';
+}
+
+void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS,
+ unsigned indent) const {
+ OS.indent(indent) << "CheckFoldableChainNode\n";
+}
+
+void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitInteger " << Val << " VT=" << VT << '\n';
+}
+
+void EmitStringIntegerMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << VT << '\n';
+}
+
+void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitRegister ";
+ if (Reg)
+ OS << Reg->getName();
+ else
+ OS << "zero_reg";
+ OS << " VT=" << VT << '\n';
+}
+
+void EmitConvertToTargetMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n';
+}
+
+void EmitMergeInputChainsMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitMergeInputChains <todo: args>\n";
+}
+
+void EmitCopyToRegMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitCopyToReg <todo: args>\n";
+}
+
+void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName()
+ << " Slot=" << Slot << '\n';
+}
+
+
+void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent);
+ OS << (isa<MorphNodeToMatcher>(this) ? "MorphNodeTo: " : "EmitNode: ")
+ << OpcodeName << ": <todo flags> ";
+
+ for (unsigned i = 0, e = VTs.size(); i != e; ++i)
+ OS << ' ' << getEnumName(VTs[i]);
+ OS << '(';
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ OS << Operands[i] << ' ';
+ OS << ")\n";
+}
+
+void MarkFlagResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MarkFlagResults <todo: args>\n";
+}
+
+void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CompleteMatch <todo args>\n";
+ OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n";
+ OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n";
+}
+
+// getHashImpl Implementation.
+
+unsigned CheckPatternPredicateMatcher::getHashImpl() const {
+ return HashString(Predicate);
+}
+
+unsigned CheckPredicateMatcher::getHashImpl() const {
+ return HashString(PredName);
+}
+
+unsigned CheckOpcodeMatcher::getHashImpl() const {
+ return HashString(Opcode.getEnumName());
+}
+
+unsigned CheckCondCodeMatcher::getHashImpl() const {
+ return HashString(CondCodeName);
+}
+
+unsigned CheckValueTypeMatcher::getHashImpl() const {
+ return HashString(TypeName);
+}
+
+unsigned EmitStringIntegerMatcher::getHashImpl() const {
+ return HashString(Val) ^ VT;
+}
+
+template<typename It>
+static unsigned HashUnsigneds(It I, It E) {
+ unsigned Result = 0;
+ for (; I != E; ++I)
+ Result = (Result<<3) ^ *I;
+ return Result;
+}
+
+unsigned EmitMergeInputChainsMatcher::getHashImpl() const {
+ return HashUnsigneds(ChainNodes.begin(), ChainNodes.end());
+}
+
+bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const {
+ // Note: pointer equality isn't enough here, we have to check the enum names
+ // to ensure that the nodes are for the same opcode.
+ return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() ==
+ Opcode.getEnumName();
+}
+
+
+bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
+ const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m);
+ return M->OpcodeName == OpcodeName && M->VTs == VTs &&
+ M->Operands == Operands && M->HasChain == HasChain &&
+ M->HasInFlag == HasInFlag && M->HasOutFlag == HasOutFlag &&
+ M->HasMemRefs == HasMemRefs &&
+ M->NumFixedArityOperands == NumFixedArityOperands;
+}
+
+unsigned EmitNodeMatcherCommon::getHashImpl() const {
+ return (HashString(OpcodeName) << 4) | Operands.size();
+}
+
+
+unsigned MarkFlagResultsMatcher::getHashImpl() const {
+ return HashUnsigneds(FlagResultNodes.begin(), FlagResultNodes.end());
+}
+
+unsigned CompleteMatchMatcher::getHashImpl() const {
+ return HashUnsigneds(Results.begin(), Results.end()) ^
+ ((unsigned)(intptr_t)&Pattern << 8);
+}
+
+// isContradictoryImpl Implementations.
+
+static bool TypesAreContradictory(MVT::SimpleValueType T1,
+ MVT::SimpleValueType T2) {
+ // If the two types are the same, then they are the same, so they don't
+ // contradict.
+ if (T1 == T2) return false;
+
+ // If either type is about iPtr, then they don't conflict unless the other
+ // one is not a scalar integer type.
+ if (T1 == MVT::iPTR)
+ return !MVT(T2).isInteger() || MVT(T2).isVector();
+
+ if (T2 == MVT::iPTR)
+ return !MVT(T1).isInteger() || MVT(T1).isVector();
+
+ // Otherwise, they are two different non-iPTR types, they conflict.
+ return true;
+}
+
+bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) {
+ // One node can't have two different opcodes!
+ // Note: pointer equality isn't enough here, we have to check the enum names
+ // to ensure that the nodes are for the same opcode.
+ return COM->getOpcode().getEnumName() != getOpcode().getEnumName();
+ }
+
+ // If the node has a known type, and if the type we're checking for is
+ // different, then we know they contradict. For example, a check for
+ // ISD::STORE will never be true at the same time a check for Type i32 is.
+ if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) {
+ // FIXME: What result is this referring to?
+ unsigned NodeType;
+ if (getOpcode().getNumResults() == 0)
+ NodeType = MVT::isVoid;
+ else
+ NodeType = getOpcode().getKnownType();
+ if (NodeType != EEVT::isUnknown)
+ return TypesAreContradictory((MVT::SimpleValueType)NodeType,
+ CT->getType());
+ }
+
+ return false;
+}
+
+bool CheckTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M))
+ return TypesAreContradictory(getType(), CT->getType());
+ return false;
+}
+
+bool CheckChildTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckChildTypeMatcher *CC = dyn_cast<CheckChildTypeMatcher>(M)) {
+ // If the two checks are about different nodes, we don't know if they
+ // conflict!
+ if (CC->getChildNo() != getChildNo())
+ return false;
+
+ return TypesAreContradictory(getType(), CC->getType());
+ }
+ return false;
+}
+
+bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M))
+ return CIM->getValue() != getValue();
+ return false;
+}
+
+bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M))
+ return CVT->getTypeName() != getTypeName();
+ return false;
+}
+
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
new file mode 100644
index 0000000..ef7ecf4
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -0,0 +1,1112 @@
+//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TBLGEN_DAGISELMATCHER_H
+#define TBLGEN_DAGISELMATCHER_H
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+ class CodeGenDAGPatterns;
+ class Matcher;
+ class PatternToMatch;
+ class raw_ostream;
+ class ComplexPattern;
+ class Record;
+ class SDNodeInfo;
+
+Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant,
+ const CodeGenDAGPatterns &CGP);
+Matcher *OptimizeMatcher(Matcher *Matcher, const CodeGenDAGPatterns &CGP);
+void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP,
+ raw_ostream &OS);
+
+
+/// Matcher - Base class for all the the DAG ISel Matcher representation
+/// nodes.
+class Matcher {
+ // The next matcher node that is executed after this one. Null if this is the
+ // last stage of a match.
+ OwningPtr<Matcher> Next;
+public:
+ enum KindTy {
+ // Matcher state manipulation.
+ Scope, // Push a checking scope.
+ RecordNode, // Record the current node.
+ RecordChild, // Record a child of the current node.
+ RecordMemRef, // Record the memref in the current node.
+ CaptureFlagInput, // If the current node has an input flag, save it.
+ MoveChild, // Move current node to specified child.
+ MoveParent, // Move current node to parent.
+
+ // Predicate checking.
+ CheckSame, // Fail if not same as prev match.
+ CheckPatternPredicate,
+ CheckPredicate, // Fail if node predicate fails.
+ CheckOpcode, // Fail if not opcode.
+ SwitchOpcode, // Dispatch based on opcode.
+ CheckType, // Fail if not correct type.
+ SwitchType, // Dispatch based on type.
+ CheckChildType, // Fail if child has wrong type.
+ CheckInteger, // Fail if wrong val.
+ CheckCondCode, // Fail if not condcode.
+ CheckValueType,
+ CheckComplexPat,
+ CheckAndImm,
+ CheckOrImm,
+ CheckFoldableChainNode,
+
+ // Node creation/emisssion.
+ EmitInteger, // Create a TargetConstant
+ EmitStringInteger, // Create a TargetConstant from a string.
+ EmitRegister, // Create a register.
+ EmitConvertToTarget, // Convert a imm/fpimm to target imm/fpimm
+ EmitMergeInputChains, // Merge together a chains for an input.
+ EmitCopyToReg, // Emit a copytoreg into a physreg.
+ EmitNode, // Create a DAG node
+ EmitNodeXForm, // Run a SDNodeXForm
+ MarkFlagResults, // Indicate which interior nodes have flag results.
+ CompleteMatch, // Finish a match and update the results.
+ MorphNodeTo // Build a node, finish a match and update results.
+ };
+ const KindTy Kind;
+
+protected:
+ Matcher(KindTy K) : Kind(K) {}
+public:
+ virtual ~Matcher() {}
+
+ KindTy getKind() const { return Kind; }
+
+ Matcher *getNext() { return Next.get(); }
+ const Matcher *getNext() const { return Next.get(); }
+ void setNext(Matcher *C) { Next.reset(C); }
+ Matcher *takeNext() { return Next.take(); }
+
+ OwningPtr<Matcher> &getNextPtr() { return Next; }
+
+ static inline bool classof(const Matcher *) { return true; }
+
+ bool isEqual(const Matcher *M) const {
+ if (getKind() != M->getKind()) return false;
+ return isEqualImpl(M);
+ }
+
+ unsigned getHash() const {
+ // Clear the high bit so we don't conflict with tombstones etc.
+ return ((getHashImpl() << 4) ^ getKind()) & (~0U>>1);
+ }
+
+ /// isSafeToReorderWithPatternPredicate - Return true if it is safe to sink a
+ /// PatternPredicate node past this one.
+ virtual bool isSafeToReorderWithPatternPredicate() const {
+ return false;
+ }
+
+ /// isSimplePredicateNode - Return true if this is a simple predicate that
+ /// operates on the node or its children without potential side effects or a
+ /// change of the current node.
+ bool isSimplePredicateNode() const {
+ switch (getKind()) {
+ default: return false;
+ case CheckSame:
+ case CheckPatternPredicate:
+ case CheckPredicate:
+ case CheckOpcode:
+ case CheckType:
+ case CheckChildType:
+ case CheckInteger:
+ case CheckCondCode:
+ case CheckValueType:
+ case CheckAndImm:
+ case CheckOrImm:
+ case CheckFoldableChainNode:
+ return true;
+ }
+ }
+
+ /// isSimplePredicateOrRecordNode - Return true if this is a record node or
+ /// a simple predicate.
+ bool isSimplePredicateOrRecordNode() const {
+ return isSimplePredicateNode() ||
+ getKind() == RecordNode || getKind() == RecordChild;
+ }
+
+ /// unlinkNode - Unlink the specified node from this chain. If Other == this,
+ /// we unlink the next pointer and return it. Otherwise we unlink Other from
+ /// the list and return this.
+ Matcher *unlinkNode(Matcher *Other);
+
+ /// canMoveBefore - Return true if this matcher is the same as Other, or if
+ /// we can move this matcher past all of the nodes in-between Other and this
+ /// node. Other must be equal to or before this.
+ bool canMoveBefore(const Matcher *Other) const;
+
+ /// canMoveBefore - Return true if it is safe to move the current matcher
+ /// across the specified one.
+ bool canMoveBeforeNode(const Matcher *Other) const;
+
+ /// isContradictory - Return true of these two matchers could never match on
+ /// the same node.
+ bool isContradictory(const Matcher *Other) const {
+ // Since this predicate is reflexive, we canonicalize the ordering so that
+ // we always match a node against nodes with kinds that are greater or equal
+ // to them. For example, we'll pass in a CheckType node as an argument to
+ // the CheckOpcode method, not the other way around.
+ if (getKind() < Other->getKind())
+ return isContradictoryImpl(Other);
+ return Other->isContradictoryImpl(this);
+ }
+
+ void print(raw_ostream &OS, unsigned indent = 0) const;
+ void printOne(raw_ostream &OS) const;
+ void dump() const;
+protected:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const = 0;
+ virtual bool isEqualImpl(const Matcher *M) const = 0;
+ virtual unsigned getHashImpl() const = 0;
+ virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
+};
+
+/// ScopeMatcher - This attempts to match each of its children to find the first
+/// one that successfully matches. If one child fails, it tries the next child.
+/// If none of the children match then this check fails. It never has a 'next'.
+class ScopeMatcher : public Matcher {
+ SmallVector<Matcher*, 4> Children;
+public:
+ ScopeMatcher(Matcher *const *children, unsigned numchildren)
+ : Matcher(Scope), Children(children, children+numchildren) {
+ }
+ virtual ~ScopeMatcher();
+
+ unsigned getNumChildren() const { return Children.size(); }
+
+ Matcher *getChild(unsigned i) { return Children[i]; }
+ const Matcher *getChild(unsigned i) const { return Children[i]; }
+
+ void resetChild(unsigned i, Matcher *N) {
+ delete Children[i];
+ Children[i] = N;
+ }
+
+ Matcher *takeChild(unsigned i) {
+ Matcher *Res = Children[i];
+ Children[i] = 0;
+ return Res;
+ }
+
+ void setNumChildren(unsigned NC) {
+ if (NC < Children.size()) {
+ // delete any children we're about to lose pointers to.
+ for (unsigned i = NC, e = Children.size(); i != e; ++i)
+ delete Children[i];
+ }
+ Children.resize(NC);
+ }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == Scope;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return false; }
+ virtual unsigned getHashImpl() const { return 12312; }
+};
+
+/// RecordMatcher - Save the current node in the operand list.
+class RecordMatcher : public Matcher {
+ /// WhatFor - This is a string indicating why we're recording this. This
+ /// should only be used for comment generation not anything semantic.
+ std::string WhatFor;
+
+ /// ResultNo - The slot number in the RecordedNodes vector that this will be,
+ /// just printed as a comment.
+ unsigned ResultNo;
+public:
+ RecordMatcher(const std::string &whatfor, unsigned resultNo)
+ : Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {}
+
+ const std::string &getWhatFor() const { return WhatFor; }
+ unsigned getResultNo() const { return ResultNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordNode;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+/// RecordChildMatcher - Save a numbered child of the current node, or fail
+/// the match if it doesn't exist. This is logically equivalent to:
+/// MoveChild N + RecordNode + MoveParent.
+class RecordChildMatcher : public Matcher {
+ unsigned ChildNo;
+
+ /// WhatFor - This is a string indicating why we're recording this. This
+ /// should only be used for comment generation not anything semantic.
+ std::string WhatFor;
+
+ /// ResultNo - The slot number in the RecordedNodes vector that this will be,
+ /// just printed as a comment.
+ unsigned ResultNo;
+public:
+ RecordChildMatcher(unsigned childno, const std::string &whatfor,
+ unsigned resultNo)
+ : Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor),
+ ResultNo(resultNo) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ const std::string &getWhatFor() const { return WhatFor; }
+ unsigned getResultNo() const { return ResultNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordChild;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<RecordChildMatcher>(M)->getChildNo() == getChildNo();
+ }
+ virtual unsigned getHashImpl() const { return getChildNo(); }
+};
+
+/// RecordMemRefMatcher - Save the current node's memref.
+class RecordMemRefMatcher : public Matcher {
+public:
+ RecordMemRefMatcher() : Matcher(RecordMemRef) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordMemRef;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+
+/// CaptureFlagInputMatcher - If the current record has a flag input, record
+/// it so that it is used as an input to the generated code.
+class CaptureFlagInputMatcher : public Matcher {
+public:
+ CaptureFlagInputMatcher() : Matcher(CaptureFlagInput) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CaptureFlagInput;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+/// MoveChildMatcher - This tells the interpreter to move into the
+/// specified child node.
+class MoveChildMatcher : public Matcher {
+ unsigned ChildNo;
+public:
+ MoveChildMatcher(unsigned childNo) : Matcher(MoveChild), ChildNo(childNo) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MoveChild;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<MoveChildMatcher>(M)->getChildNo() == getChildNo();
+ }
+ virtual unsigned getHashImpl() const { return getChildNo(); }
+};
+
+/// MoveParentMatcher - This tells the interpreter to move to the parent
+/// of the current node.
+class MoveParentMatcher : public Matcher {
+public:
+ MoveParentMatcher() : Matcher(MoveParent) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MoveParent;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+/// CheckSameMatcher - This checks to see if this node is exactly the same
+/// node as the specified match that was recorded with 'Record'. This is used
+/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
+class CheckSameMatcher : public Matcher {
+ unsigned MatchNumber;
+public:
+ CheckSameMatcher(unsigned matchnumber)
+ : Matcher(CheckSame), MatchNumber(matchnumber) {}
+
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckSame;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckSameMatcher>(M)->getMatchNumber() == getMatchNumber();
+ }
+ virtual unsigned getHashImpl() const { return getMatchNumber(); }
+};
+
+/// CheckPatternPredicateMatcher - This checks the target-specific predicate
+/// to see if the entire pattern is capable of matching. This predicate does
+/// not take a node as input. This is used for subtarget feature checks etc.
+class CheckPatternPredicateMatcher : public Matcher {
+ std::string Predicate;
+public:
+ CheckPatternPredicateMatcher(StringRef predicate)
+ : Matcher(CheckPatternPredicate), Predicate(predicate) {}
+
+ StringRef getPredicate() const { return Predicate; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckPatternPredicate;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckPatternPredicateMatcher>(M)->getPredicate() == Predicate;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// CheckPredicateMatcher - This checks the target-specific predicate to
+/// see if the node is acceptable.
+class CheckPredicateMatcher : public Matcher {
+ StringRef PredName;
+public:
+ CheckPredicateMatcher(StringRef predname)
+ : Matcher(CheckPredicate), PredName(predname) {}
+
+ StringRef getPredicateName() const { return PredName; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckPredicate;
+ }
+
+ // TODO: Ok?
+ //virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckPredicateMatcher>(M)->PredName == PredName;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+
+/// CheckOpcodeMatcher - This checks to see if the current node has the
+/// specified opcode, if not it fails to match.
+class CheckOpcodeMatcher : public Matcher {
+ const SDNodeInfo &Opcode;
+public:
+ CheckOpcodeMatcher(const SDNodeInfo &opcode)
+ : Matcher(CheckOpcode), Opcode(opcode) {}
+
+ const SDNodeInfo &getOpcode() const { return Opcode; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckOpcode;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const;
+ virtual unsigned getHashImpl() const;
+ virtual bool isContradictoryImpl(const Matcher *M) const;
+};
+
+/// SwitchOpcodeMatcher - Switch based on the current node's opcode, dispatching
+/// to one matcher per opcode. If the opcode doesn't match any of the cases,
+/// then the match fails. This is semantically equivalent to a Scope node where
+/// every child does a CheckOpcode, but is much faster.
+class SwitchOpcodeMatcher : public Matcher {
+ SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
+public:
+ SwitchOpcodeMatcher(const std::pair<const SDNodeInfo*, Matcher*> *cases,
+ unsigned numcases)
+ : Matcher(SwitchOpcode), Cases(cases, cases+numcases) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == SwitchOpcode;
+ }
+
+ unsigned getNumCases() const { return Cases.size(); }
+
+ const SDNodeInfo &getCaseOpcode(unsigned i) const { return *Cases[i].first; }
+ Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
+ const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return false; }
+ virtual unsigned getHashImpl() const { return 4123; }
+};
+
+/// CheckTypeMatcher - This checks to see if the current node has the
+/// specified type, if not it fails to match.
+class CheckTypeMatcher : public Matcher {
+ MVT::SimpleValueType Type;
+public:
+ CheckTypeMatcher(MVT::SimpleValueType type)
+ : Matcher(CheckType), Type(type) {}
+
+ MVT::SimpleValueType getType() const { return Type; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckType;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckTypeMatcher>(M)->Type == Type;
+ }
+ virtual unsigned getHashImpl() const { return Type; }
+ virtual bool isContradictoryImpl(const Matcher *M) const;
+};
+
+/// SwitchTypeMatcher - Switch based on the current node's type, dispatching
+/// to one matcher per case. If the type doesn't match any of the cases,
+/// then the match fails. This is semantically equivalent to a Scope node where
+/// every child does a CheckType, but is much faster.
+class SwitchTypeMatcher : public Matcher {
+ SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
+public:
+ SwitchTypeMatcher(const std::pair<MVT::SimpleValueType, Matcher*> *cases,
+ unsigned numcases)
+ : Matcher(SwitchType), Cases(cases, cases+numcases) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == SwitchType;
+ }
+
+ unsigned getNumCases() const { return Cases.size(); }
+
+ MVT::SimpleValueType getCaseType(unsigned i) const { return Cases[i].first; }
+ Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
+ const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return false; }
+ virtual unsigned getHashImpl() const { return 4123; }
+};
+
+
+/// CheckChildTypeMatcher - This checks to see if a child node has the
+/// specified type, if not it fails to match.
+class CheckChildTypeMatcher : public Matcher {
+ unsigned ChildNo;
+ MVT::SimpleValueType Type;
+public:
+ CheckChildTypeMatcher(unsigned childno, MVT::SimpleValueType type)
+ : Matcher(CheckChildType), ChildNo(childno), Type(type) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ MVT::SimpleValueType getType() const { return Type; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckChildType;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckChildTypeMatcher>(M)->ChildNo == ChildNo &&
+ cast<CheckChildTypeMatcher>(M)->Type == Type;
+ }
+ virtual unsigned getHashImpl() const { return (Type << 3) | ChildNo; }
+ virtual bool isContradictoryImpl(const Matcher *M) const;
+};
+
+
+/// CheckIntegerMatcher - This checks to see if the current node is a
+/// ConstantSDNode with the specified integer value, if not it fails to match.
+class CheckIntegerMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckIntegerMatcher(int64_t value)
+ : Matcher(CheckInteger), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckInteger;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckIntegerMatcher>(M)->Value == Value;
+ }
+ virtual unsigned getHashImpl() const { return Value; }
+ virtual bool isContradictoryImpl(const Matcher *M) const;
+};
+
+/// CheckCondCodeMatcher - This checks to see if the current node is a
+/// CondCodeSDNode with the specified condition, if not it fails to match.
+class CheckCondCodeMatcher : public Matcher {
+ StringRef CondCodeName;
+public:
+ CheckCondCodeMatcher(StringRef condcodename)
+ : Matcher(CheckCondCode), CondCodeName(condcodename) {}
+
+ StringRef getCondCodeName() const { return CondCodeName; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckCondCode;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// CheckValueTypeMatcher - This checks to see if the current node is a
+/// VTSDNode with the specified type, if not it fails to match.
+class CheckValueTypeMatcher : public Matcher {
+ StringRef TypeName;
+public:
+ CheckValueTypeMatcher(StringRef type_name)
+ : Matcher(CheckValueType), TypeName(type_name) {}
+
+ StringRef getTypeName() const { return TypeName; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckValueType;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName;
+ }
+ virtual unsigned getHashImpl() const;
+ bool isContradictoryImpl(const Matcher *M) const;
+};
+
+
+
+/// CheckComplexPatMatcher - This node runs the specified ComplexPattern on
+/// the current node.
+class CheckComplexPatMatcher : public Matcher {
+ const ComplexPattern &Pattern;
+
+ /// MatchNumber - This is the recorded nodes slot that contains the node we want to
+ /// match against.
+ unsigned MatchNumber;
+
+ /// Name - The name of the node we're matching, for comment emission.
+ std::string Name;
+
+ /// FirstResult - This is the first slot in the RecordedNodes list that the
+ /// result of the match populates.
+ unsigned FirstResult;
+public:
+ CheckComplexPatMatcher(const ComplexPattern &pattern, unsigned matchnumber,
+ const std::string &name, unsigned firstresult)
+ : Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber),
+ Name(name), FirstResult(firstresult) {}
+
+ const ComplexPattern &getPattern() const { return Pattern; }
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ const std::string getName() const { return Name; }
+ unsigned getFirstResult() const { return FirstResult; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckComplexPat;
+ }
+
+ // Not safe to move a pattern predicate past a complex pattern.
+ virtual bool isSafeToReorderWithPatternPredicate() const { return false; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern &&
+ cast<CheckComplexPatMatcher>(M)->MatchNumber == MatchNumber;
+ }
+ virtual unsigned getHashImpl() const {
+ return (unsigned)(intptr_t)&Pattern ^ MatchNumber;
+ }
+};
+
+/// CheckAndImmMatcher - This checks to see if the current node is an 'and'
+/// with something equivalent to the specified immediate.
+class CheckAndImmMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckAndImmMatcher(int64_t value)
+ : Matcher(CheckAndImm), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckAndImm;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckAndImmMatcher>(M)->Value == Value;
+ }
+ virtual unsigned getHashImpl() const { return Value; }
+};
+
+/// CheckOrImmMatcher - This checks to see if the current node is an 'and'
+/// with something equivalent to the specified immediate.
+class CheckOrImmMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckOrImmMatcher(int64_t value)
+ : Matcher(CheckOrImm), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckOrImm;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckOrImmMatcher>(M)->Value == Value;
+ }
+ virtual unsigned getHashImpl() const { return Value; }
+};
+
+/// CheckFoldableChainNodeMatcher - This checks to see if the current node
+/// (which defines a chain operand) is safe to fold into a larger pattern.
+class CheckFoldableChainNodeMatcher : public Matcher {
+public:
+ CheckFoldableChainNodeMatcher()
+ : Matcher(CheckFoldableChainNode) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckFoldableChainNode;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const { return true; }
+ virtual unsigned getHashImpl() const { return 0; }
+};
+
+/// EmitIntegerMatcher - This creates a new TargetConstant.
+class EmitIntegerMatcher : public Matcher {
+ int64_t Val;
+ MVT::SimpleValueType VT;
+public:
+ EmitIntegerMatcher(int64_t val, MVT::SimpleValueType vt)
+ : Matcher(EmitInteger), Val(val), VT(vt) {}
+
+ int64_t getValue() const { return Val; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitInteger;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitIntegerMatcher>(M)->Val == Val &&
+ cast<EmitIntegerMatcher>(M)->VT == VT;
+ }
+ virtual unsigned getHashImpl() const { return (Val << 4) | VT; }
+};
+
+/// EmitStringIntegerMatcher - A target constant whose value is represented
+/// by a string.
+class EmitStringIntegerMatcher : public Matcher {
+ std::string Val;
+ MVT::SimpleValueType VT;
+public:
+ EmitStringIntegerMatcher(const std::string &val, MVT::SimpleValueType vt)
+ : Matcher(EmitStringInteger), Val(val), VT(vt) {}
+
+ const std::string &getValue() const { return Val; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitStringInteger;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitStringIntegerMatcher>(M)->Val == Val &&
+ cast<EmitStringIntegerMatcher>(M)->VT == VT;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// EmitRegisterMatcher - This creates a new TargetConstant.
+class EmitRegisterMatcher : public Matcher {
+ /// Reg - The def for the register that we're emitting. If this is null, then
+ /// this is a reference to zero_reg.
+ Record *Reg;
+ MVT::SimpleValueType VT;
+public:
+ EmitRegisterMatcher(Record *reg, MVT::SimpleValueType vt)
+ : Matcher(EmitRegister), Reg(reg), VT(vt) {}
+
+ Record *getReg() const { return Reg; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitRegister;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitRegisterMatcher>(M)->Reg == Reg &&
+ cast<EmitRegisterMatcher>(M)->VT == VT;
+ }
+ virtual unsigned getHashImpl() const {
+ return ((unsigned)(intptr_t)Reg) << 4 | VT;
+ }
+};
+
+/// EmitConvertToTargetMatcher - Emit an operation that reads a specified
+/// recorded node and converts it from being a ISD::Constant to
+/// ISD::TargetConstant, likewise for ConstantFP.
+class EmitConvertToTargetMatcher : public Matcher {
+ unsigned Slot;
+public:
+ EmitConvertToTargetMatcher(unsigned slot)
+ : Matcher(EmitConvertToTarget), Slot(slot) {}
+
+ unsigned getSlot() const { return Slot; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitConvertToTarget;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitConvertToTargetMatcher>(M)->Slot == Slot;
+ }
+ virtual unsigned getHashImpl() const { return Slot; }
+};
+
+/// EmitMergeInputChainsMatcher - Emit a node that merges a list of input
+/// chains together with a token factor. The list of nodes are the nodes in the
+/// matched pattern that have chain input/outputs. This node adds all input
+/// chains of these nodes if they are not themselves a node in the pattern.
+class EmitMergeInputChainsMatcher : public Matcher {
+ SmallVector<unsigned, 3> ChainNodes;
+public:
+ EmitMergeInputChainsMatcher(const unsigned *nodes, unsigned NumNodes)
+ : Matcher(EmitMergeInputChains), ChainNodes(nodes, nodes+NumNodes) {}
+
+ unsigned getNumNodes() const { return ChainNodes.size(); }
+
+ unsigned getNode(unsigned i) const {
+ assert(i < ChainNodes.size());
+ return ChainNodes[i];
+ }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitMergeInputChains;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitMergeInputChainsMatcher>(M)->ChainNodes == ChainNodes;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg,
+/// pushing the chain and flag results.
+///
+class EmitCopyToRegMatcher : public Matcher {
+ unsigned SrcSlot; // Value to copy into the physreg.
+ Record *DestPhysReg;
+public:
+ EmitCopyToRegMatcher(unsigned srcSlot, Record *destPhysReg)
+ : Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {}
+
+ unsigned getSrcSlot() const { return SrcSlot; }
+ Record *getDestPhysReg() const { return DestPhysReg; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitCopyToReg;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot &&
+ cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg;
+ }
+ virtual unsigned getHashImpl() const {
+ return SrcSlot ^ ((unsigned)(intptr_t)DestPhysReg << 4);
+ }
+};
+
+
+
+/// EmitNodeXFormMatcher - Emit an operation that runs an SDNodeXForm on a
+/// recorded node and records the result.
+class EmitNodeXFormMatcher : public Matcher {
+ unsigned Slot;
+ Record *NodeXForm;
+public:
+ EmitNodeXFormMatcher(unsigned slot, Record *nodeXForm)
+ : Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {}
+
+ unsigned getSlot() const { return Slot; }
+ Record *getNodeXForm() const { return NodeXForm; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNodeXForm;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<EmitNodeXFormMatcher>(M)->Slot == Slot &&
+ cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm;
+ }
+ virtual unsigned getHashImpl() const {
+ return Slot ^ ((unsigned)(intptr_t)NodeXForm << 4);
+ }
+};
+
+/// EmitNodeMatcherCommon - Common class shared between EmitNode and
+/// MorphNodeTo.
+class EmitNodeMatcherCommon : public Matcher {
+ std::string OpcodeName;
+ const SmallVector<MVT::SimpleValueType, 3> VTs;
+ const SmallVector<unsigned, 6> Operands;
+ bool HasChain, HasInFlag, HasOutFlag, HasMemRefs;
+
+ /// NumFixedArityOperands - If this is a fixed arity node, this is set to -1.
+ /// If this is a varidic node, this is set to the number of fixed arity
+ /// operands in the root of the pattern. The rest are appended to this node.
+ int NumFixedArityOperands;
+public:
+ EmitNodeMatcherCommon(const std::string &opcodeName,
+ const MVT::SimpleValueType *vts, unsigned numvts,
+ const unsigned *operands, unsigned numops,
+ bool hasChain, bool hasInFlag, bool hasOutFlag,
+ bool hasmemrefs,
+ int numfixedarityoperands, bool isMorphNodeTo)
+ : Matcher(isMorphNodeTo ? MorphNodeTo : EmitNode), OpcodeName(opcodeName),
+ VTs(vts, vts+numvts), Operands(operands, operands+numops),
+ HasChain(hasChain), HasInFlag(hasInFlag), HasOutFlag(hasOutFlag),
+ HasMemRefs(hasmemrefs), NumFixedArityOperands(numfixedarityoperands) {}
+
+ const std::string &getOpcodeName() const { return OpcodeName; }
+
+ unsigned getNumVTs() const { return VTs.size(); }
+ MVT::SimpleValueType getVT(unsigned i) const {
+ assert(i < VTs.size());
+ return VTs[i];
+ }
+
+ unsigned getNumOperands() const { return Operands.size(); }
+ unsigned getOperand(unsigned i) const {
+ assert(i < Operands.size());
+ return Operands[i];
+ }
+
+ const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; }
+ const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; }
+
+
+ bool hasChain() const { return HasChain; }
+ bool hasInFlag() const { return HasInFlag; }
+ bool hasOutFlag() const { return HasOutFlag; }
+ bool hasMemRefs() const { return HasMemRefs; }
+ int getNumFixedArityOperands() const { return NumFixedArityOperands; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNode || N->getKind() == MorphNodeTo;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const;
+ virtual unsigned getHashImpl() const;
+};
+
+/// EmitNodeMatcher - This signals a successful match and generates a node.
+class EmitNodeMatcher : public EmitNodeMatcherCommon {
+ unsigned FirstResultSlot;
+public:
+ EmitNodeMatcher(const std::string &opcodeName,
+ const MVT::SimpleValueType *vts, unsigned numvts,
+ const unsigned *operands, unsigned numops,
+ bool hasChain, bool hasInFlag, bool hasOutFlag,
+ bool hasmemrefs,
+ int numfixedarityoperands, unsigned firstresultslot)
+ : EmitNodeMatcherCommon(opcodeName, vts, numvts, operands, numops, hasChain,
+ hasInFlag, hasOutFlag, hasmemrefs,
+ numfixedarityoperands, false),
+ FirstResultSlot(firstresultslot) {}
+
+ unsigned getFirstResultSlot() const { return FirstResultSlot; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNode;
+ }
+
+};
+
+class MorphNodeToMatcher : public EmitNodeMatcherCommon {
+ const PatternToMatch &Pattern;
+public:
+ MorphNodeToMatcher(const std::string &opcodeName,
+ const MVT::SimpleValueType *vts, unsigned numvts,
+ const unsigned *operands, unsigned numops,
+ bool hasChain, bool hasInFlag, bool hasOutFlag,
+ bool hasmemrefs,
+ int numfixedarityoperands, const PatternToMatch &pattern)
+ : EmitNodeMatcherCommon(opcodeName, vts, numvts, operands, numops, hasChain,
+ hasInFlag, hasOutFlag, hasmemrefs,
+ numfixedarityoperands, true),
+ Pattern(pattern) {
+ }
+
+ const PatternToMatch &getPattern() const { return Pattern; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MorphNodeTo;
+ }
+};
+
+/// MarkFlagResultsMatcher - This node indicates which non-root nodes in the
+/// pattern produce flags. This allows CompleteMatchMatcher to update them
+/// with the output flag of the resultant code.
+class MarkFlagResultsMatcher : public Matcher {
+ SmallVector<unsigned, 3> FlagResultNodes;
+public:
+ MarkFlagResultsMatcher(const unsigned *nodes, unsigned NumNodes)
+ : Matcher(MarkFlagResults), FlagResultNodes(nodes, nodes+NumNodes) {}
+
+ unsigned getNumNodes() const { return FlagResultNodes.size(); }
+
+ unsigned getNode(unsigned i) const {
+ assert(i < FlagResultNodes.size());
+ return FlagResultNodes[i];
+ }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MarkFlagResults;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<MarkFlagResultsMatcher>(M)->FlagResultNodes == FlagResultNodes;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+/// CompleteMatchMatcher - Complete a match by replacing the results of the
+/// pattern with the newly generated nodes. This also prints a comment
+/// indicating the source and dest patterns.
+class CompleteMatchMatcher : public Matcher {
+ SmallVector<unsigned, 2> Results;
+ const PatternToMatch &Pattern;
+public:
+ CompleteMatchMatcher(const unsigned *results, unsigned numresults,
+ const PatternToMatch &pattern)
+ : Matcher(CompleteMatch), Results(results, results+numresults),
+ Pattern(pattern) {}
+
+ unsigned getNumResults() const { return Results.size(); }
+ unsigned getResult(unsigned R) const { return Results[R]; }
+ const PatternToMatch &getPattern() const { return Pattern; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CompleteMatch;
+ }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CompleteMatchMatcher>(M)->Results == Results &&
+ &cast<CompleteMatchMatcher>(M)->Pattern == &Pattern;
+ }
+ virtual unsigned getHashImpl() const;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
new file mode 100644
index 0000000..cabf2d4
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -0,0 +1,779 @@
+//===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to generate C++ code a matcher.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "Record.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
+using namespace llvm;
+
+enum {
+ CommentIndent = 30
+};
+
+// To reduce generated source code size.
+static cl::opt<bool>
+OmitComments("omit-comments", cl::desc("Do not generate comments"),
+ cl::init(false));
+
+namespace {
+class MatcherTableEmitter {
+ StringMap<unsigned> NodePredicateMap, PatternPredicateMap;
+ std::vector<std::string> NodePredicates, PatternPredicates;
+
+ DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap;
+ std::vector<const ComplexPattern*> ComplexPatterns;
+
+
+ DenseMap<Record*, unsigned> NodeXFormMap;
+ std::vector<Record*> NodeXForms;
+
+public:
+ MatcherTableEmitter() {}
+
+ unsigned EmitMatcherList(const Matcher *N, unsigned Indent,
+ unsigned StartIdx, formatted_raw_ostream &OS);
+
+ void EmitPredicateFunctions(const CodeGenDAGPatterns &CGP,
+ formatted_raw_ostream &OS);
+
+ void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS);
+private:
+ unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS);
+
+ unsigned getNodePredicate(StringRef PredName) {
+ unsigned &Entry = NodePredicateMap[PredName];
+ if (Entry == 0) {
+ NodePredicates.push_back(PredName.str());
+ Entry = NodePredicates.size();
+ }
+ return Entry-1;
+ }
+ unsigned getPatternPredicate(StringRef PredName) {
+ unsigned &Entry = PatternPredicateMap[PredName];
+ if (Entry == 0) {
+ PatternPredicates.push_back(PredName.str());
+ Entry = PatternPredicates.size();
+ }
+ return Entry-1;
+ }
+
+ unsigned getComplexPat(const ComplexPattern &P) {
+ unsigned &Entry = ComplexPatternMap[&P];
+ if (Entry == 0) {
+ ComplexPatterns.push_back(&P);
+ Entry = ComplexPatterns.size();
+ }
+ return Entry-1;
+ }
+
+ unsigned getNodeXFormID(Record *Rec) {
+ unsigned &Entry = NodeXFormMap[Rec];
+ if (Entry == 0) {
+ NodeXForms.push_back(Rec);
+ Entry = NodeXForms.size();
+ }
+ return Entry-1;
+ }
+
+};
+} // end anonymous namespace.
+
+static unsigned GetVBRSize(unsigned Val) {
+ if (Val <= 127) return 1;
+
+ unsigned NumBytes = 0;
+ while (Val >= 128) {
+ Val >>= 7;
+ ++NumBytes;
+ }
+ return NumBytes+1;
+}
+
+/// EmitVBRValue - Emit the specified value as a VBR, returning the number of
+/// bytes emitted.
+static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) {
+ if (Val <= 127) {
+ OS << Val << ", ";
+ return 1;
+ }
+
+ uint64_t InVal = Val;
+ unsigned NumBytes = 0;
+ while (Val >= 128) {
+ OS << (Val&127) << "|128,";
+ Val >>= 7;
+ ++NumBytes;
+ }
+ OS << Val;
+ if (!OmitComments)
+ OS << "/*" << InVal << "*/";
+ OS << ", ";
+ return NumBytes+1;
+}
+
+/// EmitMatcherOpcodes - Emit bytes for the specified matcher and return
+/// the number of bytes emitted.
+unsigned MatcherTableEmitter::
+EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS) {
+ OS.PadToColumn(Indent*2);
+
+ switch (N->getKind()) {
+ case Matcher::Scope: {
+ const ScopeMatcher *SM = cast<ScopeMatcher>(N);
+ assert(SM->getNext() == 0 && "Shouldn't have next after scope");
+
+ unsigned StartIdx = CurrentIdx;
+
+ // Emit all of the children.
+ for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
+ if (i == 0) {
+ OS << "OPC_Scope, ";
+ ++CurrentIdx;
+ } else {
+ if (!OmitComments) {
+ OS << "/*" << CurrentIdx << "*/";
+ OS.PadToColumn(Indent*2) << "/*Scope*/ ";
+ } else
+ OS.PadToColumn(Indent*2);
+ }
+
+ // We need to encode the child and the offset of the failure code before
+ // emitting either of them. Handle this by buffering the output into a
+ // string while we get the size. Unfortunately, the offset of the
+ // children depends on the VBR size of the child, so for large children we
+ // have to iterate a bit.
+ SmallString<128> TmpBuf;
+ unsigned ChildSize = 0;
+ unsigned VBRSize = 0;
+ do {
+ VBRSize = GetVBRSize(ChildSize);
+
+ TmpBuf.clear();
+ raw_svector_ostream OS(TmpBuf);
+ formatted_raw_ostream FOS(OS);
+ ChildSize = EmitMatcherList(SM->getChild(i), Indent+1,
+ CurrentIdx+VBRSize, FOS);
+ } while (GetVBRSize(ChildSize) != VBRSize);
+
+ assert(ChildSize != 0 && "Should not have a zero-sized child!");
+
+ CurrentIdx += EmitVBRValue(ChildSize, OS);
+ if (!OmitComments) {
+ OS << "/*->" << CurrentIdx+ChildSize << "*/";
+
+ if (i == 0)
+ OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren()
+ << " children in Scope";
+ }
+
+ OS << '\n' << TmpBuf.str();
+ CurrentIdx += ChildSize;
+ }
+
+ // Emit a zero as a sentinel indicating end of 'Scope'.
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
+ OS.PadToColumn(Indent*2) << "0, ";
+ if (!OmitComments)
+ OS << "/*End of Scope*/";
+ OS << '\n';
+ return CurrentIdx - StartIdx + 1;
+ }
+
+ case Matcher::RecordNode:
+ OS << "OPC_RecordNode,";
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// #"
+ << cast<RecordMatcher>(N)->getResultNo() << " = "
+ << cast<RecordMatcher>(N)->getWhatFor();
+ OS << '\n';
+ return 1;
+
+ case Matcher::RecordChild:
+ OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo()
+ << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// #"
+ << cast<RecordChildMatcher>(N)->getResultNo() << " = "
+ << cast<RecordChildMatcher>(N)->getWhatFor();
+ OS << '\n';
+ return 1;
+
+ case Matcher::RecordMemRef:
+ OS << "OPC_RecordMemRef,\n";
+ return 1;
+
+ case Matcher::CaptureFlagInput:
+ OS << "OPC_CaptureFlagInput,\n";
+ return 1;
+
+ case Matcher::MoveChild:
+ OS << "OPC_MoveChild, " << cast<MoveChildMatcher>(N)->getChildNo() << ",\n";
+ return 2;
+
+ case Matcher::MoveParent:
+ OS << "OPC_MoveParent,\n";
+ return 1;
+
+ case Matcher::CheckSame:
+ OS << "OPC_CheckSame, "
+ << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";
+ return 2;
+
+ case Matcher::CheckPatternPredicate: {
+ StringRef Pred = cast<CheckPatternPredicateMatcher>(N)->getPredicate();
+ OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// " << Pred;
+ OS << '\n';
+ return 2;
+ }
+ case Matcher::CheckPredicate: {
+ StringRef Pred = cast<CheckPredicateMatcher>(N)->getPredicateName();
+ OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// " << Pred;
+ OS << '\n';
+ return 2;
+ }
+
+ case Matcher::CheckOpcode:
+ OS << "OPC_CheckOpcode, "
+ << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << ",\n";
+ return 2;
+
+ case Matcher::SwitchOpcode:
+ case Matcher::SwitchType: {
+ unsigned StartIdx = CurrentIdx;
+
+ unsigned NumCases;
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
+ OS << "OPC_SwitchOpcode ";
+ NumCases = SOM->getNumCases();
+ } else {
+ OS << "OPC_SwitchType ";
+ NumCases = cast<SwitchTypeMatcher>(N)->getNumCases();
+ }
+
+ if (!OmitComments)
+ OS << "/*" << NumCases << " cases */";
+ OS << ", ";
+ ++CurrentIdx;
+
+ // For each case we emit the size, then the opcode, then the matcher.
+ for (unsigned i = 0, e = NumCases; i != e; ++i) {
+ const Matcher *Child;
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
+ Child = SOM->getCaseMatcher(i);
+ else
+ Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
+
+ // We need to encode the opcode and the offset of the case code before
+ // emitting the case code. Handle this by buffering the output into a
+ // string while we get the size. Unfortunately, the offset of the
+ // children depends on the VBR size of the child, so for large children we
+ // have to iterate a bit.
+ SmallString<128> TmpBuf;
+ unsigned ChildSize = 0;
+ unsigned VBRSize = 0;
+ do {
+ VBRSize = GetVBRSize(ChildSize);
+
+ TmpBuf.clear();
+ raw_svector_ostream OS(TmpBuf);
+ formatted_raw_ostream FOS(OS);
+ ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+1, FOS);
+ } while (GetVBRSize(ChildSize) != VBRSize);
+
+ assert(ChildSize != 0 && "Should not have a zero-sized child!");
+
+ if (i != 0) {
+ OS.PadToColumn(Indent*2);
+ if (!OmitComments)
+ OS << (isa<SwitchOpcodeMatcher>(N) ?
+ "/*SwitchOpcode*/ " : "/*SwitchType*/ ");
+ }
+
+ // Emit the VBR.
+ CurrentIdx += EmitVBRValue(ChildSize, OS);
+
+ OS << ' ';
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
+ OS << SOM->getCaseOpcode(i).getEnumName();
+ else
+ OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i));
+ OS << ',';
+
+ if (!OmitComments)
+ OS << "// ->" << CurrentIdx+ChildSize+1;
+ OS << '\n';
+ ++CurrentIdx;
+ OS << TmpBuf.str();
+ CurrentIdx += ChildSize;
+ }
+
+ // Emit the final zero to terminate the switch.
+ OS.PadToColumn(Indent*2) << "0, ";
+ if (!OmitComments)
+ OS << (isa<SwitchOpcodeMatcher>(N) ?
+ "// EndSwitchOpcode" : "// EndSwitchType");
+
+ OS << '\n';
+ ++CurrentIdx;
+ return CurrentIdx-StartIdx;
+ }
+
+ case Matcher::CheckType:
+ OS << "OPC_CheckType, "
+ << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";
+ return 2;
+
+ case Matcher::CheckChildType:
+ OS << "OPC_CheckChild"
+ << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, "
+ << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n";
+ return 2;
+
+ case Matcher::CheckInteger: {
+ OS << "OPC_CheckInteger, ";
+ unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+ case Matcher::CheckCondCode:
+ OS << "OPC_CheckCondCode, ISD::"
+ << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n";
+ return 2;
+
+ case Matcher::CheckValueType:
+ OS << "OPC_CheckValueType, MVT::"
+ << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n";
+ return 2;
+
+ case Matcher::CheckComplexPat: {
+ const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N);
+ const ComplexPattern &Pattern = CCPM->getPattern();
+ OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/"
+ << CCPM->getMatchNumber() << ',';
+
+ if (!OmitComments) {
+ OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc();
+ OS << ":$" << CCPM->getName();
+ for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i)
+ OS << " #" << CCPM->getFirstResult()+i;
+
+ if (Pattern.hasProperty(SDNPHasChain))
+ OS << " + chain result";
+ }
+ OS << '\n';
+ return 3;
+ }
+
+ case Matcher::CheckAndImm: {
+ OS << "OPC_CheckAndImm, ";
+ unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+
+ case Matcher::CheckOrImm: {
+ OS << "OPC_CheckOrImm, ";
+ unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+
+ case Matcher::CheckFoldableChainNode:
+ OS << "OPC_CheckFoldableChainNode,\n";
+ return 1;
+
+ case Matcher::EmitInteger: {
+ int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();
+ OS << "OPC_EmitInteger, "
+ << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", ";
+ unsigned Bytes = 2+EmitVBRValue(Val, OS);
+ OS << '\n';
+ return Bytes;
+ }
+ case Matcher::EmitStringInteger: {
+ const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();
+ // These should always fit into one byte.
+ OS << "OPC_EmitInteger, "
+ << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "
+ << Val << ",\n";
+ return 3;
+ }
+
+ case Matcher::EmitRegister:
+ OS << "OPC_EmitRegister, "
+ << getEnumName(cast<EmitRegisterMatcher>(N)->getVT()) << ", ";
+ if (Record *R = cast<EmitRegisterMatcher>(N)->getReg())
+ OS << getQualifiedName(R) << ",\n";
+ else {
+ OS << "0 ";
+ if (!OmitComments)
+ OS << "/*zero_reg*/";
+ OS << ",\n";
+ }
+ return 3;
+
+ case Matcher::EmitConvertToTarget:
+ OS << "OPC_EmitConvertToTarget, "
+ << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n";
+ return 2;
+
+ case Matcher::EmitMergeInputChains: {
+ const EmitMergeInputChainsMatcher *MN =
+ cast<EmitMergeInputChainsMatcher>(N);
+ OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", ";
+ for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)
+ OS << MN->getNode(i) << ", ";
+ OS << '\n';
+ return 2+MN->getNumNodes();
+ }
+ case Matcher::EmitCopyToReg:
+ OS << "OPC_EmitCopyToReg, "
+ << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", "
+ << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg())
+ << ",\n";
+ return 3;
+ case Matcher::EmitNodeXForm: {
+ const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N);
+ OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", "
+ << XF->getSlot() << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// "<<XF->getNodeXForm()->getName();
+ OS <<'\n';
+ return 3;
+ }
+
+ case Matcher::EmitNode:
+ case Matcher::MorphNodeTo: {
+ const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
+ OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");
+ OS << ", TARGET_OPCODE(" << EN->getOpcodeName() << "), 0";
+
+ if (EN->hasChain()) OS << "|OPFL_Chain";
+ if (EN->hasInFlag()) OS << "|OPFL_FlagInput";
+ if (EN->hasOutFlag()) OS << "|OPFL_FlagOutput";
+ if (EN->hasMemRefs()) OS << "|OPFL_MemRefs";
+ if (EN->getNumFixedArityOperands() != -1)
+ OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
+ OS << ",\n";
+
+ OS.PadToColumn(Indent*2+4) << EN->getNumVTs();
+ if (!OmitComments)
+ OS << "/*#VTs*/";
+ OS << ", ";
+ for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i)
+ OS << getEnumName(EN->getVT(i)) << ", ";
+
+ OS << EN->getNumOperands();
+ if (!OmitComments)
+ OS << "/*#Ops*/";
+ OS << ", ";
+ unsigned NumOperandBytes = 0;
+ for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i)
+ NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS);
+
+ if (!OmitComments) {
+ // Print the result #'s for EmitNode.
+ if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) {
+ if (unsigned NumResults = EN->getNumVTs()) {
+ OS.PadToColumn(CommentIndent) << "// Results = ";
+ unsigned First = E->getFirstResultSlot();
+ for (unsigned i = 0; i != NumResults; ++i)
+ OS << "#" << First+i << " ";
+ }
+ }
+ OS << '\n';
+
+ if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
+ OS.PadToColumn(Indent*2) << "// Src: "
+ << *SNT->getPattern().getSrcPattern() << '\n';
+ OS.PadToColumn(Indent*2) << "// Dst: "
+ << *SNT->getPattern().getDstPattern() << '\n';
+ }
+ } else
+ OS << '\n';
+
+ return 6+EN->getNumVTs()+NumOperandBytes;
+ }
+ case Matcher::MarkFlagResults: {
+ const MarkFlagResultsMatcher *CFR = cast<MarkFlagResultsMatcher>(N);
+ OS << "OPC_MarkFlagResults, " << CFR->getNumNodes() << ", ";
+ unsigned NumOperandBytes = 0;
+ for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i)
+ NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS);
+ OS << '\n';
+ return 2+NumOperandBytes;
+ }
+ case Matcher::CompleteMatch: {
+ const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
+ OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
+ unsigned NumResultBytes = 0;
+ for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
+ NumResultBytes += EmitVBRValue(CM->getResult(i), OS);
+ OS << '\n';
+ if (!OmitComments) {
+ OS.PadToColumn(Indent*2) << "// Src: "
+ << *CM->getPattern().getSrcPattern() << '\n';
+ OS.PadToColumn(Indent*2) << "// Dst: "
+ << *CM->getPattern().getDstPattern();
+ }
+ OS << '\n';
+ return 2 + NumResultBytes;
+ }
+ }
+ assert(0 && "Unreachable");
+ return 0;
+}
+
+/// EmitMatcherList - Emit the bytes for the specified matcher subtree.
+unsigned MatcherTableEmitter::
+EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS) {
+ unsigned Size = 0;
+ while (N) {
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
+ unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS);
+ Size += MatcherSize;
+ CurrentIdx += MatcherSize;
+
+ // If there are other nodes in this list, iterate to them, otherwise we're
+ // done.
+ N = N->getNext();
+ }
+ return Size;
+}
+
+void MatcherTableEmitter::EmitPredicateFunctions(const CodeGenDAGPatterns &CGP,
+ formatted_raw_ostream &OS) {
+ // Emit pattern predicates.
+ if (!PatternPredicates.empty()) {
+ OS << "bool CheckPatternPredicate(unsigned PredNo) const {\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: assert(0 && \"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i)
+ OS << " case " << i << ": return " << PatternPredicates[i] << ";\n";
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+ // Emit Node predicates.
+ // FIXME: Annoyingly, these are stored by name, which we never even emit. Yay?
+ StringMap<TreePattern*> PFsByName;
+
+ for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
+ I != E; ++I)
+ PFsByName[I->first->getName()] = I->second;
+
+ if (!NodePredicates.empty()) {
+ OS << "bool CheckNodePredicate(SDNode *Node, unsigned PredNo) const {\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: assert(0 && \"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) {
+ // FIXME: Storing this by name is horrible.
+ TreePattern *P =PFsByName[NodePredicates[i].substr(strlen("Predicate_"))];
+ assert(P && "Unknown name?");
+
+ // Emit the predicate code corresponding to this pattern.
+ std::string Code = P->getRecord()->getValueAsCode("Predicate");
+ assert(!Code.empty() && "No code in this predicate");
+ OS << " case " << i << ": { // " << NodePredicates[i] << '\n';
+ std::string ClassName;
+ if (P->getOnlyTree()->isLeaf())
+ ClassName = "SDNode";
+ else
+ ClassName =
+ CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
+ if (ClassName == "SDNode")
+ OS << " SDNode *N = Node;\n";
+ else
+ OS << " " << ClassName << "*N = cast<" << ClassName << ">(Node);\n";
+ OS << Code << "\n }\n";
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+ // Emit CompletePattern matchers.
+ // FIXME: This should be const.
+ if (!ComplexPatterns.empty()) {
+ OS << "bool CheckComplexPattern(SDNode *Root, SDValue N,\n";
+ OS << " unsigned PatternNo, SmallVectorImpl<SDValue> &Result) {\n";
+ OS << " switch (PatternNo) {\n";
+ OS << " default: assert(0 && \"Invalid pattern # in table?\");\n";
+ for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) {
+ const ComplexPattern &P = *ComplexPatterns[i];
+ unsigned NumOps = P.getNumOperands();
+
+ if (P.hasProperty(SDNPHasChain))
+ ++NumOps; // Get the chained node too.
+
+ OS << " case " << i << ":\n";
+ OS << " Result.resize(Result.size()+" << NumOps << ");\n";
+ OS << " return " << P.getSelectFunc();
+
+ OS << "(Root, N";
+ for (unsigned i = 0; i != NumOps; ++i)
+ OS << ", Result[Result.size()-" << (NumOps-i) << ']';
+ OS << ");\n";
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+
+ // Emit SDNodeXForm handlers.
+ // FIXME: This should be const.
+ if (!NodeXForms.empty()) {
+ OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n";
+ OS << " switch (XFormNo) {\n";
+ OS << " default: assert(0 && \"Invalid xform # in table?\");\n";
+
+ // FIXME: The node xform could take SDValue's instead of SDNode*'s.
+ for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) {
+ const CodeGenDAGPatterns::NodeXForm &Entry =
+ CGP.getSDNodeTransform(NodeXForms[i]);
+
+ Record *SDNode = Entry.first;
+ const std::string &Code = Entry.second;
+
+ OS << " case " << i << ": { ";
+ if (!OmitComments)
+ OS << "// " << NodeXForms[i]->getName();
+ OS << '\n';
+
+ std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName();
+ if (ClassName == "SDNode")
+ OS << " SDNode *N = V.getNode();\n";
+ else
+ OS << " " << ClassName << " *N = cast<" << ClassName
+ << ">(V.getNode());\n";
+ OS << Code << "\n }\n";
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+}
+
+static void BuildHistogram(const Matcher *M, std::vector<unsigned> &OpcodeFreq){
+ for (; M != 0; M = M->getNext()) {
+ // Count this node.
+ if (unsigned(M->getKind()) >= OpcodeFreq.size())
+ OpcodeFreq.resize(M->getKind()+1);
+ OpcodeFreq[M->getKind()]++;
+
+ // Handle recursive nodes.
+ if (const ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M)) {
+ for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i)
+ BuildHistogram(SM->getChild(i), OpcodeFreq);
+ } else if (const SwitchOpcodeMatcher *SOM =
+ dyn_cast<SwitchOpcodeMatcher>(M)) {
+ for (unsigned i = 0, e = SOM->getNumCases(); i != e; ++i)
+ BuildHistogram(SOM->getCaseMatcher(i), OpcodeFreq);
+ } else if (const SwitchTypeMatcher *STM = dyn_cast<SwitchTypeMatcher>(M)) {
+ for (unsigned i = 0, e = STM->getNumCases(); i != e; ++i)
+ BuildHistogram(STM->getCaseMatcher(i), OpcodeFreq);
+ }
+ }
+}
+
+void MatcherTableEmitter::EmitHistogram(const Matcher *M,
+ formatted_raw_ostream &OS) {
+ if (OmitComments)
+ return;
+
+ std::vector<unsigned> OpcodeFreq;
+ BuildHistogram(M, OpcodeFreq);
+
+ OS << " // Opcode Histogram:\n";
+ for (unsigned i = 0, e = OpcodeFreq.size(); i != e; ++i) {
+ OS << " // #";
+ switch ((Matcher::KindTy)i) {
+ case Matcher::Scope: OS << "OPC_Scope"; break;
+ case Matcher::RecordNode: OS << "OPC_RecordNode"; break;
+ case Matcher::RecordChild: OS << "OPC_RecordChild"; break;
+ case Matcher::RecordMemRef: OS << "OPC_RecordMemRef"; break;
+ case Matcher::CaptureFlagInput: OS << "OPC_CaptureFlagInput"; break;
+ case Matcher::MoveChild: OS << "OPC_MoveChild"; break;
+ case Matcher::MoveParent: OS << "OPC_MoveParent"; break;
+ case Matcher::CheckSame: OS << "OPC_CheckSame"; break;
+ case Matcher::CheckPatternPredicate:
+ OS << "OPC_CheckPatternPredicate"; break;
+ case Matcher::CheckPredicate: OS << "OPC_CheckPredicate"; break;
+ case Matcher::CheckOpcode: OS << "OPC_CheckOpcode"; break;
+ case Matcher::SwitchOpcode: OS << "OPC_SwitchOpcode"; break;
+ case Matcher::CheckType: OS << "OPC_CheckType"; break;
+ case Matcher::SwitchType: OS << "OPC_SwitchType"; break;
+ case Matcher::CheckChildType: OS << "OPC_CheckChildType"; break;
+ case Matcher::CheckInteger: OS << "OPC_CheckInteger"; break;
+ case Matcher::CheckCondCode: OS << "OPC_CheckCondCode"; break;
+ case Matcher::CheckValueType: OS << "OPC_CheckValueType"; break;
+ case Matcher::CheckComplexPat: OS << "OPC_CheckComplexPat"; break;
+ case Matcher::CheckAndImm: OS << "OPC_CheckAndImm"; break;
+ case Matcher::CheckOrImm: OS << "OPC_CheckOrImm"; break;
+ case Matcher::CheckFoldableChainNode:
+ OS << "OPC_CheckFoldableChainNode"; break;
+ case Matcher::EmitInteger: OS << "OPC_EmitInteger"; break;
+ case Matcher::EmitStringInteger: OS << "OPC_EmitStringInteger"; break;
+ case Matcher::EmitRegister: OS << "OPC_EmitRegister"; break;
+ case Matcher::EmitConvertToTarget: OS << "OPC_EmitConvertToTarget"; break;
+ case Matcher::EmitMergeInputChains: OS << "OPC_EmitMergeInputChains"; break;
+ case Matcher::EmitCopyToReg: OS << "OPC_EmitCopyToReg"; break;
+ case Matcher::EmitNode: OS << "OPC_EmitNode"; break;
+ case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break;
+ case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break;
+ case Matcher::MarkFlagResults: OS << "OPC_MarkFlagResults"; break;
+ case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break;
+ }
+
+ OS.PadToColumn(40) << " = " << OpcodeFreq[i] << '\n';
+ }
+ OS << '\n';
+}
+
+
+void llvm::EmitMatcherTable(const Matcher *TheMatcher,
+ const CodeGenDAGPatterns &CGP, raw_ostream &O) {
+ formatted_raw_ostream OS(O);
+
+ OS << "// The main instruction selector code.\n";
+ OS << "SDNode *SelectCode(SDNode *N) {\n";
+
+ MatcherTableEmitter MatcherEmitter;
+
+ OS << " // Opcodes are emitted as 2 bytes, TARGET_OPCODE handles this.\n";
+ OS << " #define TARGET_OPCODE(X) X & 255, unsigned(X) >> 8\n";
+ OS << " static const unsigned char MatcherTable[] = {\n";
+ unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 5, 0, OS);
+ OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";
+
+ MatcherEmitter.EmitHistogram(TheMatcher, OS);
+
+ OS << " #undef TARGET_OPCODE\n";
+ OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n";
+ OS << '\n';
+
+ // Next up, emit the function for node and pattern predicates:
+ MatcherEmitter.EmitPredicateFunctions(CGP, OS);
+}
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
new file mode 100644
index 0000000..4951a42
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -0,0 +1,882 @@
+//===- DAGISelMatcherGen.cpp - Matcher generator --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "Record.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include <utility>
+using namespace llvm;
+
+
+/// getRegisterValueType - Look up and return the ValueType of the specified
+/// register. If the register is a member of multiple register classes which
+/// have different associated types, return MVT::Other.
+static MVT::SimpleValueType getRegisterValueType(Record *R,
+ const CodeGenTarget &T) {
+ bool FoundRC = false;
+ MVT::SimpleValueType VT = MVT::Other;
+ const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
+ std::vector<Record*>::const_iterator Element;
+
+ for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RCs[rc];
+ if (!std::count(RC.Elements.begin(), RC.Elements.end(), R))
+ continue;
+
+ if (!FoundRC) {
+ FoundRC = true;
+ VT = RC.getValueTypeNum(0);
+ continue;
+ }
+
+ // If this occurs in multiple register classes, they all have to agree.
+ assert(VT == RC.getValueTypeNum(0));
+ }
+ return VT;
+}
+
+
+namespace {
+ class MatcherGen {
+ const PatternToMatch &Pattern;
+ const CodeGenDAGPatterns &CGP;
+
+ /// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts
+ /// out with all of the types removed. This allows us to insert type checks
+ /// as we scan the tree.
+ TreePatternNode *PatWithNoTypes;
+
+ /// VariableMap - A map from variable names ('$dst') to the recorded operand
+ /// number that they were captured as. These are biased by 1 to make
+ /// insertion easier.
+ StringMap<unsigned> VariableMap;
+
+ /// NextRecordedOperandNo - As we emit opcodes to record matched values in
+ /// the RecordedNodes array, this keeps track of which slot will be next to
+ /// record into.
+ unsigned NextRecordedOperandNo;
+
+ /// MatchedChainNodes - This maintains the position in the recorded nodes
+ /// array of all of the recorded input nodes that have chains.
+ SmallVector<unsigned, 2> MatchedChainNodes;
+
+ /// MatchedFlagResultNodes - This maintains the position in the recorded
+ /// nodes array of all of the recorded input nodes that have flag results.
+ SmallVector<unsigned, 2> MatchedFlagResultNodes;
+
+ /// MatchedComplexPatterns - This maintains a list of all of the
+ /// ComplexPatterns that we need to check. The patterns are known to have
+ /// names which were recorded. The second element of each pair is the first
+ /// slot number that the OPC_CheckComplexPat opcode drops the matched
+ /// results into.
+ SmallVector<std::pair<const TreePatternNode*,
+ unsigned>, 2> MatchedComplexPatterns;
+
+ /// PhysRegInputs - List list has an entry for each explicitly specified
+ /// physreg input to the pattern. The first elt is the Register node, the
+ /// second is the recorded slot number the input pattern match saved it in.
+ SmallVector<std::pair<Record*, unsigned>, 2> PhysRegInputs;
+
+ /// Matcher - This is the top level of the generated matcher, the result.
+ Matcher *TheMatcher;
+
+ /// CurPredicate - As we emit matcher nodes, this points to the latest check
+ /// which should have future checks stuck into its Next position.
+ Matcher *CurPredicate;
+ public:
+ MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
+
+ ~MatcherGen() {
+ delete PatWithNoTypes;
+ }
+
+ bool EmitMatcherCode(unsigned Variant);
+ void EmitResultCode();
+
+ Matcher *GetMatcher() const { return TheMatcher; }
+ Matcher *GetCurPredicate() const { return CurPredicate; }
+ private:
+ void AddMatcher(Matcher *NewNode);
+ void InferPossibleTypes();
+
+ // Matcher Generation.
+ void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes);
+ void EmitLeafMatchCode(const TreePatternNode *N);
+ void EmitOperatorMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes);
+
+ // Result Code Generation.
+ unsigned getNamedArgumentSlot(StringRef Name) {
+ unsigned VarMapEntry = VariableMap[Name];
+ assert(VarMapEntry != 0 &&
+ "Variable referenced but not defined and not caught earlier!");
+ return VarMapEntry-1;
+ }
+
+ /// GetInstPatternNode - Get the pattern for an instruction.
+ const TreePatternNode *GetInstPatternNode(const DAGInstruction &Ins,
+ const TreePatternNode *N);
+
+ void EmitResultOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultOfNamedOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultLeafAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultInstructionAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ };
+
+} // end anon namespace.
+
+MatcherGen::MatcherGen(const PatternToMatch &pattern,
+ const CodeGenDAGPatterns &cgp)
+: Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0),
+ TheMatcher(0), CurPredicate(0) {
+ // We need to produce the matcher tree for the patterns source pattern. To do
+ // this we need to match the structure as well as the types. To do the type
+ // matching, we want to figure out the fewest number of type checks we need to
+ // emit. For example, if there is only one integer type supported by a
+ // target, there should be no type comparisons at all for integer patterns!
+ //
+ // To figure out the fewest number of type checks needed, clone the pattern,
+ // remove the types, then perform type inference on the pattern as a whole.
+ // If there are unresolved types, emit an explicit check for those types,
+ // apply the type to the tree, then rerun type inference. Iterate until all
+ // types are resolved.
+ //
+ PatWithNoTypes = Pattern.getSrcPattern()->clone();
+ PatWithNoTypes->RemoveAllTypes();
+
+ // If there are types that are manifestly known, infer them.
+ InferPossibleTypes();
+}
+
+/// InferPossibleTypes - As we emit the pattern, we end up generating type
+/// checks and applying them to the 'PatWithNoTypes' tree. As we do this, we
+/// want to propagate implied types as far throughout the tree as possible so
+/// that we avoid doing redundant type checks. This does the type propagation.
+void MatcherGen::InferPossibleTypes() {
+ // TP - Get *SOME* tree pattern, we don't care which. It is only used for
+ // diagnostics, which we know are impossible at this point.
+ TreePattern &TP = *CGP.pf_begin()->second;
+
+ try {
+ bool MadeChange = true;
+ while (MadeChange)
+ MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP,
+ true/*Ignore reg constraints*/);
+ } catch (...) {
+ errs() << "Type constraint application shouldn't fail!";
+ abort();
+ }
+}
+
+
+/// AddMatcher - Add a matcher node to the current graph we're building.
+void MatcherGen::AddMatcher(Matcher *NewNode) {
+ if (CurPredicate != 0)
+ CurPredicate->setNext(NewNode);
+ else
+ TheMatcher = NewNode;
+ CurPredicate = NewNode;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Pattern Match Generation
+//===----------------------------------------------------------------------===//
+
+/// EmitLeafMatchCode - Generate matching code for leaf nodes.
+void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
+ assert(N->isLeaf() && "Not a leaf?");
+
+ // Direct match against an integer constant.
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
+ // If this is the root of the dag we're matching, we emit a redundant opcode
+ // check to ensure that this gets folded into the normal top-level
+ // OpcodeSwitch.
+ if (N == Pattern.getSrcPattern()) {
+ const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("imm"));
+ AddMatcher(new CheckOpcodeMatcher(NI));
+ }
+
+ return AddMatcher(new CheckIntegerMatcher(II->getValue()));
+ }
+
+ DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue());
+ if (DI == 0) {
+ errs() << "Unknown leaf kind: " << *DI << "\n";
+ abort();
+ }
+
+ Record *LeafRec = DI->getDef();
+ if (// Handle register references. Nothing to do here, they always match.
+ LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->isSubClassOf("PointerLikeRegClass") ||
+ // Place holder for SRCVALUE nodes. Nothing to do here.
+ LeafRec->getName() == "srcvalue")
+ return;
+
+ // If we have a physreg reference like (mul gpr:$src, EAX) then we need to
+ // record the register
+ if (LeafRec->isSubClassOf("Register")) {
+ AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName(),
+ NextRecordedOperandNo));
+ PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++));
+ return;
+ }
+
+ if (LeafRec->isSubClassOf("ValueType"))
+ return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName()));
+
+ if (LeafRec->isSubClassOf("CondCode"))
+ return AddMatcher(new CheckCondCodeMatcher(LeafRec->getName()));
+
+ if (LeafRec->isSubClassOf("ComplexPattern")) {
+ // We can't model ComplexPattern uses that don't have their name taken yet.
+ // The OPC_CheckComplexPattern operation implicitly records the results.
+ if (N->getName().empty()) {
+ errs() << "We expect complex pattern uses to have names: " << *N << "\n";
+ exit(1);
+ }
+
+ // Remember this ComplexPattern so that we can emit it after all the other
+ // structural matches are done.
+ MatchedComplexPatterns.push_back(std::make_pair(N, 0));
+ return;
+ }
+
+ errs() << "Unknown leaf kind: " << *N << "\n";
+ abort();
+}
+
+void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes) {
+ assert(!N->isLeaf() && "Not an operator?");
+ const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator());
+
+ // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
+ // a constant without a predicate fn that has more that one bit set, handle
+ // this as a special case. This is usually for targets that have special
+ // handling of certain large constants (e.g. alpha with it's 8/16/32-bit
+ // handling stuff). Using these instructions is often far more efficient
+ // than materializing the constant. Unfortunately, both the instcombiner
+ // and the dag combiner can often infer that bits are dead, and thus drop
+ // them from the mask in the dag. For example, it might turn 'AND X, 255'
+ // into 'AND X, 254' if it knows the low bit is set. Emit code that checks
+ // to handle this.
+ if ((N->getOperator()->getName() == "and" ||
+ N->getOperator()->getName() == "or") &&
+ N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() &&
+ N->getPredicateFns().empty()) {
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
+ if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
+ // If this is at the root of the pattern, we emit a redundant
+ // CheckOpcode so that the following checks get factored properly under
+ // a single opcode check.
+ if (N == Pattern.getSrcPattern())
+ AddMatcher(new CheckOpcodeMatcher(CInfo));
+
+ // Emit the CheckAndImm/CheckOrImm node.
+ if (N->getOperator()->getName() == "and")
+ AddMatcher(new CheckAndImmMatcher(II->getValue()));
+ else
+ AddMatcher(new CheckOrImmMatcher(II->getValue()));
+
+ // Match the LHS of the AND as appropriate.
+ AddMatcher(new MoveChildMatcher(0));
+ EmitMatchCode(N->getChild(0), NodeNoTypes->getChild(0));
+ AddMatcher(new MoveParentMatcher());
+ return;
+ }
+ }
+ }
+
+ // Check that the current opcode lines up.
+ AddMatcher(new CheckOpcodeMatcher(CInfo));
+
+ // If this node has memory references (i.e. is a load or store), tell the
+ // interpreter to capture them in the memref array.
+ if (N->NodeHasProperty(SDNPMemOperand, CGP))
+ AddMatcher(new RecordMemRefMatcher());
+
+ // If this node has a chain, then the chain is operand #0 is the SDNode, and
+ // the child numbers of the node are all offset by one.
+ unsigned OpNo = 0;
+ if (N->NodeHasProperty(SDNPHasChain, CGP)) {
+ // Record the node and remember it in our chained nodes list.
+ AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
+ "' chained node",
+ NextRecordedOperandNo));
+ // Remember all of the input chains our pattern will match.
+ MatchedChainNodes.push_back(NextRecordedOperandNo++);
+
+ // Don't look at the input chain when matching the tree pattern to the
+ // SDNode.
+ OpNo = 1;
+
+ // If this node is not the root and the subtree underneath it produces a
+ // chain, then the result of matching the node is also produce a chain.
+ // Beyond that, this means that we're also folding (at least) the root node
+ // into the node that produce the chain (for example, matching
+ // "(add reg, (load ptr))" as a add_with_memory on X86). This is
+ // problematic, if the 'reg' node also uses the load (say, its chain).
+ // Graphically:
+ //
+ // [LD]
+ // ^ ^
+ // | \ DAG's like cheese.
+ // / |
+ // / [YY]
+ // | ^
+ // [XX]--/
+ //
+ // It would be invalid to fold XX and LD. In this case, folding the two
+ // nodes together would induce a cycle in the DAG, making it a 'cyclic DAG'
+ // To prevent this, we emit a dynamic check for legality before allowing
+ // this to be folded.
+ //
+ const TreePatternNode *Root = Pattern.getSrcPattern();
+ if (N != Root) { // Not the root of the pattern.
+ // If there is a node between the root and this node, then we definitely
+ // need to emit the check.
+ bool NeedCheck = !Root->hasChild(N);
+
+ // If it *is* an immediate child of the root, we can still need a check if
+ // the root SDNode has multiple inputs. For us, this means that it is an
+ // intrinsic, has multiple operands, or has other inputs like chain or
+ // flag).
+ if (!NeedCheck) {
+ const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator());
+ NeedCheck =
+ Root->getOperator() == CGP.get_intrinsic_void_sdnode() ||
+ Root->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
+ Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
+ PInfo.getNumOperands() > 1 ||
+ PInfo.hasProperty(SDNPHasChain) ||
+ PInfo.hasProperty(SDNPInFlag) ||
+ PInfo.hasProperty(SDNPOptInFlag);
+ }
+
+ if (NeedCheck)
+ AddMatcher(new CheckFoldableChainNodeMatcher());
+ }
+ }
+
+ // If this node has an output flag and isn't the root, remember it.
+ if (N->NodeHasProperty(SDNPOutFlag, CGP) &&
+ N != Pattern.getSrcPattern()) {
+ // TODO: This redundantly records nodes with both flags and chains.
+
+ // Record the node and remember it in our chained nodes list.
+ AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
+ "' flag output node",
+ NextRecordedOperandNo));
+ // Remember all of the nodes with output flags our pattern will match.
+ MatchedFlagResultNodes.push_back(NextRecordedOperandNo++);
+ }
+
+ // If this node is known to have an input flag or if it *might* have an input
+ // flag, capture it as the flag input of the pattern.
+ if (N->NodeHasProperty(SDNPOptInFlag, CGP) ||
+ N->NodeHasProperty(SDNPInFlag, CGP))
+ AddMatcher(new CaptureFlagInputMatcher());
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
+ // Get the code suitable for matching this child. Move to the child, check
+ // it then move back to the parent.
+ AddMatcher(new MoveChildMatcher(OpNo));
+ EmitMatchCode(N->getChild(i), NodeNoTypes->getChild(i));
+ AddMatcher(new MoveParentMatcher());
+ }
+}
+
+
+void MatcherGen::EmitMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes) {
+ // If N and NodeNoTypes don't agree on a type, then this is a case where we
+ // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and
+ // reinfer any correlated types.
+ unsigned NodeType = EEVT::isUnknown;
+ if (NodeNoTypes->getExtTypes() != N->getExtTypes()) {
+ NodeType = N->getTypeNum(0);
+ NodeNoTypes->setTypes(N->getExtTypes());
+ InferPossibleTypes();
+ }
+
+ // If this node has a name associated with it, capture it in VariableMap. If
+ // we already saw this in the pattern, emit code to verify dagness.
+ if (!N->getName().empty()) {
+ unsigned &VarMapEntry = VariableMap[N->getName()];
+ if (VarMapEntry == 0) {
+ // If it is a named node, we must emit a 'Record' opcode.
+ AddMatcher(new RecordMatcher("$" + N->getName(), NextRecordedOperandNo));
+ VarMapEntry = ++NextRecordedOperandNo;
+ } else {
+ // If we get here, this is a second reference to a specific name. Since
+ // we already have checked that the first reference is valid, we don't
+ // have to recursively match it, just check that it's the same as the
+ // previously named thing.
+ AddMatcher(new CheckSameMatcher(VarMapEntry-1));
+ return;
+ }
+ }
+
+ if (N->isLeaf())
+ EmitLeafMatchCode(N);
+ else
+ EmitOperatorMatchCode(N, NodeNoTypes);
+
+ // If there are node predicates for this node, generate their checks.
+ for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
+ AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
+
+ if (NodeType != EEVT::isUnknown)
+ AddMatcher(new CheckTypeMatcher((MVT::SimpleValueType)NodeType));
+}
+
+/// EmitMatcherCode - Generate the code that matches the predicate of this
+/// pattern for the specified Variant. If the variant is invalid this returns
+/// true and does not generate code, if it is valid, it returns false.
+bool MatcherGen::EmitMatcherCode(unsigned Variant) {
+ // If the root of the pattern is a ComplexPattern and if it is specified to
+ // match some number of root opcodes, these are considered to be our variants.
+ // Depending on which variant we're generating code for, emit the root opcode
+ // check.
+ if (const ComplexPattern *CP =
+ Pattern.getSrcPattern()->getComplexPatternInfo(CGP)) {
+ const std::vector<Record*> &OpNodes = CP->getRootNodes();
+ assert(!OpNodes.empty() &&"Complex Pattern must specify what it can match");
+ if (Variant >= OpNodes.size()) return true;
+
+ AddMatcher(new CheckOpcodeMatcher(CGP.getSDNodeInfo(OpNodes[Variant])));
+ } else {
+ if (Variant != 0) return true;
+ }
+
+ // Emit the matcher for the pattern structure and types.
+ EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes);
+
+ // If the pattern has a predicate on it (e.g. only enabled when a subtarget
+ // feature is around, do the check).
+ if (!Pattern.getPredicateCheck().empty())
+ AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck()));
+
+ // Now that we've completed the structural type match, emit any ComplexPattern
+ // checks (e.g. addrmode matches). We emit this after the structural match
+ // because they are generally more expensive to evaluate and more difficult to
+ // factor.
+ for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) {
+ const TreePatternNode *N = MatchedComplexPatterns[i].first;
+
+ // Remember where the results of this match get stuck.
+ MatchedComplexPatterns[i].second = NextRecordedOperandNo;
+
+ // Get the slot we recorded the value in from the name on the node.
+ unsigned RecNodeEntry = VariableMap[N->getName()];
+ assert(!N->getName().empty() && RecNodeEntry &&
+ "Complex pattern should have a name and slot");
+ --RecNodeEntry; // Entries in VariableMap are biased.
+
+ const ComplexPattern &CP =
+ CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef());
+
+ // Emit a CheckComplexPat operation, which does the match (aborting if it
+ // fails) and pushes the matched operands onto the recorded nodes list.
+ AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry,
+ N->getName(), NextRecordedOperandNo));
+
+ // Record the right number of operands.
+ NextRecordedOperandNo += CP.getNumOperands();
+ if (CP.hasProperty(SDNPHasChain)) {
+ // If the complex pattern has a chain, then we need to keep track of the
+ // fact that we just recorded a chain input. The chain input will be
+ // matched as the last operand of the predicate if it was successful.
+ ++NextRecordedOperandNo; // Chained node operand.
+
+ // It is the last operand recorded.
+ assert(NextRecordedOperandNo > 1 &&
+ "Should have recorded input/result chains at least!");
+ MatchedChainNodes.push_back(NextRecordedOperandNo-1);
+ }
+
+ // TODO: Complex patterns can't have output flags, if they did, we'd want
+ // to record them.
+ }
+
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Node Result Generation
+//===----------------------------------------------------------------------===//
+
+void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps){
+ assert(!N->getName().empty() && "Operand not named!");
+
+ // A reference to a complex pattern gets all of the results of the complex
+ // pattern's match.
+ if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) {
+ unsigned SlotNo = 0;
+ for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i)
+ if (MatchedComplexPatterns[i].first->getName() == N->getName()) {
+ SlotNo = MatchedComplexPatterns[i].second;
+ break;
+ }
+ assert(SlotNo != 0 && "Didn't get a slot number assigned?");
+
+ // The first slot entry is the node itself, the subsequent entries are the
+ // matched values.
+ for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
+ ResultOps.push_back(SlotNo+i);
+ return;
+ }
+
+ unsigned SlotNo = getNamedArgumentSlot(N->getName());
+
+ // If this is an 'imm' or 'fpimm' node, make sure to convert it to the target
+ // version of the immediate so that it doesn't get selected due to some other
+ // node use.
+ if (!N->isLeaf()) {
+ StringRef OperatorName = N->getOperator()->getName();
+ if (OperatorName == "imm" || OperatorName == "fpimm") {
+ AddMatcher(new EmitConvertToTargetMatcher(SlotNo));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+ }
+
+ ResultOps.push_back(SlotNo);
+}
+
+void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ assert(N->isLeaf() && "Must be a leaf");
+
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
+ AddMatcher(new EmitIntegerMatcher(II->getValue(),N->getTypeNum(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ // If this is an explicit register reference, handle it.
+ if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
+ if (DI->getDef()->isSubClassOf("Register")) {
+ AddMatcher(new EmitRegisterMatcher(DI->getDef(),
+ N->getTypeNum(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ if (DI->getDef()->getName() == "zero_reg") {
+ AddMatcher(new EmitRegisterMatcher(0, N->getTypeNum(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ // Handle a reference to a register class. This is used
+ // in COPY_TO_SUBREG instructions.
+ if (DI->getDef()->isSubClassOf("RegisterClass")) {
+ std::string Value = getQualifiedName(DI->getDef()) + "RegClassID";
+ AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+ }
+
+ errs() << "unhandled leaf node: \n";
+ N->dump();
+}
+
+/// GetInstPatternNode - Get the pattern for an instruction.
+///
+const TreePatternNode *MatcherGen::
+GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) {
+ const TreePattern *InstPat = Inst.getPattern();
+
+ // FIXME2?: Assume actual pattern comes before "implicit".
+ TreePatternNode *InstPatNode;
+ if (InstPat)
+ InstPatNode = InstPat->getTree(0);
+ else if (/*isRoot*/ N == Pattern.getDstPattern())
+ InstPatNode = Pattern.getSrcPattern();
+ else
+ return 0;
+
+ if (InstPatNode && !InstPatNode->isLeaf() &&
+ InstPatNode->getOperator()->getName() == "set")
+ InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
+
+ return InstPatNode;
+}
+
+void MatcherGen::
+EmitResultInstructionAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &OutputOps) {
+ Record *Op = N->getOperator();
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(Op->getName());
+ const DAGInstruction &Inst = CGP.getInstruction(Op);
+
+ // If we can, get the pattern for the instruction we're generating. We derive
+ // a variety of information from this pattern, such as whether it has a chain.
+ //
+ // FIXME2: This is extremely dubious for several reasons, not the least of
+ // which it gives special status to instructions with patterns that Pat<>
+ // nodes can't duplicate.
+ const TreePatternNode *InstPatNode = GetInstPatternNode(Inst, N);
+
+ // NodeHasChain - Whether the instruction node we're creating takes chains.
+ bool NodeHasChain = InstPatNode &&
+ InstPatNode->TreeHasProperty(SDNPHasChain, CGP);
+
+ bool isRoot = N == Pattern.getDstPattern();
+
+ // TreeHasOutFlag - True if this tree has a flag.
+ bool TreeHasInFlag = false, TreeHasOutFlag = false;
+ if (isRoot) {
+ const TreePatternNode *SrcPat = Pattern.getSrcPattern();
+ TreeHasInFlag = SrcPat->TreeHasProperty(SDNPOptInFlag, CGP) ||
+ SrcPat->TreeHasProperty(SDNPInFlag, CGP);
+
+ // FIXME2: this is checking the entire pattern, not just the node in
+ // question, doing this just for the root seems like a total hack.
+ TreeHasOutFlag = SrcPat->TreeHasProperty(SDNPOutFlag, CGP);
+ }
+
+ // NumResults - This is the number of results produced by the instruction in
+ // the "outs" list.
+ unsigned NumResults = Inst.getNumResults();
+
+ // Loop over all of the operands of the instruction pattern, emitting code
+ // to fill them all in. The node 'N' usually has number children equal to
+ // the number of input operands of the instruction. However, in cases
+ // where there are predicate operands for an instruction, we need to fill
+ // in the 'execute always' values. Match up the node operands to the
+ // instruction operands to do this.
+ SmallVector<unsigned, 8> InstOps;
+ for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.OperandList.size();
+ InstOpNo != e; ++InstOpNo) {
+
+ // 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()) {
+ // This is a predicate or optional def operand; emit the
+ // 'default ops' operands.
+ const DAGDefaultOperand &DefaultOp =
+ CGP.getDefaultOperand(II.OperandList[InstOpNo].Rec);
+ for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i)
+ EmitResultOperand(DefaultOp.DefaultOps[i], InstOps);
+ continue;
+ }
+
+ // Otherwise this is a normal operand or a predicate operand without
+ // 'execute always'; emit it.
+ EmitResultOperand(N->getChild(ChildNo), InstOps);
+ ++ChildNo;
+ }
+
+ // If this node has an input flag or explicitly specified input physregs, we
+ // need to add chained and flagged copyfromreg nodes and materialize the flag
+ // input.
+ if (isRoot && !PhysRegInputs.empty()) {
+ // Emit all of the CopyToReg nodes for the input physical registers. These
+ // occur in patterns like (mul:i8 AL:i8, GR8:i8:$src).
+ for (unsigned i = 0, e = PhysRegInputs.size(); i != e; ++i)
+ AddMatcher(new EmitCopyToRegMatcher(PhysRegInputs[i].second,
+ PhysRegInputs[i].first));
+ // Even if the node has no other flag inputs, the resultant node must be
+ // flagged to the CopyFromReg nodes we just generated.
+ TreeHasInFlag = true;
+ }
+
+ // Result order: node results, chain, flags
+
+ // Determine the result types.
+ SmallVector<MVT::SimpleValueType, 4> ResultVTs;
+ if (NumResults != 0 && N->getTypeNum(0) != MVT::isVoid) {
+ // FIXME2: If the node has multiple results, we should add them. For now,
+ // preserve existing behavior?!
+ ResultVTs.push_back(N->getTypeNum(0));
+ }
+
+
+ // If this is the root instruction of a pattern that has physical registers in
+ // its result pattern, add output VTs for them. For example, X86 has:
+ // (set AL, (mul ...))
+ // This also handles implicit results like:
+ // (implicit EFLAGS)
+ if (isRoot && Pattern.getDstRegs().size() != 0) {
+ for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i)
+ if (Pattern.getDstRegs()[i]->isSubClassOf("Register"))
+ ResultVTs.push_back(getRegisterValueType(Pattern.getDstRegs()[i], CGT));
+ }
+
+ // FIXME2: Instead of using the isVariadic flag on the instruction, we should
+ // have an SDNP that indicates variadicism. The TargetInstrInfo isVariadic
+ // property should be inferred from this when an instruction has a pattern.
+ int NumFixedArityOperands = -1;
+ if (isRoot && II.isVariadic)
+ NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren();
+
+ // If this is the root node and any of the nodes matched nodes in the input
+ // pattern have MemRefs in them, have the interpreter collect them and plop
+ // them onto this node.
+ //
+ // FIXME3: This is actively incorrect for result patterns where the root of
+ // the pattern is not the memory reference and is also incorrect when the
+ // result pattern has multiple memory-referencing instructions. For example,
+ // in the X86 backend, this pattern causes the memrefs to get attached to the
+ // CVTSS2SDrr instead of the MOVSSrm:
+ //
+ // def : Pat<(extloadf32 addr:$src),
+ // (CVTSS2SDrr (MOVSSrm addr:$src))>;
+ //
+ bool NodeHasMemRefs =
+ isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
+
+ AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(),
+ ResultVTs.data(), ResultVTs.size(),
+ InstOps.data(), InstOps.size(),
+ NodeHasChain, TreeHasInFlag, TreeHasOutFlag,
+ NodeHasMemRefs, NumFixedArityOperands,
+ NextRecordedOperandNo));
+
+ // The non-chain and non-flag results of the newly emitted node get recorded.
+ for (unsigned i = 0, e = ResultVTs.size(); i != e; ++i) {
+ if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Flag) break;
+ OutputOps.push_back(NextRecordedOperandNo++);
+ }
+}
+
+void MatcherGen::
+EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ assert(N->getOperator()->isSubClassOf("SDNodeXForm") && "Not SDNodeXForm?");
+
+ // Emit the operand.
+ SmallVector<unsigned, 8> InputOps;
+
+ // FIXME2: Could easily generalize this to support multiple inputs and outputs
+ // to the SDNodeXForm. For now we just support one input and one output like
+ // the old instruction selector.
+ assert(N->getNumChildren() == 1);
+ EmitResultOperand(N->getChild(0), InputOps);
+
+ // The input currently must have produced exactly one result.
+ assert(InputOps.size() == 1 && "Unexpected input to SDNodeXForm");
+
+ AddMatcher(new EmitNodeXFormMatcher(InputOps[0], N->getOperator()));
+ ResultOps.push_back(NextRecordedOperandNo++);
+}
+
+void MatcherGen::EmitResultOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ // This is something selected from the pattern we matched.
+ if (!N->getName().empty())
+ return EmitResultOfNamedOperand(N, ResultOps);
+
+ if (N->isLeaf())
+ return EmitResultLeafAsOperand(N, ResultOps);
+
+ Record *OpRec = N->getOperator();
+ if (OpRec->isSubClassOf("Instruction"))
+ return EmitResultInstructionAsOperand(N, ResultOps);
+ if (OpRec->isSubClassOf("SDNodeXForm"))
+ return EmitResultSDNodeXFormAsOperand(N, ResultOps);
+ errs() << "Unknown result node to emit code for: " << *N << '\n';
+ throw std::string("Unknown node in result pattern!");
+}
+
+void MatcherGen::EmitResultCode() {
+ // Patterns that match nodes with (potentially multiple) chain inputs have to
+ // merge them together into a token factor. This informs the generated code
+ // what all the chained nodes are.
+ if (!MatchedChainNodes.empty())
+ AddMatcher(new EmitMergeInputChainsMatcher
+ (MatchedChainNodes.data(), MatchedChainNodes.size()));
+
+ // Codegen the root of the result pattern, capturing the resulting values.
+ SmallVector<unsigned, 8> Ops;
+ EmitResultOperand(Pattern.getDstPattern(), Ops);
+
+ // At this point, we have however many values the result pattern produces.
+ // However, the input pattern might not need all of these. If there are
+ // excess values at the end (such as condition codes etc) just lop them off.
+ // This doesn't need to worry about flags or chains, just explicit results.
+ //
+ // FIXME2: This doesn't work because there is currently no way to get an
+ // accurate count of the # results the source pattern sets. This is because
+ // of the "parallel" construct in X86 land, which looks like this:
+ //
+ //def : Pat<(parallel (X86and_flag GR8:$src1, GR8:$src2),
+ // (implicit EFLAGS)),
+ // (AND8rr GR8:$src1, GR8:$src2)>;
+ //
+ // This idiom means to match the two-result node X86and_flag (which is
+ // declared as returning a single result, because we can't match multi-result
+ // nodes yet). In this case, we would have to know that the input has two
+ // results. However, mul8r is modelled exactly the same way, but without
+ // implicit defs included. The fix is to support multiple results directly
+ // and eliminate 'parallel'.
+ //
+ // FIXME2: When this is fixed, we should revert the terrible hack in the
+ // OPC_EmitNode code in the interpreter.
+#if 0
+ const TreePatternNode *Src = Pattern.getSrcPattern();
+ unsigned NumSrcResults = Src->getTypeNum(0) != MVT::isVoid ? 1 : 0;
+ NumSrcResults += Pattern.getDstRegs().size();
+ assert(Ops.size() >= NumSrcResults && "Didn't provide enough results");
+ Ops.resize(NumSrcResults);
+#endif
+
+ // If the matched pattern covers nodes which define a flag result, emit a node
+ // that tells the matcher about them so that it can update their results.
+ if (!MatchedFlagResultNodes.empty())
+ AddMatcher(new MarkFlagResultsMatcher(MatchedFlagResultNodes.data(),
+ MatchedFlagResultNodes.size()));
+
+ AddMatcher(new CompleteMatchMatcher(Ops.data(), Ops.size(), Pattern));
+}
+
+
+/// ConvertPatternToMatcher - Create the matcher for the specified pattern with
+/// the specified variant. If the variant number is invalid, this returns null.
+Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,
+ unsigned Variant,
+ const CodeGenDAGPatterns &CGP) {
+ MatcherGen Gen(Pattern, CGP);
+
+ // Generate the code for the matcher.
+ if (Gen.EmitMatcherCode(Variant))
+ return 0;
+
+ // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence.
+ // FIXME2: Split result code out to another table, and make the matcher end
+ // with an "Emit <index>" command. This allows result generation stuff to be
+ // shared and factored?
+
+ // If the match succeeds, then we generate Pattern.
+ Gen.EmitResultCode();
+
+ // Unconditional match.
+ return Gen.GetMatcher();
+}
+
+
+
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
new file mode 100644
index 0000000..910c4c5
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -0,0 +1,509 @@
+//===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DAG Matcher optimizer.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "isel-opt"
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+using namespace llvm;
+
+/// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
+/// into single compound nodes like RecordChild.
+static void ContractNodes(OwningPtr<Matcher> &MatcherPtr,
+ const CodeGenDAGPatterns &CGP) {
+ // If we reached the end of the chain, we're done.
+ Matcher *N = MatcherPtr.get();
+ if (N == 0) return;
+
+ // If we have a scope node, walk down all of the children.
+ if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {
+ for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
+ OwningPtr<Matcher> Child(Scope->takeChild(i));
+ ContractNodes(Child, CGP);
+ Scope->resetChild(i, Child.take());
+ }
+ return;
+ }
+
+ // If we found a movechild node with a node that comes in a 'foochild' form,
+ // transform it.
+ if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) {
+ Matcher *New = 0;
+ if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext()))
+ New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),
+ RM->getResultNo());
+
+ if (CheckTypeMatcher *CT= dyn_cast<CheckTypeMatcher>(MC->getNext()))
+ New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());
+
+ if (New) {
+ // Insert the new node.
+ New->setNext(MatcherPtr.take());
+ MatcherPtr.reset(New);
+ // Remove the old one.
+ MC->setNext(MC->getNext()->takeNext());
+ return ContractNodes(MatcherPtr, CGP);
+ }
+ }
+
+ // Zap movechild -> moveparent.
+ if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N))
+ if (MoveParentMatcher *MP =
+ dyn_cast<MoveParentMatcher>(MC->getNext())) {
+ MatcherPtr.reset(MP->takeNext());
+ return ContractNodes(MatcherPtr, CGP);
+ }
+
+ // Turn EmitNode->MarkFlagResults->CompleteMatch into
+ // MarkFlagResults->EmitNode->CompleteMatch when we can to encourage
+ // MorphNodeTo formation. This is safe because MarkFlagResults never refers
+ // to the root of the pattern.
+ if (isa<EmitNodeMatcher>(N) && isa<MarkFlagResultsMatcher>(N->getNext()) &&
+ isa<CompleteMatchMatcher>(N->getNext()->getNext())) {
+ // Unlink the two nodes from the list.
+ Matcher *EmitNode = MatcherPtr.take();
+ Matcher *MFR = EmitNode->takeNext();
+ Matcher *Tail = MFR->takeNext();
+
+ // Relink them.
+ MatcherPtr.reset(MFR);
+ MFR->setNext(EmitNode);
+ EmitNode->setNext(Tail);
+ return ContractNodes(MatcherPtr, CGP);
+ }
+
+ // Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
+ if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))
+ if (CompleteMatchMatcher *CM =
+ dyn_cast<CompleteMatchMatcher>(EN->getNext())) {
+ // We can only use MorphNodeTo if the result values match up.
+ unsigned RootResultFirst = EN->getFirstResultSlot();
+ bool ResultsMatch = true;
+ for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
+ if (CM->getResult(i) != RootResultFirst+i)
+ ResultsMatch = false;
+
+ // If the selected node defines a subset of the flag/chain results, we
+ // can't use MorphNodeTo. For example, we can't use MorphNodeTo if the
+ // matched pattern has a chain but the root node doesn't.
+ const PatternToMatch &Pattern = CM->getPattern();
+
+ if (!EN->hasChain() &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP))
+ ResultsMatch = false;
+
+ // If the matched node has a flag and the output root doesn't, we can't
+ // use MorphNodeTo.
+ //
+ // NOTE: Strictly speaking, we don't have to check for the flag here
+ // because the code in the pattern generator doesn't handle it right. We
+ // do it anyway for thoroughness.
+ if (!EN->hasOutFlag() &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPOutFlag, CGP))
+ ResultsMatch = false;
+
+
+ // If the root result node defines more results than the source root node
+ // *and* has a chain or flag input, then we can't match it because it
+ // would end up replacing the extra result with the chain/flag.
+#if 0
+ if ((EN->hasFlag() || EN->hasChain()) &&
+ EN->getNumNonChainFlagVTs() > ... need to get no results reliably ...)
+ ResultMatch = false;
+#endif
+
+ if (ResultsMatch) {
+ const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList();
+ const SmallVectorImpl<unsigned> &Operands = EN->getOperandList();
+ MatcherPtr.reset(new MorphNodeToMatcher(EN->getOpcodeName(),
+ VTs.data(), VTs.size(),
+ Operands.data(),Operands.size(),
+ EN->hasChain(), EN->hasInFlag(),
+ EN->hasOutFlag(),
+ EN->hasMemRefs(),
+ EN->getNumFixedArityOperands(),
+ Pattern));
+ return;
+ }
+
+ // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode
+ // variants.
+ }
+
+ ContractNodes(N->getNextPtr(), CGP);
+
+
+ // If we have a CheckType/CheckChildType/Record node followed by a
+ // CheckOpcode, invert the two nodes. We prefer to do structural checks
+ // before type checks, as this opens opportunities for factoring on targets
+ // like X86 where many operations are valid on multiple types.
+ if ((isa<CheckTypeMatcher>(N) || isa<CheckChildTypeMatcher>(N) ||
+ isa<RecordMatcher>(N)) &&
+ isa<CheckOpcodeMatcher>(N->getNext())) {
+ // Unlink the two nodes from the list.
+ Matcher *CheckType = MatcherPtr.take();
+ Matcher *CheckOpcode = CheckType->takeNext();
+ Matcher *Tail = CheckOpcode->takeNext();
+
+ // Relink them.
+ MatcherPtr.reset(CheckOpcode);
+ CheckOpcode->setNext(CheckType);
+ CheckType->setNext(Tail);
+ return ContractNodes(MatcherPtr, CGP);
+ }
+}
+
+/// SinkPatternPredicates - Pattern predicates can be checked at any level of
+/// the matching tree. The generator dumps them at the top level of the pattern
+/// though, which prevents factoring from being able to see past them. This
+/// optimization sinks them as far down into the pattern as possible.
+///
+/// Conceptually, we'd like to sink these predicates all the way to the last
+/// matcher predicate in the series. However, it turns out that some
+/// ComplexPatterns have side effects on the graph, so we really don't want to
+/// run a the complex pattern if the pattern predicate will fail. For this
+/// reason, we refuse to sink the pattern predicate past a ComplexPattern.
+///
+static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) {
+ // Recursively scan for a PatternPredicate.
+ // If we reached the end of the chain, we're done.
+ Matcher *N = MatcherPtr.get();
+ if (N == 0) return;
+
+ // Walk down all members of a scope node.
+ if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {
+ for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
+ OwningPtr<Matcher> Child(Scope->takeChild(i));
+ SinkPatternPredicates(Child);
+ Scope->resetChild(i, Child.take());
+ }
+ return;
+ }
+
+ // If this node isn't a CheckPatternPredicateMatcher we keep scanning until
+ // we find one.
+ CheckPatternPredicateMatcher *CPPM =dyn_cast<CheckPatternPredicateMatcher>(N);
+ if (CPPM == 0)
+ return SinkPatternPredicates(N->getNextPtr());
+
+ // Ok, we found one, lets try to sink it. Check if we can sink it past the
+ // next node in the chain. If not, we won't be able to change anything and
+ // might as well bail.
+ if (!CPPM->getNext()->isSafeToReorderWithPatternPredicate())
+ return;
+
+ // Okay, we know we can sink it past at least one node. Unlink it from the
+ // chain and scan for the new insertion point.
+ MatcherPtr.take(); // Don't delete CPPM.
+ MatcherPtr.reset(CPPM->takeNext());
+
+ N = MatcherPtr.get();
+ while (N->getNext()->isSafeToReorderWithPatternPredicate())
+ N = N->getNext();
+
+ // At this point, we want to insert CPPM after N.
+ CPPM->setNext(N->takeNext());
+ N->setNext(CPPM);
+}
+
+/// FindNodeWithKind - Scan a series of matchers looking for a matcher with a
+/// specified kind. Return null if we didn't find one otherwise return the
+/// matcher.
+static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) {
+ for (; M; M = M->getNext())
+ if (M->getKind() == Kind)
+ return M;
+ return 0;
+}
+
+
+/// FactorNodes - Turn matches like this:
+/// Scope
+/// OPC_CheckType i32
+/// ABC
+/// OPC_CheckType i32
+/// XYZ
+/// into:
+/// OPC_CheckType i32
+/// Scope
+/// ABC
+/// XYZ
+///
+static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) {
+ // If we reached the end of the chain, we're done.
+ Matcher *N = MatcherPtr.get();
+ if (N == 0) return;
+
+ // If this is not a push node, just scan for one.
+ ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N);
+ if (Scope == 0)
+ return FactorNodes(N->getNextPtr());
+
+ // Okay, pull together the children of the scope node into a vector so we can
+ // inspect it more easily. While we're at it, bucket them up by the hash
+ // code of their first predicate.
+ SmallVector<Matcher*, 32> OptionsToMatch;
+
+ for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
+ // Factor the subexpression.
+ OwningPtr<Matcher> Child(Scope->takeChild(i));
+ FactorNodes(Child);
+
+ if (Matcher *N = Child.take())
+ OptionsToMatch.push_back(N);
+ }
+
+ SmallVector<Matcher*, 32> NewOptionsToMatch;
+
+ // Loop over options to match, merging neighboring patterns with identical
+ // starting nodes into a shared matcher.
+ for (unsigned OptionIdx = 0, e = OptionsToMatch.size(); OptionIdx != e;) {
+ // Find the set of matchers that start with this node.
+ Matcher *Optn = OptionsToMatch[OptionIdx++];
+
+ if (OptionIdx == e) {
+ NewOptionsToMatch.push_back(Optn);
+ continue;
+ }
+
+ // See if the next option starts with the same matcher. If the two
+ // neighbors *do* start with the same matcher, we can factor the matcher out
+ // of at least these two patterns. See what the maximal set we can merge
+ // together is.
+ SmallVector<Matcher*, 8> EqualMatchers;
+ EqualMatchers.push_back(Optn);
+
+ // Factor all of the known-equal matchers after this one into the same
+ // group.
+ while (OptionIdx != e && OptionsToMatch[OptionIdx]->isEqual(Optn))
+ EqualMatchers.push_back(OptionsToMatch[OptionIdx++]);
+
+ // If we found a non-equal matcher, see if it is contradictory with the
+ // current node. If so, we know that the ordering relation between the
+ // current sets of nodes and this node don't matter. Look past it to see if
+ // we can merge anything else into this matching group.
+ unsigned Scan = OptionIdx;
+ while (1) {
+ // If we ran out of stuff to scan, we're done.
+ if (Scan == e) break;
+
+ Matcher *ScanMatcher = OptionsToMatch[Scan];
+
+ // If we found an entry that matches out matcher, merge it into the set to
+ // handle.
+ if (Optn->isEqual(ScanMatcher)) {
+ // If is equal after all, add the option to EqualMatchers and remove it
+ // from OptionsToMatch.
+ EqualMatchers.push_back(ScanMatcher);
+ OptionsToMatch.erase(OptionsToMatch.begin()+Scan);
+ --e;
+ continue;
+ }
+
+ // If the option we're checking for contradicts the start of the list,
+ // skip over it.
+ if (Optn->isContradictory(ScanMatcher)) {
+ ++Scan;
+ continue;
+ }
+
+ // If we're scanning for a simple node, see if it occurs later in the
+ // sequence. If so, and if we can move it up, it might be contradictory
+ // or the same as what we're looking for. If so, reorder it.
+ if (Optn->isSimplePredicateOrRecordNode()) {
+ Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());
+ if (M2 != 0 && M2 != ScanMatcher &&
+ M2->canMoveBefore(ScanMatcher) &&
+ (M2->isEqual(Optn) || M2->isContradictory(Optn))) {
+ Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
+ M2->setNext(MatcherWithoutM2);
+ OptionsToMatch[Scan] = M2;
+ continue;
+ }
+ }
+
+ // Otherwise, we don't know how to handle this entry, we have to bail.
+ break;
+ }
+
+ if (Scan != e &&
+ // Don't print it's obvious nothing extra could be merged anyway.
+ Scan+1 != e) {
+ DEBUG(errs() << "Couldn't merge this:\n";
+ Optn->print(errs(), 4);
+ errs() << "into this:\n";
+ OptionsToMatch[Scan]->print(errs(), 4);
+ if (Scan+1 != e)
+ OptionsToMatch[Scan+1]->printOne(errs());
+ if (Scan+2 < e)
+ OptionsToMatch[Scan+2]->printOne(errs());
+ errs() << "\n");
+ }
+
+ // If we only found one option starting with this matcher, no factoring is
+ // possible.
+ if (EqualMatchers.size() == 1) {
+ NewOptionsToMatch.push_back(EqualMatchers[0]);
+ continue;
+ }
+
+ // Factor these checks by pulling the first node off each entry and
+ // discarding it. Take the first one off the first entry to reuse.
+ Matcher *Shared = Optn;
+ Optn = Optn->takeNext();
+ EqualMatchers[0] = Optn;
+
+ // Remove and delete the first node from the other matchers we're factoring.
+ for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) {
+ Matcher *Tmp = EqualMatchers[i]->takeNext();
+ delete EqualMatchers[i];
+ EqualMatchers[i] = Tmp;
+ }
+
+ Shared->setNext(new ScopeMatcher(&EqualMatchers[0], EqualMatchers.size()));
+
+ // Recursively factor the newly created node.
+ FactorNodes(Shared->getNextPtr());
+
+ NewOptionsToMatch.push_back(Shared);
+ }
+
+ // If we're down to a single pattern to match, then we don't need this scope
+ // anymore.
+ if (NewOptionsToMatch.size() == 1) {
+ MatcherPtr.reset(NewOptionsToMatch[0]);
+ return;
+ }
+
+ if (NewOptionsToMatch.empty()) {
+ MatcherPtr.reset(0);
+ return;
+ }
+
+ // If our factoring failed (didn't achieve anything) see if we can simplify in
+ // other ways.
+
+ // Check to see if all of the leading entries are now opcode checks. If so,
+ // we can convert this Scope to be a OpcodeSwitch instead.
+ bool AllOpcodeChecks = true, AllTypeChecks = true;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ // Check to see if this breaks a series of CheckOpcodeMatchers.
+ if (AllOpcodeChecks &&
+ !isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) {
+#if 0
+ if (i > 3) {
+ errs() << "FAILING OPC #" << i << "\n";
+ NewOptionsToMatch[i]->dump();
+ }
+#endif
+ AllOpcodeChecks = false;
+ }
+
+ // Check to see if this breaks a series of CheckTypeMatcher's.
+ if (AllTypeChecks) {
+ CheckTypeMatcher *CTM =
+ cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
+ Matcher::CheckType));
+ if (CTM == 0 ||
+ // iPTR checks could alias any other case without us knowing, don't
+ // bother with them.
+ CTM->getType() == MVT::iPTR ||
+ // If the CheckType isn't at the start of the list, see if we can move
+ // it there.
+ !CTM->canMoveBefore(NewOptionsToMatch[i])) {
+#if 0
+ if (i > 3 && AllTypeChecks) {
+ errs() << "FAILING TYPE #" << i << "\n";
+ NewOptionsToMatch[i]->dump();
+ }
+#endif
+ AllTypeChecks = false;
+ }
+ }
+ }
+
+ // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.
+ if (AllOpcodeChecks) {
+ StringSet<> Opcodes;
+ SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]);
+ assert(Opcodes.insert(COM->getOpcode().getEnumName()) &&
+ "Duplicate opcodes not factored?");
+ Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext()));
+ }
+
+ MatcherPtr.reset(new SwitchOpcodeMatcher(&Cases[0], Cases.size()));
+ return;
+ }
+
+ // If all the options are CheckType's, we can form the SwitchType, woot.
+ if (AllTypeChecks) {
+ DenseMap<unsigned, unsigned> TypeEntry;
+ SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ CheckTypeMatcher *CTM =
+ cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
+ Matcher::CheckType));
+ Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM);
+ MVT::SimpleValueType CTMTy = CTM->getType();
+ delete CTM;
+
+ unsigned &Entry = TypeEntry[CTMTy];
+ if (Entry != 0) {
+ // If we have unfactored duplicate types, then we should factor them.
+ Matcher *PrevMatcher = Cases[Entry-1].second;
+ if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {
+ SM->setNumChildren(SM->getNumChildren()+1);
+ SM->resetChild(SM->getNumChildren()-1, MatcherWithoutCTM);
+ continue;
+ }
+
+ Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM };
+ Cases[Entry-1].second = new ScopeMatcher(Entries, 2);
+ continue;
+ }
+
+ Entry = Cases.size()+1;
+ Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM));
+ }
+
+ if (Cases.size() != 1) {
+ MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size()));
+ } else {
+ // If we factored and ended up with one case, create it now.
+ MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first));
+ MatcherPtr->setNext(Cases[0].second);
+ }
+ return;
+ }
+
+
+ // Reassemble the Scope node with the adjusted children.
+ Scope->setNumChildren(NewOptionsToMatch.size());
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i)
+ Scope->resetChild(i, NewOptionsToMatch[i]);
+}
+
+Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher,
+ const CodeGenDAGPatterns &CGP) {
+ OwningPtr<Matcher> MatcherPtr(TheMatcher);
+ ContractNodes(MatcherPtr, CGP);
+ SinkPatternPredicates(MatcherPtr);
+ FactorNodes(MatcherPtr);
+ return MatcherPtr.take();
+}
diff --git a/utils/TableGen/InstrEnumEmitter.cpp b/utils/TableGen/InstrEnumEmitter.cpp
index f382d34..d1e7f3d 100644
--- a/utils/TableGen/InstrEnumEmitter.cpp
+++ b/utils/TableGen/InstrEnumEmitter.cpp
@@ -29,7 +29,7 @@ void InstrEnumEmitter::run(raw_ostream &OS) {
std::string Namespace;
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
E = Target.inst_end(); II != E; ++II) {
- if (II->second.Namespace != "TargetInstrInfo") {
+ if (II->second.Namespace != "TargetOpcode") {
Namespace = II->second.Namespace;
break;
}
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index 2abc94b..da2d54f 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -43,6 +43,7 @@ const unsigned TabWidth = 4;
const unsigned Indent1 = TabWidth*1;
const unsigned Indent2 = TabWidth*2;
const unsigned Indent3 = TabWidth*3;
+const unsigned Indent4 = TabWidth*4;
// Default help string.
const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";
@@ -229,7 +230,8 @@ namespace OptionDescriptionFlags {
enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
ReallyHidden = 0x4, Extern = 0x8,
OneOrMore = 0x10, Optional = 0x20,
- CommaSeparated = 0x40 };
+ CommaSeparated = 0x40, ForwardNotSplit = 0x80,
+ ZeroOrMore = 0x100 };
}
/// OptionDescription - Represents data contained in a single
@@ -259,6 +261,9 @@ struct OptionDescription {
/// Merge - Merge two option descriptions.
void Merge (const OptionDescription& other);
+ /// CheckConsistency - Check that the flags are consistent.
+ void CheckConsistency() const;
+
// Misc convenient getters/setters.
bool isAlias() const;
@@ -271,12 +276,18 @@ struct OptionDescription {
bool isExtern() const;
void setExtern();
+ bool isForwardNotSplit() const;
+ void setForwardNotSplit();
+
bool isRequired() const;
void setRequired();
bool isOneOrMore() const;
void setOneOrMore();
+ bool isZeroOrMore() const;
+ void setZeroOrMore();
+
bool isOptional() const;
void setOptional();
@@ -297,6 +308,20 @@ struct OptionDescription {
};
+void OptionDescription::CheckConsistency() const {
+ unsigned i = 0;
+
+ i += this->isRequired();
+ i += this->isOptional();
+ i += this->isOneOrMore();
+ i += this->isZeroOrMore();
+
+ if (i > 1) {
+ throw "Only one of (required), (optional), (one_or_more) or "
+ "(zero_or_more) properties is allowed!";
+ }
+}
+
void OptionDescription::Merge (const OptionDescription& other)
{
if (other.Type != Type)
@@ -327,6 +352,13 @@ void OptionDescription::setCommaSeparated() {
Flags |= OptionDescriptionFlags::CommaSeparated;
}
+bool OptionDescription::isForwardNotSplit() const {
+ return Flags & OptionDescriptionFlags::ForwardNotSplit;
+}
+void OptionDescription::setForwardNotSplit() {
+ Flags |= OptionDescriptionFlags::ForwardNotSplit;
+}
+
bool OptionDescription::isExtern() const {
return Flags & OptionDescriptionFlags::Extern;
}
@@ -348,6 +380,13 @@ void OptionDescription::setOneOrMore() {
Flags |= OptionDescriptionFlags::OneOrMore;
}
+bool OptionDescription::isZeroOrMore() const {
+ return Flags & OptionDescriptionFlags::ZeroOrMore;
+}
+void OptionDescription::setZeroOrMore() {
+ Flags |= OptionDescriptionFlags::ZeroOrMore;
+}
+
bool OptionDescription::isOptional() const {
return Flags & OptionDescriptionFlags::Optional;
}
@@ -582,10 +621,13 @@ public:
AddHandler("init", &CollectOptionProperties::onInit);
AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
+ AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
AddHandler("required", &CollectOptionProperties::onRequired);
AddHandler("optional", &CollectOptionProperties::onOptional);
AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated);
+ AddHandler("forward_not_split",
+ &CollectOptionProperties::onForwardNotSplit);
staticMembersInitialized_ = true;
}
@@ -629,12 +671,18 @@ private:
optDesc_.setCommaSeparated();
}
+ void onForwardNotSplit (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+ if (!optDesc_.isParameter())
+ throw "'forward_not_split' is valid only for parameter options!";
+ optDesc_.setForwardNotSplit();
+ }
+
void onRequired (const DagInit& d) {
CheckNumberOfArguments(d, 0);
- if (optDesc_.isOneOrMore() || optDesc_.isOptional())
- throw "Only one of (required), (optional) or "
- "(one_or_more) properties is allowed!";
+
optDesc_.setRequired();
+ optDesc_.CheckConsistency();
}
void onInit (const DagInit& d) {
@@ -653,24 +701,31 @@ private:
void onOneOrMore (const DagInit& d) {
CheckNumberOfArguments(d, 0);
- if (optDesc_.isRequired() || optDesc_.isOptional())
- throw "Only one of (required), (optional) or "
- "(one_or_more) properties is allowed!";
- if (!OptionType::IsList(optDesc_.Type))
- llvm::errs() << "Warning: specifying the 'one_or_more' property "
- "on a non-list option will have no effect.\n";
+
optDesc_.setOneOrMore();
+ optDesc_.CheckConsistency();
+ }
+
+ void onZeroOrMore (const DagInit& d) {
+ CheckNumberOfArguments(d, 0);
+
+ if (OptionType::IsList(optDesc_.Type))
+ llvm::errs() << "Warning: specifying the 'zero_or_more' property "
+ "on a list option has no effect.\n";
+
+ optDesc_.setZeroOrMore();
+ optDesc_.CheckConsistency();
}
void onOptional (const DagInit& d) {
CheckNumberOfArguments(d, 0);
- if (optDesc_.isRequired() || optDesc_.isOneOrMore())
- throw "Only one of (required), (optional) or "
- "(one_or_more) properties is allowed!";
+
if (!OptionType::IsList(optDesc_.Type))
llvm::errs() << "Warning: specifying the 'optional' property"
- "on a non-list option will have no effect.\n";
+ "on a non-list option has no effect.\n";
+
optDesc_.setOptional();
+ optDesc_.CheckConsistency();
}
void onMultiVal (const DagInit& d) {
@@ -761,9 +816,12 @@ struct ToolDescription : public RefCountedBase<ToolDescription> {
Init* CmdLine;
Init* Actions;
StrVector InLanguage;
+ std::string InFileOption;
+ std::string OutFileOption;
std::string OutLanguage;
std::string OutputSuffix;
unsigned Flags;
+ const Init* OnEmpty;
// Various boolean properties
void setSink() { Flags |= ToolFlags::Sink; }
@@ -773,9 +831,13 @@ struct ToolDescription : public RefCountedBase<ToolDescription> {
// Default ctor here is needed because StringMap can only store
// DefaultConstructible objects
- ToolDescription() : CmdLine(0), Actions(0), Flags(0) {}
+ ToolDescription ()
+ : CmdLine(0), Actions(0), OutFileOption("-o"),
+ Flags(0), OnEmpty(0)
+ {}
ToolDescription (const std::string& n)
- : Name(n), CmdLine(0), Actions(0), Flags(0)
+ : Name(n), CmdLine(0), Actions(0), OutFileOption("-o"),
+ Flags(0), OnEmpty(0)
{}
};
@@ -806,12 +868,17 @@ public:
if (!staticMembersInitialized_) {
AddHandler("actions", &CollectToolProperties::onActions);
- AddHandler("cmd_line", &CollectToolProperties::onCmdLine);
+ AddHandler("command", &CollectToolProperties::onCommand);
AddHandler("in_language", &CollectToolProperties::onInLanguage);
AddHandler("join", &CollectToolProperties::onJoin);
AddHandler("out_language", &CollectToolProperties::onOutLanguage);
+
+ AddHandler("out_file_option", &CollectToolProperties::onOutFileOption);
+ AddHandler("in_file_option", &CollectToolProperties::onInFileOption);
+
AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
AddHandler("sink", &CollectToolProperties::onSink);
+ AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty);
staticMembersInitialized_ = true;
}
@@ -836,7 +903,7 @@ private:
toolDesc_.Actions = Case;
}
- void onCmdLine (const DagInit& d) {
+ void onCommand (const DagInit& d) {
CheckNumberOfArguments(d, 1);
toolDesc_.CmdLine = d.getArg(0);
}
@@ -878,6 +945,16 @@ private:
toolDesc_.OutLanguage = InitPtrToString(d.getArg(0));
}
+ void onOutFileOption (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ toolDesc_.OutFileOption = InitPtrToString(d.getArg(0));
+ }
+
+ void onInFileOption (const DagInit& d) {
+ CheckNumberOfArguments(d, 1);
+ toolDesc_.InFileOption = InitPtrToString(d.getArg(0));
+ }
+
void onOutputSuffix (const DagInit& d) {
CheckNumberOfArguments(d, 1);
toolDesc_.OutputSuffix = InitPtrToString(d.getArg(0));
@@ -888,6 +965,10 @@ private:
toolDesc_.setSink();
}
+ void onWorksOnEmpty (const DagInit& d) {
+ toolDesc_.OnEmpty = d.getArg(0);
+ }
+
};
/// CollectToolDescriptions - Gather information about tool properties
@@ -1490,7 +1571,7 @@ public:
/// EmitCaseConstructHandler - Emit code that handles the 'case'
/// construct. Takes a function object that should emit code for every case
/// clause. Implemented on top of WalkCase.
-/// Callback's type is void F(Init* Statement, unsigned IndentLevel,
+/// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
/// raw_ostream& O).
/// EmitElseIf parameter controls the type of condition that is emitted ('if
/// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..) {..}
@@ -1699,82 +1780,41 @@ void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
if (StrVec.empty())
throw "Tool '" + ToolName + "' has empty command line!";
- StrVector::const_iterator I = StrVec.begin(), E = StrVec.end();
+ StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
- // If there is a hook invocation on the place of the first command, skip it.
+ // Emit the command itself.
assert(!StrVec[0].empty());
+ O.indent(IndentLevel) << "cmd = ";
if (StrVec[0][0] == '$') {
- while (I != E && (*I)[0] != ')' )
- ++I;
-
- // Skip the ')' symbol.
- ++I;
+ B = SubstituteSpecialCommands(B, E, IsJoin, O);
+ ++B;
}
else {
- ++I;
+ O << '"' << StrVec[0] << '"';
+ ++B;
}
+ O << ";\n";
- bool hasINFILE = false;
+ // Go through the command arguments.
+ assert(B <= E);
+ for (; B != E; ++B) {
+ const std::string& cmd = *B;
- for (; I != E; ++I) {
- const std::string& cmd = *I;
assert(!cmd.empty());
O.indent(IndentLevel);
+
if (cmd.at(0) == '$') {
- if (cmd == "$INFILE") {
- hasINFILE = true;
- if (IsJoin) {
- O << "for (PathVector::const_iterator B = inFiles.begin()"
- << ", E = inFiles.end();\n";
- O.indent(IndentLevel) << "B != E; ++B)\n";
- O.indent(IndentLevel + Indent1) << "vec.push_back(B->str());\n";
- }
- else {
- O << "vec.push_back(inFile.str());\n";
- }
- }
- else if (cmd == "$OUTFILE") {
- O << "vec.push_back(\"\");\n";
- O.indent(IndentLevel) << "out_file_index = vec.size()-1;\n";
- }
- else {
- O << "vec.push_back(";
- I = SubstituteSpecialCommands(I, E, IsJoin, O);
- O << ");\n";
- }
+ O << "vec.push_back(std::make_pair(0, ";
+ B = SubstituteSpecialCommands(B, E, IsJoin, O);
+ O << "));\n";
}
else {
- O << "vec.push_back(\"" << cmd << "\");\n";
+ O << "vec.push_back(std::make_pair(0, \"" << cmd << "\"));\n";
}
}
- if (!hasINFILE)
- throw "Tool '" + ToolName + "' doesn't take any input!";
- O.indent(IndentLevel) << "cmd = ";
- if (StrVec[0][0] == '$')
- SubstituteSpecialCommands(StrVec.begin(), StrVec.end(), IsJoin, O);
- else
- O << '"' << StrVec[0] << '"';
- O << ";\n";
}
-/// EmitCmdLineVecFillCallback - A function object wrapper around
-/// EmitCmdLineVecFill(). Used by EmitGenerateActionMethod() as an
-/// argument to EmitCaseConstructHandler().
-class EmitCmdLineVecFillCallback {
- bool IsJoin;
- const std::string& ToolName;
- public:
- EmitCmdLineVecFillCallback(bool J, const std::string& TN)
- : IsJoin(J), ToolName(TN) {}
-
- void operator()(const Init* Statement, unsigned IndentLevel,
- raw_ostream& O) const
- {
- EmitCmdLineVecFill(Statement, ToolName, IsJoin, IndentLevel, O);
- }
-};
-
/// EmitForwardOptionPropertyHandlingCode - Helper function used to
/// implement EmitActionHandler. Emits code for
/// handling the (forward) and (forward_as) option properties.
@@ -1789,15 +1829,30 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
switch (D.Type) {
case OptionType::Switch:
- O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\");\n";
+ O.indent(IndentLevel)
+ << "vec.push_back(std::make_pair(" << D.GenVariableName()
+ << ".getPosition(), \"" << Name << "\"));\n";
break;
case OptionType::Parameter:
- O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\");\n";
- O.indent(IndentLevel) << "vec.push_back(" << D.GenVariableName() << ");\n";
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName()
+ <<".getPosition(), \"" << Name;
+
+ if (!D.isForwardNotSplit()) {
+ O << "\"));\n";
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName() << ".getPosition(), "
+ << D.GenVariableName() << "));\n";
+ }
+ else {
+ O << "=\" + " << D.GenVariableName() << "));\n";
+ }
break;
case OptionType::Prefix:
- O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\" + "
- << D.GenVariableName() << ");\n";
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName() << ".getPosition(), \""
+ << Name << "\" + "
+ << D.GenVariableName() << "));\n";
break;
case OptionType::PrefixList:
O.indent(IndentLevel)
@@ -1805,11 +1860,15 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n";
O.indent(IndentLevel)
<< "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
- O.indent(IndentLevel1) << "vec.push_back(\"" << Name << "\" + " << "*B);\n";
+ O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
+ << ".getPosition(B - " << D.GenVariableName()
+ << ".begin());\n";
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
+ << Name << "\" + " << "*B));\n";
O.indent(IndentLevel1) << "++B;\n";
for (int i = 1, j = D.MultiVal; i < j; ++i) {
- O.indent(IndentLevel1) << "vec.push_back(*B);\n";
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
O.indent(IndentLevel1) << "++B;\n";
}
@@ -1821,10 +1880,14 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
<< D.GenVariableName() << ".begin(),\n";
O.indent(IndentLevel) << "E = " << D.GenVariableName()
<< ".end() ; B != E;) {\n";
- O.indent(IndentLevel1) << "vec.push_back(\"" << Name << "\");\n";
+ O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
+ << ".getPosition(B - " << D.GenVariableName()
+ << ".begin());\n";
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
+ << Name << "\"));\n";
for (int i = 0, j = D.MultiVal; i < j; ++i) {
- O.indent(IndentLevel1) << "vec.push_back(*B);\n";
+ O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
O.indent(IndentLevel1) << "++B;\n";
}
@@ -1906,7 +1969,8 @@ class EmitActionHandlersCallback :
{
CheckNumberOfArguments(Dag, 1);
this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
- "vec.push_back(", ");\n", IndentLevel, O);
+ "vec.push_back(std::make_pair(65536, ", "));\n",
+ IndentLevel, O);
}
void onForward (const DagInit& Dag,
@@ -1936,13 +2000,23 @@ class EmitActionHandlersCallback :
const OptionDescription& D = OptDescs.FindListOrParameter(Name);
if (D.isParameter()) {
- O.indent(IndentLevel) << "vec.push_back("
- << D.GenVariableName() << ");\n";
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName() << ".getPosition(), "
+ << D.GenVariableName() << "));\n";
}
else {
- O.indent(IndentLevel) << "std::copy(" << D.GenVariableName()
- << ".begin(), " << D.GenVariableName()
- << ".end(), std::back_inserter(vec));\n";
+ O.indent(IndentLevel) << "for (cl::list<std::string>::iterator B = "
+ << D.GenVariableName() << ".begin(), \n";
+ O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
+ << ".end(); B != E; ++B)\n";
+ O.indent(IndentLevel) << "{\n";
+ O.indent(IndentLevel + Indent1)
+ << "unsigned pos = " << D.GenVariableName()
+ << ".getPosition(B - " << D.GenVariableName()
+ << ".begin());\n";
+ O.indent(IndentLevel + Indent1)
+ << "vec.push_back(std::make_pair(pos, *B));\n";
+ O.indent(IndentLevel) << "}\n";
}
}
@@ -1954,9 +2028,18 @@ class EmitActionHandlersCallback :
const std::string& Hook = InitPtrToString(Dag.getArg(1));
const OptionDescription& D = OptDescs.FindListOrParameter(Name);
- O.indent(IndentLevel) << "vec.push_back(" << "hooks::"
- << Hook << "(" << D.GenVariableName()
- << (D.isParameter() ? ".c_str()" : "") << "));\n";
+ O.indent(IndentLevel) << "vec.push_back(std::make_pair("
+ << D.GenVariableName() << ".getPosition("
+ << (D.isList() ? "0" : "") << "), "
+ << "hooks::" << Hook << "(" << D.GenVariableName()
+ << (D.isParameter() ? ".c_str()" : "") << ")));\n";
+ }
+
+ void onNoOutFile (const DagInit& Dag,
+ unsigned IndentLevel, raw_ostream& O) const
+ {
+ CheckNumberOfArguments(Dag, 0);
+ O.indent(IndentLevel) << "no_out_file = true;\n";
}
void onOutputSuffix (const DagInit& Dag,
@@ -1995,12 +2078,15 @@ class EmitActionHandlersCallback :
AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue);
AddHandler("forward_transformed_value",
&EmitActionHandlersCallback::onForwardTransformedValue);
+ AddHandler("no_out_file",
+ &EmitActionHandlersCallback::onNoOutFile);
AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix);
AddHandler("stop_compilation",
&EmitActionHandlersCallback::onStopCompilation);
AddHandler("unpack_values",
&EmitActionHandlersCallback::onUnpackValues);
+
staticMembersInitialized_ = true;
}
}
@@ -2012,58 +2098,6 @@ class EmitActionHandlersCallback :
}
};
-bool IsOutFileIndexCheckRequiredStr (const Init* CmdLine) {
- StrVector StrVec;
- TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);
-
- for (StrVector::const_iterator I = StrVec.begin(), E = StrVec.end();
- I != E; ++I) {
- if (*I == "$OUTFILE")
- return false;
- }
-
- return true;
-}
-
-class IsOutFileIndexCheckRequiredStrCallback {
- bool* ret_;
-
-public:
- IsOutFileIndexCheckRequiredStrCallback(bool* ret) : ret_(ret)
- {}
-
- void operator()(const Init* CmdLine) {
- // Ignore nested 'case' DAG.
- if (typeid(*CmdLine) == typeid(DagInit))
- return;
-
- if (IsOutFileIndexCheckRequiredStr(CmdLine))
- *ret_ = true;
- }
-
- void operator()(const DagInit* Test, unsigned, bool) {
- this->operator()(Test);
- }
- void operator()(const Init* Statement, unsigned) {
- this->operator()(Statement);
- }
-};
-
-bool IsOutFileIndexCheckRequiredCase (Init* CmdLine) {
- bool ret = false;
- WalkCase(CmdLine, Id(), IsOutFileIndexCheckRequiredStrCallback(&ret));
- return ret;
-}
-
-/// IsOutFileIndexCheckRequired - Should we emit an "out_file_index != -1" check
-/// in EmitGenerateActionMethod() ?
-bool IsOutFileIndexCheckRequired (Init* CmdLine) {
- if (typeid(*CmdLine) == typeid(StringInit))
- return IsOutFileIndexCheckRequiredStr(CmdLine);
- else
- return IsOutFileIndexCheckRequiredCase(CmdLine);
-}
-
void EmitGenerateActionMethodHeader(const ToolDescription& D,
bool IsJoin, raw_ostream& O)
{
@@ -2078,8 +2112,10 @@ void EmitGenerateActionMethodHeader(const ToolDescription& D,
O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
O.indent(Indent1) << "{\n";
O.indent(Indent2) << "std::string cmd;\n";
- O.indent(Indent2) << "std::vector<std::string> vec;\n";
+ O.indent(Indent2) << "std::string out_file;\n";
+ O.indent(Indent2) << "std::vector<std::pair<unsigned, std::string> > vec;\n";
O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
+ O.indent(Indent2) << "bool no_out_file = false;\n";
O.indent(Indent2) << "const char* output_suffix = \""
<< D.OutputSuffix << "\";\n";
}
@@ -2095,46 +2131,67 @@ void EmitGenerateActionMethod (const ToolDescription& D,
if (!D.CmdLine)
throw "Tool " + D.Name + " has no cmd_line property!";
- bool IndexCheckRequired = IsOutFileIndexCheckRequired(D.CmdLine);
- O.indent(Indent2) << "int out_file_index"
- << (IndexCheckRequired ? " = -1" : "")
- << ";\n\n";
-
- // Process the cmd_line property.
- if (typeid(*D.CmdLine) == typeid(StringInit))
- EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
- else
- EmitCaseConstructHandler(D.CmdLine, Indent2,
- EmitCmdLineVecFillCallback(IsJoin, D.Name),
- true, OptDescs, O);
+ // Process the 'command' property.
+ O << '\n';
+ EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
+ O << '\n';
- // For every understood option, emit handling code.
+ // Process the 'actions' list of this tool.
if (D.Actions)
EmitCaseConstructHandler(D.Actions, Indent2,
EmitActionHandlersCallback(OptDescs),
false, OptDescs, O);
-
O << '\n';
- O.indent(Indent2)
- << "std::string out_file = OutFilename("
- << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
- O.indent(Indent3) << "TempDir, stop_compilation, output_suffix).str();\n\n";
- if (IndexCheckRequired)
- O.indent(Indent2) << "if (out_file_index != -1)\n";
- O.indent(IndexCheckRequired ? Indent3 : Indent2)
- << "vec[out_file_index] = out_file;\n";
+ // Input file (s)
+ if (!D.InFileOption.empty()) {
+ O.indent(Indent2)
+ << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
+ << D.InFileOption << "\");\n";
+ }
+
+ if (IsJoin) {
+ O.indent(Indent2)
+ << "for (PathVector::const_iterator B = inFiles.begin(),\n";
+ O.indent(Indent3) << "E = inFiles.end(); B != E; ++B)\n";
+ O.indent(Indent2) << "{\n";
+ O.indent(Indent3) << "vec.push_back(std::make_pair("
+ << "InputFilenames.getPosition(B - inFiles.begin()), "
+ << "B->str()));\n";
+ O.indent(Indent2) << "}\n";
+ }
+ else {
+ O.indent(Indent2) << "vec.push_back(std::make_pair("
+ << "InputFilenames.getPosition(0), inFile.str()));\n";
+ }
+
+ // Output file
+ O.indent(Indent2) << "if (!no_out_file) {\n";
+ if (!D.OutFileOption.empty())
+ O.indent(Indent3) << "vec.push_back(std::make_pair(65536, \""
+ << D.OutFileOption << "\"));\n";
+
+ O.indent(Indent3) << "out_file = this->OutFilename("
+ << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
+ O.indent(Indent4) << "TempDir, stop_compilation, output_suffix).str();\n\n";
+ O.indent(Indent3) << "vec.push_back(std::make_pair(65536, out_file));\n";
+
+ O.indent(Indent2) << "}\n\n";
// Handle the Sink property.
if (D.isSink()) {
O.indent(Indent2) << "if (!" << SinkOptionName << ".empty()) {\n";
- O.indent(Indent3) << "vec.insert(vec.end(), "
- << SinkOptionName << ".begin(), " << SinkOptionName
- << ".end());\n";
+ O.indent(Indent3) << "for (cl::list<std::string>::iterator B = "
+ << SinkOptionName << ".begin(), E = " << SinkOptionName
+ << ".end(); B != E; ++B)\n";
+ O.indent(Indent4) << "vec.push_back(std::make_pair(" << SinkOptionName
+ << ".getPosition(B - " << SinkOptionName
+ << ".begin()), *B));\n";
O.indent(Indent2) << "}\n";
}
- O.indent(Indent2) << "return Action(cmd, vec, stop_compilation, out_file);\n";
+ O.indent(Indent2) << "return Action(cmd, this->SortArgs(vec), "
+ << "stop_compilation, out_file);\n";
O.indent(Indent1) << "}\n\n";
}
@@ -2194,6 +2251,29 @@ void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
O.indent(Indent1) << "}\n\n";
}
+/// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
+/// conjunction with EmitCaseConstructHandler.
+void EmitWorksOnEmptyCallback (const Init* Value,
+ unsigned IndentLevel, raw_ostream& O) {
+ CheckBooleanConstant(Value);
+ O.indent(IndentLevel) << "return " << Value->getAsString() << ";\n";
+}
+
+/// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
+/// class.
+void EmitWorksOnEmptyMethod (const ToolDescription& D,
+ const OptionDescriptions& OptDescs,
+ raw_ostream& O)
+{
+ O.indent(Indent1) << "bool WorksOnEmpty() const {\n";
+ if (D.OnEmpty == 0)
+ O.indent(Indent2) << "return false;\n";
+ else
+ EmitCaseConstructHandler(D.OnEmpty, Indent2, EmitWorksOnEmptyCallback,
+ /*EmitElseIf = */ true, OptDescs, O);
+ O.indent(Indent1) << "}\n\n";
+}
+
/// EmitStaticMemberDefinitions - Emit static member definitions for a
/// given Tool class.
void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
@@ -2228,6 +2308,7 @@ void EmitToolClassDefinition (const ToolDescription& D,
EmitNameMethod(D, O);
EmitInOutLanguageMethods(D, O);
EmitIsJoinMethod(D, O);
+ EmitWorksOnEmptyMethod(D, OptDescs, O);
EmitGenerateActionMethods(D, OptDescs, O);
// Close class definition
@@ -2277,12 +2358,15 @@ void EmitOptionDefinitions (const OptionDescriptions& descs,
else
O << ", cl::Required";
}
- else if (val.isOneOrMore() && val.isList()) {
- O << ", cl::OneOrMore";
- }
- else if (val.isOptional() && val.isList()) {
+
+ if (val.isOptional())
O << ", cl::Optional";
- }
+
+ if (val.isOneOrMore())
+ O << ", cl::OneOrMore";
+
+ if (val.isZeroOrMore())
+ O << ", cl::ZeroOrMore";
if (val.isReallyHidden())
O << ", cl::ReallyHidden";
@@ -2981,7 +3065,7 @@ void LLVMCConfigurationEmitter::run (raw_ostream &O) {
CollectPluginData(Records, Data);
CheckPluginData(Data);
- EmitSourceFileHeader("LLVMC Configuration Library", O);
+ this->EmitSourceFileHeader("LLVMC Configuration Library", O);
EmitPluginCode(Data, O);
} catch (std::exception& Error) {
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index 45f3072..90096e9 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -1225,6 +1225,10 @@ public:
ID(LastID++), Name(N), Loc(loc) {}
~Record() {}
+
+ static unsigned getNewUID() { return LastID++; }
+
+
unsigned getID() const { return ID; }
const std::string &getName() const { return Name; }
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index da2de6b..ea78d41 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -24,6 +24,18 @@
using namespace llvm;
+#define MRM_MAPPING \
+ MAP(C1, 33) \
+ MAP(C2, 34) \
+ MAP(C3, 35) \
+ MAP(C4, 36) \
+ MAP(C8, 37) \
+ MAP(C9, 38) \
+ MAP(E8, 39) \
+ MAP(F0, 40) \
+ MAP(F8, 41) \
+ MAP(F9, 42)
+
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
enum {
@@ -38,7 +50,12 @@ namespace X86Local {
MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23,
MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,
MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31,
- MRMInitReg = 32
+ MRMInitReg = 32,
+
+#define MAP(from, to) MRM_##from = to,
+ MRM_MAPPING
+#undef MAP
+ lastMRM
};
enum {
@@ -47,10 +64,28 @@ namespace X86Local {
D8 = 3, D9 = 4, DA = 5, DB = 6,
DC = 7, DD = 8, DE = 9, DF = 10,
XD = 11, XS = 12,
- T8 = 13, TA = 14
+ T8 = 13, P_TA = 14,
+ P_0F_AE = 16, P_0F_01 = 17
};
}
-
+
+// If rows are added to the opcode extension tables, then corresponding entries
+// must be added here.
+//
+// If the row corresponds to a single byte (i.e., 8f), then add an entry for
+// that byte to ONE_BYTE_EXTENSION_TABLES.
+//
+// If the row corresponds to two bytes where the first is 0f, add an entry for
+// the second byte to TWO_BYTE_EXTENSION_TABLES.
+//
+// If the row corresponds to some other set of bytes, you will need to modify
+// the code in RecognizableInstr::emitDecodePath() as well, and add new prefixes
+// to the X86 TD files, except in two cases: if the first two bytes of such a
+// new combination are 0f 38 or 0f 3a, you just have to add maps called
+// THREE_BYTE_38_EXTENSION_TABLES and THREE_BYTE_3A_EXTENSION_TABLES and add a
+// switch(Opcode) just below the case X86Local::T8: or case X86Local::TA: line
+// in RecognizableInstr::emitDecodePath().
+
#define ONE_BYTE_EXTENSION_TABLES \
EXTENSION_TABLE(80) \
EXTENSION_TABLE(81) \
@@ -81,10 +116,6 @@ namespace X86Local {
EXTENSION_TABLE(b9) \
EXTENSION_TABLE(ba) \
EXTENSION_TABLE(c7)
-
-#define TWO_BYTE_FULL_EXTENSION_TABLES \
- EXTENSION_TABLE(01)
-
using namespace X86Disassembler;
@@ -251,6 +282,10 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
IsCodeGenOnly)
return FILTER_STRONG;
+ if (Form == X86Local::MRMInitReg)
+ return FILTER_STRONG;
+
+
// Filter out instructions with a LOCK prefix;
// prefer forms that do not have the prefix
if (HasLockPrefix)
@@ -322,9 +357,6 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
if (AsmString.find("subreg") != AsmString.npos)
return FILTER_STRONG;
- assert(Form != X86Local::MRMInitReg &&
- "FORMAT_MRMINITREG instruction not skipped");
-
if (HasFROperands && Name.find("MOV") != Name.npos &&
((Name.find("2") != Name.npos && Name.find("32") == Name.npos) ||
(Name.find("to") != Name.npos)))
@@ -549,36 +581,10 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
// Special cases where the LLVM tables are not complete
-#define EXACTCASE(class, name, lastbyte) \
- if (Name == name) { \
- tables.setTableFields(class, \
- insnContext(), \
- Opcode, \
- ExactFilter(lastbyte), \
- UID); \
- Spec->modifierBase = Opcode; \
- return; \
- }
-
- EXACTCASE(TWOBYTE, "MONITOR", 0xc8)
- EXACTCASE(TWOBYTE, "MWAIT", 0xc9)
- EXACTCASE(TWOBYTE, "SWPGS", 0xf8)
- EXACTCASE(TWOBYTE, "INVEPT", 0x80)
- EXACTCASE(TWOBYTE, "INVVPID", 0x81)
- EXACTCASE(TWOBYTE, "VMCALL", 0xc1)
- EXACTCASE(TWOBYTE, "VMLAUNCH", 0xc2)
- EXACTCASE(TWOBYTE, "VMRESUME", 0xc3)
- EXACTCASE(TWOBYTE, "VMXOFF", 0xc4)
-
- if (Name == "INVLPG") {
- tables.setTableFields(TWOBYTE,
- insnContext(),
- Opcode,
- ExtendedFilter(false, 7),
- UID);
- Spec->modifierBase = Opcode;
- return;
- }
+#define MAP(from, to) \
+ case X86Local::MRM_##from: \
+ filter = new ExactFilter(0x##from); \
+ break;
OpcodeType opcodeType = (OpcodeType)-1;
@@ -593,6 +599,12 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
opcodeType = TWOBYTE;
switch (Opcode) {
+ default:
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ break;
#define EXTENSION_TABLE(n) case 0x##n:
TWO_BYTE_EXTENSION_TABLES
#undef EXTENSION_TABLE
@@ -619,16 +631,10 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::MRM7m:
filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
break;
+ MRM_MAPPING
} // switch (Form)
break;
- default:
- if (needsModRMForDecode(Form))
- filter = new ModFilter(isRegFormat(Form));
- else
- filter = new DumbFilter();
-
- break;
- } // switch (opcode)
+ } // switch (Opcode)
opcodeToSet = Opcode;
break;
case X86Local::T8:
@@ -639,7 +645,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
filter = new DumbFilter();
opcodeToSet = Opcode;
break;
- case X86Local::TA:
+ case X86Local::P_TA:
opcodeType = THREEBYTE_3A;
if (needsModRMForDecode(Form))
filter = new ModFilter(isRegFormat(Form));
@@ -696,6 +702,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::MRM7m:
filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
break;
+ MRM_MAPPING
} // switch (Form)
break;
case 0xd8:
@@ -760,6 +767,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
}
delete filter;
+
+#undef MAP
}
#define TYPE(str, type) if (s == str) return type;
diff --git a/utils/buildit/GNUmakefile b/utils/buildit/GNUmakefile
index 57aac43..8d8504c 100644
--- a/utils/buildit/GNUmakefile
+++ b/utils/buildit/GNUmakefile
@@ -34,9 +34,9 @@ DSTROOT = $(OBJROOT)/../dst
PREFIX = /usr/local
-# Unless assertions are forced on in the GMAKE command line, enable them.
+# Unless assertions are forced on in the GMAKE command line, disable them.
ifndef ENABLE_ASSERTIONS
-ENABLE_ASSERTIONS := yes
+ENABLE_ASSERTIONS := no
endif
# Default is optimized build.
diff --git a/utils/git/find-rev b/utils/git/find-rev
new file mode 100755
index 0000000..a6161db
--- /dev/null
+++ b/utils/git/find-rev
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+
+import os, sys, subprocess
+
+def main():
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser("usage: %prog [options] <repo> <revision>")
+ parser.add_option("", "--dump-section-data", dest="dumpSectionData",
+ help="Dump the contents of sections",
+ action="store_true", default=False)
+ (opts, args) = parser.parse_args()
+
+ if len(args) != 2:
+ parser.error("invalid number of arguments")
+
+ repo,rev = args
+
+ try:
+ rev = int(rev)
+ except:
+ parser.error("invalid revision argument (not an integer)")
+
+ os.chdir(repo)
+ p = subprocess.Popen(['git', 'rev-list', 'git-svn', '--pretty'],
+ stdout=subprocess.PIPE)
+
+ bestRev = bestCommit = None
+ lastCommit = None
+ for ln in p.stdout:
+ if ln.startswith('commit '):
+ lastCommit = ln.split(' ',2)[1]
+ elif ln.startswith(' git-svn-id: '):
+ _,repo,_ = ln.strip().split(' ')
+ _,lrev = repo.rsplit('@',1)
+ lrev = int(lrev)
+ if lrev<=rev:
+ if bestRev is None or lrev>bestRev:
+ assert lastCommit
+ bestCommit = lastCommit
+ bestRev = lrev
+ if lrev == rev:
+ break
+
+ if bestCommit is not None:
+ print bestCommit
+ sys.exit(0)
+ sys.exit(1)
+
+if __name__=='__main__':
+ main()
diff --git a/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp b/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp
index 1d9c743..efa839e 100644
--- a/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp
+++ b/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp
@@ -4,7 +4,6 @@
set target_triplet "x86_64-apple-darwin10"
set TARGETS_TO_BUILD "X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend"
set llvmgcc_langs "c,c++,objc,obj-c++"
-set llvmgcc_version "4.2.1"
set prcontext "/usr/bin/tclsh8.4 /Volumes/Data/ddunbar/llvm/test/Scripts/prcontext.tcl"
set llvmtoolsdir "/Users/ddunbar/llvm.obj.64/Debug/bin"
set llvmlibsdir "/Users/ddunbar/llvm.obj.64/Debug/lib"
@@ -19,7 +18,6 @@ set compile_cxx " /usr/bin/g++ -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include
set link " /usr/bin/g++ -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include -I/Users/ddunbar/llvm.obj.64/test -I/Volumes/Data/ddunbar/llvm.obj.64/include -I/Volumes/Data/ddunbar/llvm/include -I/Volumes/Data/ddunbar/llvm/test -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -g -fno-exceptions -fno-common -Woverloaded-virtual -m64 -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -g -L/Users/ddunbar/llvm.obj.64/Debug/lib -L/Volumes/Data/ddunbar/llvm.obj.64/Debug/lib "
set llvmgcc "/Users/ddunbar/llvm-gcc/install/bin/llvm-gcc -m64 "
set llvmgxx "/Users/ddunbar/llvm-gcc/install/bin/llvm-gcc -m64 "
-set llvmgccmajvers "4"
set bugpoint_topts "-gcc-tool-args -m64"
set shlibext ".dylib"
set ocamlopt "/sw/bin/ocamlopt -cc \"g++ -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT\" -I /Users/ddunbar/llvm.obj.64/Debug/lib/ocaml"
diff --git a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp
index 1d9c743..efa839e 100644
--- a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp
+++ b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp
@@ -4,7 +4,6 @@
set target_triplet "x86_64-apple-darwin10"
set TARGETS_TO_BUILD "X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend"
set llvmgcc_langs "c,c++,objc,obj-c++"
-set llvmgcc_version "4.2.1"
set prcontext "/usr/bin/tclsh8.4 /Volumes/Data/ddunbar/llvm/test/Scripts/prcontext.tcl"
set llvmtoolsdir "/Users/ddunbar/llvm.obj.64/Debug/bin"
set llvmlibsdir "/Users/ddunbar/llvm.obj.64/Debug/lib"
@@ -19,7 +18,6 @@ set compile_cxx " /usr/bin/g++ -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include
set link " /usr/bin/g++ -arch x86_64 -I/Users/ddunbar/llvm.obj.64/include -I/Users/ddunbar/llvm.obj.64/test -I/Volumes/Data/ddunbar/llvm.obj.64/include -I/Volumes/Data/ddunbar/llvm/include -I/Volumes/Data/ddunbar/llvm/test -D_DEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -g -fno-exceptions -fno-common -Woverloaded-virtual -m64 -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -g -L/Users/ddunbar/llvm.obj.64/Debug/lib -L/Volumes/Data/ddunbar/llvm.obj.64/Debug/lib "
set llvmgcc "/Users/ddunbar/llvm-gcc/install/bin/llvm-gcc -m64 "
set llvmgxx "/Users/ddunbar/llvm-gcc/install/bin/llvm-gcc -m64 "
-set llvmgccmajvers "4"
set bugpoint_topts "-gcc-tool-args -m64"
set shlibext ".dylib"
set ocamlopt "/sw/bin/ocamlopt -cc \"g++ -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT\" -I /Users/ddunbar/llvm.obj.64/Debug/lib/ocaml"
diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py
index fba0ce2..d87a467 100644
--- a/utils/lit/lit/TestFormats.py
+++ b/utils/lit/lit/TestFormats.py
@@ -87,6 +87,10 @@ class FileBasedTest(object):
litConfig, localConfig):
source_path = testSuite.getSourcePath(path_in_suite)
for filename in os.listdir(source_path):
+ # Ignore dot files.
+ if filename.startswith('.'):
+ continue
+
filepath = os.path.join(source_path, filename)
if not os.path.isdir(filepath):
base,ext = os.path.splitext(filename)
@@ -137,7 +141,8 @@ class OneCommandPerFileTest:
d not in localConfig.excludes)]
for filename in filenames:
- if (not self.pattern.match(filename) or
+ if (filename.startswith('.') or
+ not self.pattern.match(filename) or
filename in localConfig.excludes):
continue
diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py
index 20fbc6c..a7de2b7 100644
--- a/utils/lit/lit/TestRunner.py
+++ b/utils/lit/lit/TestRunner.py
@@ -353,6 +353,8 @@ def isExpectedFail(xfails, xtargets, target_triple):
return True
+import re
+
def parseIntegratedTestScript(test):
"""parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
script and extract the lines to 'RUN' as well as 'XFAIL' and 'XTARGET'
@@ -385,7 +387,21 @@ def parseIntegratedTestScript(test):
script = []
xfails = []
xtargets = []
+ ignoredAny = False
for ln in open(sourcepath):
+ conditional = re.search('IF\((.+?)\((.+?)\)\):', ln)
+ if conditional:
+ ln = ln[conditional.end():]
+ condition = conditional.group(1)
+ value = conditional.group(2)
+
+ # Actually test the condition.
+ if condition not in test.config.conditions:
+ return (Test.UNRESOLVED, "unknown condition '"+condition+"'")
+ if not test.config.conditions[condition](value):
+ ignoredAny = True
+ continue
+
if 'RUN:' in ln:
# Isolate the command to run.
index = ln.index('RUN:')
@@ -422,6 +438,8 @@ def parseIntegratedTestScript(test):
# Verify the script contains a run line.
if not script:
+ if ignoredAny:
+ return (Test.UNSUPPORTED, "Test has only ignored run lines")
return (Test.UNRESOLVED, "Test has no run line!")
if script[-1][-1] == '\\':
diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py
index 1f5067c..d6f2a4d 100644
--- a/utils/lit/lit/TestingConfig.py
+++ b/utils/lit/lit/TestingConfig.py
@@ -10,6 +10,7 @@ class TestingConfig:
if config is None:
# Set the environment based on the command line arguments.
environment = {
+ 'LD_LIBRARY_PATH' : os.environ.get('LD_LIBRARY_PATH',''),
'PATH' : os.pathsep.join(litConfig.path +
[os.environ.get('PATH','')]),
'PATHEXT' : os.environ.get('PATHEXT',''),
@@ -27,7 +28,8 @@ class TestingConfig:
on_clone = None,
test_exec_root = None,
test_source_root = None,
- excludes = [])
+ excludes = [],
+ conditions = {})
if os.path.exists(path):
# FIXME: Improve detection and error reporting of errors in the
@@ -53,7 +55,7 @@ class TestingConfig:
def __init__(self, parent, name, suffixes, test_format,
environment, substitutions, unsupported, on_clone,
- test_exec_root, test_source_root, excludes):
+ test_exec_root, test_source_root, excludes, conditions):
self.parent = parent
self.name = str(name)
self.suffixes = set(suffixes)
@@ -65,6 +67,7 @@ class TestingConfig:
self.test_exec_root = test_exec_root
self.test_source_root = test_source_root
self.excludes = set(excludes)
+ self.conditions = dict(conditions)
def clone(self, path):
# FIXME: Chain implementations?
@@ -74,7 +77,7 @@ class TestingConfig:
self.environment, self.substitutions,
self.unsupported, self.on_clone,
self.test_exec_root, self.test_source_root,
- self.excludes)
+ self.excludes, self.conditions)
if cfg.on_clone:
cfg.on_clone(self, cfg, path)
return cfg
diff --git a/utils/llvm.grm b/utils/llvm.grm
index 86a707a..d391e2a 100644
--- a/utils/llvm.grm
+++ b/utils/llvm.grm
@@ -162,6 +162,7 @@ FuncAttr ::= noreturn
| readnone
| readonly
| inlinehint
+ | alignstack
| noinline
| alwaysinline
| optsize
diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim
index 6e4a207..518aa04 100644
--- a/utils/vim/llvm.vim
+++ b/utils/vim/llvm.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: llvm
" Maintainer: The LLVM team, http://llvm.org/
-" Updated: 2003-06-02
+" Version: $Revision: 97271 $
if version < 600
syntax clear
@@ -52,11 +52,12 @@ syn keyword llvmKeyword x86_stdcallcc x86_fastcallcc
syn keyword llvmKeyword signext zeroext inreg sret nounwind noreturn
syn keyword llvmKeyword nocapture byval nest readnone readonly noalias
syn keyword llvmKeyword inlinehint noinline alwaysinline optsize ssp sspreq
-syn keyword llvmKeyword noredzone noimplicitfloat naked
+syn keyword llvmKeyword noredzone noimplicitfloat naked alignstack
syn keyword llvmKeyword module asm align tail to
syn keyword llvmKeyword addrspace section alias sideeffect c gc
syn keyword llvmKeyword target datalayout triple
syn keyword llvmKeyword blockaddress
+syn keyword llvmKeyword union
" Obsolete keywords.
syn keyword llvmError uninitialized implementation
diff --git a/utils/vim/tablegen.vim b/utils/vim/tablegen.vim
index ad35872..11a4d80 100644
--- a/utils/vim/tablegen.vim
+++ b/utils/vim/tablegen.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: TableGen
" Maintainer: The LLVM team, http://llvm.org/
-" Updated: 2003-08-11
+" Version: $Revision: 97271 $
if version < 600
syntax clear
diff --git a/utils/vim/vimrc b/utils/vim/vimrc
index 4909f60..63108f2 100644
--- a/utils/vim/vimrc
+++ b/utils/vim/vimrc
@@ -1,4 +1,5 @@
" LLVM coding guidelines conformance for VIM
+" $Revision: 97273 $
"
" Maintainer: The LLVM Team, http://llvm.org
" WARNING: Read before you source in all these commands and macros! Some
@@ -10,17 +11,30 @@
" It's VIM, not VI
set nocompatible
-" Wrap text at 80 cols
-set textwidth=80
-
" A tab produces a 2-space indentation
set softtabstop=2
set shiftwidth=2
set expandtab
-" Highlight trailing whitespace
+" Highlight trailing whitespace and lines longer than 80 columns.
+highlight LongLine ctermbg=DarkYellow guibg=DarkYellow
highlight WhitespaceEOL ctermbg=DarkYellow guibg=DarkYellow
-match WhitespaceEOL /\s\+$/
+if v:version >= 702
+ " Lines longer than 80 columns.
+ au BufWinEnter * let w:m0=matchadd('LongLine', '\%>80v.\+', -1)
+
+ " Whitespace at the end of a line. This little dance suppresses
+ " whitespace that has just been typed.
+ au BufWinEnter * let w:m1=matchadd('WhitespaceEOL', '\s\+$', -1)
+ au InsertEnter * call matchdelete(w:m1)
+ au InsertEnter * let w:m2=matchadd('WhitespaceEOL', '\s\+\%#\@<!$', -1)
+ au InsertLeave * call matchdelete(w:m2)
+ au InsertLeave * let w:m1=matchadd('WhitespaceEOL', '\s\+$', -1)
+else
+ au BufRead,BufNewFile * syntax match LongLine /\%>80v.\+/
+ au InsertEnter * syntax match WhitespaceEOL /\s\+\%#\@<!$/
+ au InsertLeave * syntax match WhitespaceEOL /\s\+$/
+endif
" Enable filetype detection
filetype on
@@ -70,3 +84,10 @@ augroup END
augroup filetype
au! BufRead,BufNewFile *.td set filetype=tablegen
augroup END
+
+" Additional vim features to optionally uncomment.
+"set showcmd
+"set showmatch
+"set showmode
+"set incsearch
+"set ruler