diff options
Diffstat (limited to 'utils')
28 files changed, 806 insertions, 600 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 3c4742c..c6a1392 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -401,11 +401,12 @@ void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, } } - if (Best != StringRef::npos && BestQuality < 50) { - // Print the "possible intended match here" line if we found something - // reasonable. - SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), - "possible intended match here", "note"); + // Print the "possible intended match here" line if we found something + // reasonable and not equal to what we showed in the "scanning from here" + // line. + if (Best && Best != StringRef::npos && BestQuality < 50) { + SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), + "possible intended match here", "note"); // FIXME: If we wanted to be really friendly we would show why the match // failed, as it can be hard to spot simple one character differences. diff --git a/utils/NewNightlyTest.pl b/utils/NewNightlyTest.pl index a306382..4287cc1 100755 --- a/utils/NewNightlyTest.pl +++ b/utils/NewNightlyTest.pl @@ -24,6 +24,7 @@ use Socket; # IMPLEMENTED. # -nickname NAME The NAME argument specifieds the nickname this script # will submit to the nightlytest results repository. +# -nouname Don't include uname data (machine will be identified by nickname only). # -submit-server Specifies a server to submit the test results too. If this # option is not specified it defaults to # llvm.org. This is basically just the address of the @@ -220,6 +221,7 @@ while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) { $LLVMGCCPATH = $ARGV[0] . '/bin'; shift; next;} if (/^-noexternals$/) { $NOEXTERNALS = 1; next; } + if (/^-nouname$/) { $NOUNAME = 1; next; } if (/^-use-gmake/) { $MAKECMD = "gmake"; shift; next; } if (/^-extraflags/) { $CONFIGUREARGS .= " --with-extra-options=\'$ARGV[0]\'"; shift; next;} @@ -693,12 +695,21 @@ $endtime = `date "+20%y-%m-%d %H:%M:%S"`; if ( $VERBOSE ) { print "PREPARING LOGS TO BE SENT TO SERVER\n"; } -$machine_data = "uname: ".`uname -a`. - "hardware: ".`uname -m`. - "os: ".`uname -sr`. - "name: ".`uname -n`. - "date: ".`date \"+20%y-%m-%d\"`. - "time: ".`date +\"%H:%M:%S\"`; +if ( ! $NOUNAME ) { + $machine_data = "uname: ".`uname -a`. + "hardware: ".`uname -m`. + "os: ".`uname -sr`. + "name: ".`uname -n`. + "date: ".`date \"+20%y-%m-%d\"`. + "time: ".`date +\"%H:%M:%S\"`; +} else { + $machine_data = "uname: (excluded)\n". + "hardware: ".`uname -m`. + "os: ".`uname -sr`. + "name: $nickname\n". + "date: ".`date \"+20%y-%m-%d\"`. + "time: ".`date +\"%H:%M:%S\"`; +} # Get gcc version. my $gcc_version_long = ""; diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index b823e57..e5c068b 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -844,19 +844,20 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) { // Parse the instructions; we need to do this first so that we can gather the // singleton register classes. std::set<std::string> SingletonRegisterNames; - for (std::map<std::string, CodeGenInstruction>::const_iterator - it = Target.getInstructions().begin(), - ie = Target.getInstructions().end(); - it != ie; ++it) { - const CodeGenInstruction &CGI = it->second; + + const std::vector<const CodeGenInstruction*> &InstrList = + Target.getInstructionsByEnumValue(); + + for (unsigned i = 0, e = InstrList.size(); i != e; ++i) { + const CodeGenInstruction &CGI = *InstrList[i]; - if (!StringRef(it->first).startswith(MatchPrefix)) + if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) continue; - OwningPtr<InstructionInfo> II(new InstructionInfo); + OwningPtr<InstructionInfo> II(new InstructionInfo()); - II->InstrName = it->first; - II->Instr = &it->second; + II->InstrName = CGI.TheDef->getName(); + II->Instr = &CGI; II->AsmString = FlattenVariants(CGI.AsmString, 0); // Remove comments from the asm string. @@ -869,7 +870,7 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) { TokenizeAsmString(II->AsmString, II->Tokens); // Ignore instructions which shouldn't be matched. - if (!IsAssemblerInstruction(it->first, CGI, II->Tokens)) + if (!IsAssemblerInstruction(CGI.TheDef->getName(), CGI, II->Tokens)) continue; // Collect singleton registers, if used. @@ -998,7 +999,7 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, // Start the unified conversion function. - CvtOS << "static bool ConvertToMCInst(ConversionKind Kind, MCInst &Inst, " + CvtOS << "static void ConvertToMCInst(ConversionKind Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const SmallVectorImpl<MCParsedAsmOperand*" << "> &Operands) {\n"; @@ -1155,13 +1156,12 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, } } - CvtOS << " break;\n"; + CvtOS << " return;\n"; } // Finish the convert function. CvtOS << " }\n"; - CvtOS << " return false;\n"; CvtOS << "}\n\n"; // Finish the enum, and drop the convert function after it. @@ -1634,8 +1634,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " continue;\n"; } OS << "\n"; - OS << " return ConvertToMCInst(it->ConvertFn, Inst, " - << "it->Opcode, Operands);\n"; + OS << " ConvertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n"; + + // Call the post-processing function, if used. + std::string InsnCleanupFn = + AsmParser->getValueAsString("AsmParserInstCleanup"); + if (!InsnCleanupFn.empty()) + OS << " " << InsnCleanupFn << "(Inst);\n"; + + OS << " return false;\n"; OS << " }\n\n"; OS << " return true;\n"; diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 3a38dd4..ab1e239 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -254,16 +254,16 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) - if (!I->second.AsmString.empty() && - I->second.TheDef->getName() != "PHI") + if (!(*I)->AsmString.empty() && + (*I)->TheDef->getName() != "PHI") Instructions.push_back( - AsmWriterInst(I->second, + AsmWriterInst(**I, AsmWriter->getValueAsInt("Variant"), AsmWriter->getValueAsInt("FirstOperandColumn"), AsmWriter->getValueAsInt("OperandSpacing"))); // Get the instruction numbering. - Target.getInstructionsByEnumValue(NumberedInstructions); + NumberedInstructions = Target.getInstructionsByEnumValue(); // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not // all machine instructions are necessarily being printed, so there may be @@ -499,8 +499,8 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - std::vector<const CodeGenInstruction*> NumberedInstructions; - Target.getInstructionsByEnumValue(NumberedInstructions); + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); StringToOffsetTable StringTable; O << diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp index 6f1080e..27b1654 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -34,7 +34,7 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName << ",\n"; OS << "#undef " << ComponentName << "START\n"; - OS << "#endif\n"; + OS << "#endif\n\n"; } const std::vector<Record*> &Diags = diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index f1857f5..641c224 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -86,8 +86,8 @@ void CodeEmitterGen::run(raw_ostream &o) { EmitSourceFileHeader("Machine Code Emitter", o); std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::"; - std::vector<const CodeGenInstruction*> NumberedInstructions; - Target.getInstructionsByEnumValue(NumberedInstructions); + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); // Emit function declaration o << "unsigned " << Target.getName() << "CodeEmitter::" @@ -95,7 +95,7 @@ void CodeEmitterGen::run(raw_ostream &o) { // Emit instruction base values o << " static const unsigned InstBits[] = {\n"; - for (std::vector<const CodeGenInstruction*>::iterator + for (std::vector<const CodeGenInstruction*>::const_iterator IN = NumberedInstructions.begin(), EN = NumberedInstructions.end(); IN != EN; ++IN) { @@ -156,7 +156,7 @@ void CodeEmitterGen::run(raw_ostream &o) { BitsInit *BI = R->getValueAsBitsInit("Inst"); const std::vector<RecordVal> &Vals = R->getValues(); - CodeGenInstruction &CGI = Target.getInstruction(InstName); + CodeGenInstruction &CGI = Target.getInstruction(R); // Loop over all of the fields in the instruction, determining which are the // operands to the instruction. diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 6e894a4..4cc9b79 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -25,19 +25,18 @@ using namespace llvm; // EEVT::TypeSet Implementation //===----------------------------------------------------------------------===// -// FIXME: Remove EEVT::isUnknown! - static inline bool isInteger(MVT::SimpleValueType VT) { return EVT(VT).isInteger(); } - static inline bool isFloatingPoint(MVT::SimpleValueType VT) { return EVT(VT).isFloatingPoint(); } - static inline bool isVector(MVT::SimpleValueType VT) { return EVT(VT).isVector(); } +static inline bool isScalar(MVT::SimpleValueType VT) { + return !EVT(VT).isVector(); +} EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) { if (VT == MVT::iAny) @@ -67,6 +66,32 @@ EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) { TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end()); } +/// FillWithPossibleTypes - Set to all legal types and return true, only valid +/// on completely unknown type sets. +bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, + bool (*Pred)(MVT::SimpleValueType), + const char *PredicateName) { + assert(isCompletelyUnknown()); + const std::vector<MVT::SimpleValueType> &LegalTypes = + TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); + + for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) + if (Pred == 0 || Pred(LegalTypes[i])) + TypeVec.push_back(LegalTypes[i]); + + // If we have nothing that matches the predicate, bail out. + if (TypeVec.empty()) + TP.error("Type inference contradiction found, no " + + std::string(PredicateName) + " types found"); + // No need to sort with one element. + if (TypeVec.size() == 1) return true; + + // Remove duplicates. + array_pod_sort(TypeVec.begin(), TypeVec.end()); + TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end()); + + return true; +} /// hasIntegerTypes - Return true if this TypeSet contains iAny or an /// integer value type. @@ -97,7 +122,7 @@ bool EEVT::TypeSet::hasVectorTypes() const { std::string EEVT::TypeSet::getName() const { - if (TypeVec.empty()) return "isUnknown"; + if (TypeVec.empty()) return "<empty>"; std::string Result; @@ -200,94 +225,84 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ /// EnforceInteger - Remove all non-integer types from this set. bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { - TypeSet InputSet(*this); - bool MadeChange = false; - // If we know nothing, then get the full set. - if (TypeVec.empty()) { - *this = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); - MadeChange = true; - } - + if (TypeVec.empty()) + return FillWithPossibleTypes(TP, isInteger, "integer"); if (!hasFloatingPointTypes()) - return MadeChange; + return false; + + TypeSet InputSet(*this); // Filter out all the fp types. for (unsigned i = 0; i != TypeVec.size(); ++i) - if (isFloatingPoint(TypeVec[i])) + if (!isInteger(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); if (TypeVec.empty()) TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be integer"); - return MadeChange; + return true; } /// EnforceFloatingPoint - Remove all integer types from this set. bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { - TypeSet InputSet(*this); - bool MadeChange = false; - // If we know nothing, then get the full set. - if (TypeVec.empty()) { - *this = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); - MadeChange = true; - } - + if (TypeVec.empty()) + return FillWithPossibleTypes(TP, isFloatingPoint, "floating point"); + if (!hasIntegerTypes()) - return MadeChange; + return false; + + TypeSet InputSet(*this); // Filter out all the fp types. for (unsigned i = 0; i != TypeVec.size(); ++i) - if (isInteger(TypeVec[i])) + if (!isFloatingPoint(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); if (TypeVec.empty()) TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be floating point"); - return MadeChange; + return true; } /// EnforceScalar - Remove all vector types from this. bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { - TypeSet InputSet(*this); - bool MadeChange = false; - // If we know nothing, then get the full set. - if (TypeVec.empty()) { - *this = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); - MadeChange = true; - } - + if (TypeVec.empty()) + return FillWithPossibleTypes(TP, isScalar, "scalar"); + if (!hasVectorTypes()) - return MadeChange; + return false; + + TypeSet InputSet(*this); // Filter out all the vector types. for (unsigned i = 0; i != TypeVec.size(); ++i) - if (isVector(TypeVec[i])) + if (!isScalar(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); if (TypeVec.empty()) TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be scalar"); - return MadeChange; + return true; } /// EnforceVector - Remove all vector types from this. bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { + // If we know nothing, then get the full set. + if (TypeVec.empty()) + return FillWithPossibleTypes(TP, isVector, "vector"); + TypeSet InputSet(*this); bool MadeChange = false; - // If we know nothing, then get the full set. - if (TypeVec.empty()) { - *this = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); - MadeChange = true; - } - // Filter out all the scalar types. for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isVector(TypeVec[i])) + if (!isVector(TypeVec[i])) { TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; + } if (TypeVec.empty()) TP.error("Type inference contradiction found, '" + @@ -296,72 +311,86 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { } + /// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update /// this an other based on this information. bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { // Both operands must be integer or FP, but we don't care which. bool MadeChange = false; - // This code does not currently handle nodes which have multiple types, - // where some types are integer, and some are fp. Assert that this is not - // the case. - assert(!(hasIntegerTypes() && hasFloatingPointTypes()) && - !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && - "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); + if (isCompletelyUnknown()) + MadeChange = FillWithPossibleTypes(TP); + + if (Other.isCompletelyUnknown()) + MadeChange = Other.FillWithPossibleTypes(TP); + // If one side is known to be integer or known to be FP but the other side has // no information, get at least the type integrality info in there. - if (hasIntegerTypes()) + if (!hasFloatingPointTypes()) MadeChange |= Other.EnforceInteger(TP); - else if (hasFloatingPointTypes()) + else if (!hasIntegerTypes()) MadeChange |= Other.EnforceFloatingPoint(TP); - if (Other.hasIntegerTypes()) + if (!Other.hasFloatingPointTypes()) MadeChange |= EnforceInteger(TP); - else if (Other.hasFloatingPointTypes()) + else if (!Other.hasIntegerTypes()) MadeChange |= EnforceFloatingPoint(TP); assert(!isCompletelyUnknown() && !Other.isCompletelyUnknown() && "Should have a type list now"); // If one contains vectors but the other doesn't pull vectors out. - if (!hasVectorTypes() && Other.hasVectorTypes()) + if (!hasVectorTypes()) MadeChange |= Other.EnforceScalar(TP); - if (hasVectorTypes() && !Other.hasVectorTypes()) + if (!hasVectorTypes()) MadeChange |= EnforceScalar(TP); - // FIXME: This is a bone-headed way to do this. + // This code does not currently handle nodes which have multiple types, + // where some types are integer, and some are fp. Assert that this is not + // the case. + assert(!(hasIntegerTypes() && hasFloatingPointTypes()) && + !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && + "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); - // Get the set of legal VTs and filter it based on the known integrality. - const CodeGenTarget &CGT = TP.getDAGPatterns().getTargetInfo(); - TypeSet LegalVTs = CGT.getLegalValueTypes(); - - // TODO: If one or the other side is known to be a specific VT, we could prune - // LegalVTs. - if (hasIntegerTypes()) - LegalVTs.EnforceInteger(TP); - else if (hasFloatingPointTypes()) - LegalVTs.EnforceFloatingPoint(TP); - else - return MadeChange; + // Okay, find the smallest type from the current set and remove it from the + // largest set. + MVT::SimpleValueType Smallest = TypeVec[0]; + for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) + if (TypeVec[i] < Smallest) + Smallest = TypeVec[i]; - switch (LegalVTs.TypeVec.size()) { - case 0: assert(0 && "No legal VTs?"); - default: // Too many VT's to pick from. - // TODO: If the biggest type in LegalVTs is in this set, we could remove it. - // If one or the other side is known to be a specific VT, we could prune - // LegalVTs. - return MadeChange; - case 1: - // Only one VT of this flavor. Cannot ever satisfy the constraints. - return MergeInTypeInfo(MVT::Other, TP); // throw - case 2: - // If we have exactly two possible types, the little operand must be the - // small one, the big operand should be the big one. This is common with - // float/double for example. - assert(LegalVTs.TypeVec[0] < LegalVTs.TypeVec[1] && "Should be sorted!"); - MadeChange |= MergeInTypeInfo(LegalVTs.TypeVec[0], TP); - MadeChange |= Other.MergeInTypeInfo(LegalVTs.TypeVec[1], TP); - return MadeChange; - } + // If this is the only type in the large set, the constraint can never be + // satisfied. + if (Other.TypeVec.size() == 1 && Other.TypeVec[0] == Smallest) + TP.error("Type inference contradiction found, '" + + Other.getName() + "' has nothing larger than '" + getName() +"'!"); + + SmallVector<MVT::SimpleValueType, 2>::iterator TVI = + std::find(Other.TypeVec.begin(), Other.TypeVec.end(), Smallest); + if (TVI != Other.TypeVec.end()) { + Other.TypeVec.erase(TVI); + MadeChange = true; + } + + // Okay, find the largest type in the Other set and remove it from the + // current set. + MVT::SimpleValueType Largest = Other.TypeVec[0]; + for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) + if (Other.TypeVec[i] > Largest) + Largest = Other.TypeVec[i]; + + // If this is the only type in the small set, the constraint can never be + // satisfied. + if (TypeVec.size() == 1 && TypeVec[0] == Largest) + TP.error("Type inference contradiction found, '" + + getName() + "' has nothing smaller than '" + Other.getName()+"'!"); + + TVI = std::find(TypeVec.begin(), TypeVec.end(), Largest); + if (TVI != TypeVec.end()) { + TypeVec.erase(TVI); + MadeChange = true; + } + + return MadeChange; } /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type @@ -372,10 +401,8 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT, bool MadeChange = false; // If we know nothing, then get the full set. - if (TypeVec.empty()) { - *this = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); - MadeChange = true; - } + if (TypeVec.empty()) + MadeChange = FillWithPossibleTypes(TP, isVector, "vector"); // Filter out all the non-vector types and types which don't have the right // element type. @@ -511,24 +538,27 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { } /// getOperandNum - Return the node corresponding to operand #OpNo in tree -/// N, which has NumResults results. -TreePatternNode *SDTypeConstraint::getOperandNum(unsigned OpNo, - TreePatternNode *N, - unsigned NumResults) const { - assert(NumResults <= 1 && - "We only work with nodes with zero or one result so far!"); +/// N, and the result number in ResNo. +static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, + const SDNodeInfo &NodeInfo, + unsigned &ResNo) { + unsigned NumResults = NodeInfo.getNumResults(); + if (OpNo < NumResults) { + ResNo = OpNo; + return N; + } + + OpNo -= NumResults; - if (OpNo >= (NumResults + N->getNumChildren())) { - errs() << "Invalid operand number " << OpNo << " "; + if (OpNo >= N->getNumChildren()) { + errs() << "Invalid operand number in type constraint " + << (OpNo+NumResults) << " "; N->dump(); errs() << '\n'; exit(1); } - if (OpNo < NumResults) - return N; // FIXME: need value # - else - return N->getChild(OpNo-NumResults); + return N->getChild(OpNo); } /// ApplyTypeConstraint - Given a node in a pattern, apply this type @@ -538,10 +568,6 @@ TreePatternNode *SDTypeConstraint::getOperandNum(unsigned OpNo, bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, TreePattern &TP) const { - unsigned NumResults = NodeInfo.getNumResults(); - assert(NumResults <= 1 && - "We only work with nodes with zero or one result so far!"); - // Check that the number of operands is sane. Negative operands -> varargs. if (NodeInfo.getNumOperands() >= 0) { if (N->getNumChildren() != (unsigned)NodeInfo.getNumOperands()) @@ -549,30 +575,32 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, itostr(NodeInfo.getNumOperands()) + " operands!"); } - TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NumResults); + unsigned ResNo = 0; // The result number being referenced. + TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); switch (ConstraintType) { default: assert(0 && "Unknown constraint type!"); case SDTCisVT: // Operand must be a particular type. - return NodeToApply->UpdateNodeType(x.SDTCisVT_Info.VT, TP); + return NodeToApply->UpdateNodeType(ResNo, x.SDTCisVT_Info.VT, TP); case SDTCisPtrTy: // Operand must be same as target pointer type. - return NodeToApply->UpdateNodeType(MVT::iPTR, TP); + return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP); case SDTCisInt: // Require it to be one of the legal integer VTs. - return NodeToApply->getExtType().EnforceInteger(TP); + return NodeToApply->getExtType(ResNo).EnforceInteger(TP); case SDTCisFP: // Require it to be one of the legal fp VTs. - return NodeToApply->getExtType().EnforceFloatingPoint(TP); + return NodeToApply->getExtType(ResNo).EnforceFloatingPoint(TP); case SDTCisVec: // Require it to be one of the legal vector VTs. - return NodeToApply->getExtType().EnforceVector(TP); + return NodeToApply->getExtType(ResNo).EnforceVector(TP); case SDTCisSameAs: { + unsigned OResNo = 0; TreePatternNode *OtherNode = - getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults); - return NodeToApply->UpdateNodeType(OtherNode->getExtType(), TP) | - OtherNode->UpdateNodeType(NodeToApply->getExtType(), TP); + getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo); + return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)| + OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP); } case SDTCisVTSmallerThanOp: { // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must @@ -587,40 +615,47 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, if (!isInteger(VT)) TP.error(N->getOperator()->getName() + " VT operand must be integer!"); + unsigned OResNo = 0; TreePatternNode *OtherNode = - getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N,NumResults); + getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo, + OResNo); // It must be integer. - bool MadeChange = OtherNode->getExtType().EnforceInteger(TP); + bool MadeChange = OtherNode->getExtType(OResNo).EnforceInteger(TP); // This doesn't try to enforce any information on the OtherNode, it just // validates it when information is determined. - if (OtherNode->hasTypeSet() && OtherNode->getType() <= VT) - OtherNode->UpdateNodeType(MVT::Other, TP); // Throw an error. + if (OtherNode->hasTypeSet(OResNo) && OtherNode->getType(OResNo) <= VT) + OtherNode->UpdateNodeType(OResNo, MVT::Other, TP); // Throw an error. return MadeChange; } case SDTCisOpSmallerThanOp: { + unsigned BResNo = 0; TreePatternNode *BigOperand = - getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NumResults); - return NodeToApply->getExtType(). - EnforceSmallerThan(BigOperand->getExtType(), TP); + getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo, + BResNo); + return NodeToApply->getExtType(ResNo). + EnforceSmallerThan(BigOperand->getExtType(BResNo), TP); } case SDTCisEltOfVec: { + unsigned VResNo = 0; TreePatternNode *VecOperand = - getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NumResults); - if (VecOperand->hasTypeSet()) { - if (!isVector(VecOperand->getType())) + getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo, + VResNo); + if (VecOperand->hasTypeSet(VResNo)) { + if (!isVector(VecOperand->getType(VResNo))) TP.error(N->getOperator()->getName() + " VT operand must be a vector!"); - EVT IVT = VecOperand->getType(); + EVT IVT = VecOperand->getType(VResNo); IVT = IVT.getVectorElementType(); - return NodeToApply->UpdateNodeType(IVT.getSimpleVT().SimpleTy, TP); + return NodeToApply->UpdateNodeType(ResNo, IVT.getSimpleVT().SimpleTy, TP); } - if (NodeToApply->hasTypeSet() && VecOperand->getExtType().hasVectorTypes()){ + if (NodeToApply->hasTypeSet(ResNo) && + VecOperand->getExtType(VResNo).hasVectorTypes()){ // Filter vector types out of VecOperand that don't have the right element // type. - return VecOperand->getExtType(). - EnforceVectorEltTypeIs(NodeToApply->getType(), TP); + return VecOperand->getExtType(VResNo). + EnforceVectorEltTypeIs(NodeToApply->getType(ResNo), TP); } return false; } @@ -662,6 +697,8 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { Properties |= 1 << SDNPSideEffect; } else if (PropList[i]->getName() == "SDNPMemOperand") { Properties |= 1 << SDNPMemOperand; + } else if (PropList[i]->getName() == "SDNPVariadic") { + Properties |= 1 << SDNPVariadic; } else { errs() << "Unknown SD Node property '" << PropList[i]->getName() << "' on node '" << R->getName() << "'!\n"; @@ -678,8 +715,8 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { /// 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 { +/// MVT::SimpleValueType. Otherwise, return EEVT::Other. +MVT::SimpleValueType SDNodeInfo::getKnownType() const { unsigned NumResults = getNumResults(); assert(NumResults <= 1 && "We only work with nodes with zero or one result so far!"); @@ -697,7 +734,7 @@ unsigned SDNodeInfo::getKnownType() const { return MVT::iPTR; } } - return EEVT::isUnknown; + return MVT::Other; } //===----------------------------------------------------------------------===// @@ -711,17 +748,73 @@ TreePatternNode::~TreePatternNode() { #endif } - +static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { + if (Operator->getName() == "set" || + Operator->getName() == "implicit" || + Operator->getName() == "parallel") + return 0; // All return nothing. + + if (Operator->isSubClassOf("Intrinsic")) { + unsigned NumRes = CDP.getIntrinsic(Operator).IS.RetVTs.size(); + if (NumRes == 1 && CDP.getIntrinsic(Operator).IS.RetVTs[0] == MVT::isVoid) + return 0; + return NumRes; + } + + if (Operator->isSubClassOf("SDNode")) + return CDP.getSDNodeInfo(Operator).getNumResults(); + + if (Operator->isSubClassOf("PatFrag")) { + // If we've already parsed this pattern fragment, get it. Otherwise, handle + // the forward reference case where one pattern fragment references another + // before it is processed. + if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) + return PFRec->getOnlyTree()->getNumTypes(); + + // Get the result tree. + DagInit *Tree = Operator->getValueAsDag("Fragment"); + Record *Op = 0; + if (Tree && dynamic_cast<DefInit*>(Tree->getOperator())) + Op = dynamic_cast<DefInit*>(Tree->getOperator())->getDef(); + assert(Op && "Invalid Fragment"); + return GetNumNodeResults(Op, CDP); + } + + if (Operator->isSubClassOf("Instruction")) { + CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); + + // FIXME: Handle implicit defs right. + if (InstInfo.NumDefs != 0) + return 1; // FIXME: Handle inst results right! + + if (!InstInfo.ImplicitDefs.empty()) { + // Add on one implicit def if it has a resolvable type. + Record *FirstImplicitDef = InstInfo.ImplicitDefs[0]; + assert(FirstImplicitDef->isSubClassOf("Register")); + const std::vector<MVT::SimpleValueType> &RegVTs = + CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef); + if (RegVTs.size() == 1) + return 1; + } + return 0; + } + + if (Operator->isSubClassOf("SDNodeXForm")) + return 1; // FIXME: Generalize SDNodeXForm + + Operator->dump(); + errs() << "Unhandled node in GetNumNodeResults\n"; + exit(1); +} void TreePatternNode::print(raw_ostream &OS) const { - if (isLeaf()) { + if (isLeaf()) OS << *getLeafValue(); - } else { + else OS << '(' << getOperator()->getName(); - } - - if (!isTypeCompletelyUnknown()) - OS << ':' << getExtType().getName(); + + for (unsigned i = 0, e = Types.size(); i != e; ++i) + OS << ':' << getExtType(i).getName(); if (!isLeaf()) { if (getNumChildren() != 0) { @@ -757,7 +850,7 @@ void TreePatternNode::dump() const { bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N, const MultipleUseVarSet &DepVars) const { if (N == this) return true; - if (N->isLeaf() != isLeaf() || getExtType() != N->getExtType() || + if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() || getPredicateFns() != N->getPredicateFns() || getTransformFn() != N->getTransformFn()) return false; @@ -786,16 +879,16 @@ bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N, TreePatternNode *TreePatternNode::clone() const { TreePatternNode *New; if (isLeaf()) { - New = new TreePatternNode(getLeafValue()); + New = new TreePatternNode(getLeafValue(), getNumTypes()); } else { std::vector<TreePatternNode*> CChildren; CChildren.reserve(Children.size()); for (unsigned i = 0, e = getNumChildren(); i != e; ++i) CChildren.push_back(getChild(i)->clone()); - New = new TreePatternNode(getOperator(), CChildren); + New = new TreePatternNode(getOperator(), CChildren, getNumTypes()); } New->setName(getName()); - New->setType(getExtType()); + New->Types = Types; New->setPredicateFns(getPredicateFns()); New->setTransformFn(getTransformFn()); return New; @@ -803,7 +896,8 @@ TreePatternNode *TreePatternNode::clone() const { /// RemoveAllTypes - Recursively strip all the types of this tree. void TreePatternNode::RemoveAllTypes() { - setType(EEVT::TypeSet()); // Reset to unknown type. + for (unsigned i = 0, e = Types.size(); i != e; ++i) + Types[i] = EEVT::TypeSet(); // Reset to unknown type. if (isLeaf()) return; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) getChild(i)->RemoveAllTypes(); @@ -885,7 +979,8 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { } FragTree->setName(getName()); - FragTree->UpdateNodeType(getExtType(), TP); + for (unsigned i = 0, e = Types.size(); i != e; ++i) + FragTree->UpdateNodeType(i, getExtType(i), TP); // Transfer in the old predicates. for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i) @@ -903,8 +998,10 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { /// type which should be applied to it. This will infer the type of register /// references from the register file information, for example. /// -static EEVT::TypeSet getImplicitType(Record *R, bool NotRegisters, - TreePattern &TP) { +static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, + bool NotRegisters, TreePattern &TP) { + assert(ResNo == 0 && "FIXME: Unhandled result number"); + // Check to see if this is a register or a register class. if (R->isSubClassOf("RegisterClass")) { if (NotRegisters) @@ -1015,17 +1112,23 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (isLeaf()) { 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); + bool MadeChange = false; + for (unsigned i = 0, e = Types.size(); i != e; ++i) + MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i, + NotRegisters, TP), TP); + return MadeChange; } if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) { + assert(Types.size() == 1 && "Invalid IntInit"); + // Int inits are always integers. :) - bool MadeChange = Type.EnforceInteger(TP); + bool MadeChange = Types[0].EnforceInteger(TP); - if (!hasTypeSet()) + if (!Types[0].isConcrete()) return MadeChange; - MVT::SimpleValueType VT = getType(); + MVT::SimpleValueType VT = getType(0); if (VT == MVT::iPTR || VT == MVT::iPTRAny) return MadeChange; @@ -1046,7 +1149,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return MadeChange; TP.error("Integer value '" + itostr(II->getValue())+ - "' is out of range for type '" + getEnumName(getType()) + "'!"); + "' is out of range for type '" + getEnumName(getType(0)) + "'!"); return MadeChange; } return false; @@ -1054,27 +1157,31 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // special handling for set, which isn't really an SDNode. if (getOperator()->getName() == "set") { - assert (getNumChildren() >= 2 && "Missing RHS of a set?"); + assert(getNumTypes() == 0 && "Set doesn't produce a value"); + assert(getNumChildren() >= 2 && "Missing RHS of a set?"); unsigned NC = getNumChildren(); - bool MadeChange = false; + + TreePatternNode *SetVal = getChild(NC-1); + bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters); + for (unsigned i = 0; i < NC-1; ++i) { - MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters); - MadeChange |= getChild(NC-1)->ApplyTypeConstraints(TP, NotRegisters); + TreePatternNode *Child = getChild(i); + MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); // Types of operands must match. - MadeChange |=getChild(i)->UpdateNodeType(getChild(NC-1)->getExtType(),TP); - MadeChange |=getChild(NC-1)->UpdateNodeType(getChild(i)->getExtType(),TP); - MadeChange |=UpdateNodeType(MVT::isVoid, TP); + MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP); + MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP); } return MadeChange; } if (getOperator()->getName() == "implicit" || getOperator()->getName() == "parallel") { + assert(getNumTypes() == 0 && "Node doesn't produce a value"); + bool MadeChange = false; for (unsigned i = 0; i < getNumChildren(); ++i) MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters); - MadeChange |= UpdateNodeType(MVT::isVoid, TP); return MadeChange; } @@ -1083,13 +1190,16 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters); MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters); + assert(getChild(0)->getNumTypes() == 1 && + getChild(1)->getNumTypes() == 1 && "Unhandled case"); + // child #1 of COPY_TO_REGCLASS should be a register class. We don't care // what type it gets, so if it didn't get a concrete type just give it the // first viable type from the reg class. - if (!getChild(1)->hasTypeSet() && - !getChild(1)->getExtType().isCompletelyUnknown()) { - MVT::SimpleValueType RCVT = getChild(1)->getExtType().getTypeList()[0]; - MadeChange |= getChild(1)->UpdateNodeType(RCVT, TP); + if (!getChild(1)->hasTypeSet(0) && + !getChild(1)->getExtType(0).isCompletelyUnknown()) { + MVT::SimpleValueType RCVT = getChild(1)->getExtType(0).getTypeList()[0]; + MadeChange |= getChild(1)->UpdateNodeType(0, RCVT, TP); } return MadeChange; } @@ -1100,22 +1210,26 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Apply the result type to the node. unsigned NumRetVTs = Int->IS.RetVTs.size(); unsigned NumParamVTs = Int->IS.ParamVTs.size(); - + if (NumRetVTs == 1 && Int->IS.RetVTs[0] == MVT::isVoid) + NumRetVTs = 0; + for (unsigned i = 0, e = NumRetVTs; i != e; ++i) - MadeChange |= UpdateNodeType(Int->IS.RetVTs[i], TP); + MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP); - if (getNumChildren() != NumParamVTs + NumRetVTs) + if (getNumChildren() != NumParamVTs + 1) TP.error("Intrinsic '" + Int->Name + "' expects " + - utostr(NumParamVTs + NumRetVTs - 1) + " operands, not " + + utostr(NumParamVTs) + " operands, not " + utostr(getNumChildren() - 1) + " operands!"); // Apply type info to the intrinsic ID. - MadeChange |= getChild(0)->UpdateNodeType(MVT::iPTR, TP); + MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP); - for (unsigned i = NumRetVTs, e = getNumChildren(); i != e; ++i) { - MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i - NumRetVTs]; - MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP); - MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); + for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) { + MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters); + + MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i]; + assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case"); + MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP); } return MadeChange; } @@ -1126,51 +1240,60 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { bool MadeChange = NI.ApplyTypeConstraints(this, TP); for (unsigned i = 0, e = getNumChildren(); i != e; ++i) MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); - // Branch, etc. do not produce results and top-level forms in instr pattern - // must have void types. - if (NI.getNumResults() == 0) - MadeChange |= UpdateNodeType(MVT::isVoid, TP); - - return MadeChange; + return MadeChange; } if (getOperator()->isSubClassOf("Instruction")) { const DAGInstruction &Inst = CDP.getInstruction(getOperator()); - bool MadeChange = false; - unsigned NumResults = Inst.getNumResults(); - - assert(NumResults <= 1 && - "Only supports zero or one result instrs!"); + unsigned ResNo = 0; + assert(Inst.getNumResults() <= 1 && + "FIXME: Only supports zero or one result instrs!"); CodeGenInstruction &InstInfo = - CDP.getTargetInfo().getInstruction(getOperator()->getName()); + CDP.getTargetInfo().getInstruction(getOperator()); + + EEVT::TypeSet ResultType; + // Apply the result type to the node - if (NumResults == 0 || InstInfo.NumDefs == 0) { - MadeChange = UpdateNodeType(MVT::isVoid, TP); - } else { + if (InstInfo.NumDefs != 0) { // # of elements in (outs) list Record *ResultNode = Inst.getResult(0); if (ResultNode->isSubClassOf("PointerLikeRegClass")) { - MadeChange = UpdateNodeType(MVT::iPTR, TP); + ResultType = EEVT::TypeSet(MVT::iPTR, TP); } else if (ResultNode->getName() == "unknown") { // Nothing to do. } else { assert(ResultNode->isSubClassOf("RegisterClass") && "Operands should be register classes!"); - const CodeGenRegisterClass &RC = CDP.getTargetInfo().getRegisterClass(ResultNode); - MadeChange = UpdateNodeType(RC.getValueTypes(), TP); + ResultType = RC.getValueTypes(); } + } else if (!InstInfo.ImplicitDefs.empty()) { + // If the instruction has implicit defs, the first one defines the result + // type. + Record *FirstImplicitDef = InstInfo.ImplicitDefs[0]; + assert(FirstImplicitDef->isSubClassOf("Register")); + const std::vector<MVT::SimpleValueType> &RegVTs = + CDP.getTargetInfo().getRegisterVTs(FirstImplicitDef); + if (RegVTs.size() == 1) // FIXME: Generalize. + ResultType = EEVT::TypeSet(RegVTs); + } else { + // Otherwise, the instruction produces no value result. } + bool MadeChange = false; + + if (!ResultType.isCompletelyUnknown()) + MadeChange |= UpdateNodeType(ResNo, ResultType, TP); + // If this is an INSERT_SUBREG, constrain the source and destination VTs to // be the same. if (getOperator()->getName() == "INSERT_SUBREG") { - MadeChange |= UpdateNodeType(getChild(0)->getExtType(), TP); - MadeChange |= getChild(0)->UpdateNodeType(getExtType(), TP); + assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); + MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); + MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); } - unsigned ChildNo = 0; for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { @@ -1191,15 +1314,17 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MVT::SimpleValueType VT; TreePatternNode *Child = getChild(ChildNo++); + assert(Child->getNumTypes() == 1 && "Unknown case?"); + if (OperandNode->isSubClassOf("RegisterClass")) { const CodeGenRegisterClass &RC = CDP.getTargetInfo().getRegisterClass(OperandNode); - MadeChange |= Child->UpdateNodeType(RC.getValueTypes(), TP); + MadeChange |= Child->UpdateNodeType(0, RC.getValueTypes(), TP); } else if (OperandNode->isSubClassOf("Operand")) { VT = getValueType(OperandNode->getValueAsDef("Type")); - MadeChange |= Child->UpdateNodeType(VT, TP); + MadeChange |= Child->UpdateNodeType(0, VT, TP); } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) { - MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP); + MadeChange |= Child->UpdateNodeType(0, MVT::iPTR, TP); } else if (OperandNode->getName() == "unknown") { // Nothing to do. } else { @@ -1331,6 +1456,7 @@ void TreePattern::ComputeNamedNodes(TreePatternNode *N) { ComputeNamedNodes(N->getChild(i)); } + TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator()); if (!OpDef) error("Pattern has unexpected operator type!"); @@ -1359,11 +1485,11 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { Args.push_back(Dag->getArgName(0)); } - New = new TreePatternNode(DI); + New = new TreePatternNode(DI, 1); } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { New = ParseTreePattern(DI); } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { - New = new TreePatternNode(II); + New = new TreePatternNode(II, 1); if (!Dag->getArgName(0).empty()) error("Constant int argument should not have a name!"); } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Arg)) { @@ -1372,7 +1498,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { if (II == 0 || !dynamic_cast<IntInit*>(II)) error("Bits value must be constants!"); - New = new TreePatternNode(dynamic_cast<IntInit*>(II)); + New = new TreePatternNode(dynamic_cast<IntInit*>(II), 1); if (!Dag->getArgName(0).empty()) error("Constant int argument should not have a name!"); } else { @@ -1382,7 +1508,8 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { } // Apply the type cast. - New->UpdateNodeType(getValueType(Operator), *this); + assert(New->getNumTypes() == 1 && "FIXME: Unhandled"); + New->UpdateNodeType(0, getValueType(Operator), *this); if (New->getNumChildren() == 0) New->setName(Dag->getArgName(0)); return New; @@ -1421,7 +1548,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { std::vector<std::pair<Init*, std::string> >())); --i; // Revisit this node... } else { - TreePatternNode *Node = new TreePatternNode(DefI); + TreePatternNode *Node = new TreePatternNode(DefI, 1); Node->setName(Dag->getArgName(i)); Children.push_back(Node); @@ -1433,7 +1560,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { } } } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { - TreePatternNode *Node = new TreePatternNode(II); + TreePatternNode *Node = new TreePatternNode(II, 1); if (!Dag->getArgName(i).empty()) error("Constant int argument should not have a name!"); Children.push_back(Node); @@ -1443,7 +1570,7 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { if (II == 0 || !dynamic_cast<IntInit*>(II)) error("Bits value must be constants!"); - TreePatternNode *Node = new TreePatternNode(dynamic_cast<IntInit*>(II)); + TreePatternNode *Node = new TreePatternNode(dynamic_cast<IntInit*>(II),1); if (!Dag->getArgName(i).empty()) error("Constant int argument should not have a name!"); Children.push_back(Node); @@ -1474,11 +1601,12 @@ TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) { Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode(); } - TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID)); + TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1); Children.insert(Children.begin(), IIDNode); } - TreePatternNode *Result = new TreePatternNode(Operator, Children); + unsigned NumResults = GetNumNodeResults(Operator, CDP); + TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); Result->setName(Dag->getName()); return Result; } @@ -1525,7 +1653,11 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { continue; } - MadeChange |=Nodes[i]->UpdateNodeType(InNodes[0]->getExtType(),*this); + assert(Nodes[i]->getNumTypes() == 1 && + InNodes[0]->getNumTypes() == 1 && + "FIXME: cannot name multiple result nodes yet"); + MadeChange |= Nodes[i]->UpdateNodeType(0, InNodes[0]->getExtType(0), + *this); } } @@ -1533,8 +1665,12 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { // same type. if (I->second.size() > 1) { for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) { - MadeChange |=Nodes[i]->UpdateNodeType(Nodes[i+1]->getExtType(),*this); - MadeChange |=Nodes[i+1]->UpdateNodeType(Nodes[i]->getExtType(),*this); + TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1]; + assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 && + "FIXME: cannot name multiple result nodes yet"); + + MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this); + MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this); } } } @@ -1832,7 +1968,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, // 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->getExtType() != Pat->getExtType()) + if (Slot->getExtTypes() != Pat->getExtTypes()) I->error("All $" + Pat->getName() + " inputs must agree with each other"); return true; } @@ -1871,7 +2007,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, // 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) { - if (Pat->getChild(i)->getType() == MVT::isVoid) + if (Pat->getChild(i)->getNumTypes() == 0) I->error("Cannot have void nodes inside of patterns!"); FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults, InstImpInputs, InstImpResults); @@ -1933,10 +2069,12 @@ class InstAnalyzer { bool &mayStore; bool &mayLoad; bool &HasSideEffects; + bool &IsVariadic; public: InstAnalyzer(const CodeGenDAGPatterns &cdp, - bool &maystore, bool &mayload, bool &hse) - : CDP(cdp), mayStore(maystore), mayLoad(mayload), HasSideEffects(hse){ + bool &maystore, bool &mayload, bool &hse, bool &isv) + : CDP(cdp), mayStore(maystore), mayLoad(mayload), HasSideEffects(hse), + IsVariadic(isv) { } /// Analyze - Analyze the specified instruction, returning true if the @@ -1985,6 +2123,7 @@ private: if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true; if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true; if (OpInfo.hasProperty(SDNPSideEffect)) HasSideEffects = true; + if (OpInfo.hasProperty(SDNPVariadic)) IsVariadic = true; if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { // If this is an intrinsic, analyze it. @@ -2004,12 +2143,13 @@ private: static void InferFromPattern(const CodeGenInstruction &Inst, bool &MayStore, bool &MayLoad, - bool &HasSideEffects, + bool &HasSideEffects, bool &IsVariadic, const CodeGenDAGPatterns &CDP) { - MayStore = MayLoad = HasSideEffects = false; + MayStore = MayLoad = HasSideEffects = IsVariadic = false; bool HadPattern = - InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects).Analyze(Inst.TheDef); + InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects, IsVariadic) + .Analyze(Inst.TheDef); // InstAnalyzer only correctly analyzes mayStore/mayLoad so far. if (Inst.mayStore) { // If the .td file explicitly sets mayStore, use it. @@ -2047,6 +2187,9 @@ static void InferFromPattern(const CodeGenInstruction &Inst, "which already inferred this.\n", Inst.TheDef->getName().c_str()); HasSideEffects = true; } + + if (Inst.isVariadic) + IsVariadic = true; // Can warn if we want. } /// ParseInstructions - Parse all of the instructions, inlining and resolving @@ -2068,7 +2211,7 @@ void CodeGenDAGPatterns::ParseInstructions() { std::vector<Record*> Results; std::vector<Record*> Operands; - CodeGenInstruction &InstInfo =Target.getInstruction(Instrs[i]->getName()); + CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); if (InstInfo.OperandList.size() != 0) { if (InstInfo.NumDefs == 0) { @@ -2119,7 +2262,7 @@ void CodeGenDAGPatterns::ParseInstructions() { // fill in the InstResults map. for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { TreePatternNode *Pat = I->getTree(j); - if (!Pat->hasTypeSet() || Pat->getType() != MVT::isVoid) + if (Pat->getNumTypes() != 0) I->error("Top-level forms in instruction pattern should have" " void types"); @@ -2135,11 +2278,11 @@ void CodeGenDAGPatterns::ParseInstructions() { // Parse the operands list from the (ops) list, validating it. assert(I->getArgList().empty() && "Args list should still be empty here!"); - CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]->getName()); + CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]); // Check that all of the results occur first in the list. std::vector<Record*> Results; - TreePatternNode *Res0Node = NULL; + TreePatternNode *Res0Node = 0; for (unsigned i = 0; i != NumResults; ++i) { if (i == CGI.OperandList.size()) I->error("'" + InstResults.begin()->first + @@ -2217,7 +2360,7 @@ void CodeGenDAGPatterns::ParseInstructions() { OpNode->setTransformFn(0); std::vector<TreePatternNode*> Children; Children.push_back(OpNode); - OpNode = new TreePatternNode(Xform, Children); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } ResultNodeOperands.push_back(OpNode); @@ -2228,10 +2371,11 @@ void CodeGenDAGPatterns::ParseInstructions() { " occurs in pattern but not in operands list!"); TreePatternNode *ResultPattern = - new TreePatternNode(I->getRecord(), ResultNodeOperands); + new TreePatternNode(I->getRecord(), ResultNodeOperands, + GetNumNodeResults(I->getRecord(), *this)); // Copy fully inferred output node type to instruction result pattern. - if (NumResults > 0) - ResultPattern->setType(Res0Node->getExtType()); + for (unsigned i = 0; i != NumResults; ++i) + ResultPattern->setType(i, Res0Node->getExtType(i)); // Create and insert the instruction. // FIXME: InstImpResults and InstImpInputs should not be part of @@ -2292,7 +2436,7 @@ static void FindNames(const TreePatternNode *P, // If this is the first instance of the name, remember the node. if (Rec.second++ == 0) Rec.first = P; - else if (Rec.first->getType() != P->getType()) + else if (Rec.first->getExtTypes() != P->getExtTypes()) PatternTop->error("repetition of value: $" + P->getName() + " where different uses have different types!"); } @@ -2347,17 +2491,19 @@ void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, void CodeGenDAGPatterns::InferInstructionFlags() { - std::map<std::string, CodeGenInstruction> &InstrDescs = - Target.getInstructions(); - for (std::map<std::string, CodeGenInstruction>::iterator - II = InstrDescs.begin(), E = InstrDescs.end(); II != E; ++II) { - CodeGenInstruction &InstInfo = II->second; + const std::vector<const CodeGenInstruction*> &Instructions = + Target.getInstructionsByEnumValue(); + for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { + CodeGenInstruction &InstInfo = + const_cast<CodeGenInstruction &>(*Instructions[i]); // Determine properties of the instruction from its pattern. - bool MayStore, MayLoad, HasSideEffects; - InferFromPattern(InstInfo, MayStore, MayLoad, HasSideEffects, *this); + bool MayStore, MayLoad, HasSideEffects, IsVariadic; + InferFromPattern(InstInfo, MayStore, MayLoad, HasSideEffects, IsVariadic, + *this); InstInfo.mayStore = MayStore; InstInfo.mayLoad = MayLoad; InstInfo.hasSideEffects = HasSideEffects; + InstInfo.isVariadic = IsVariadic; } } @@ -2378,23 +2524,29 @@ static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) { // If this type is already concrete or completely unknown we can't do // anything. - if (N->getExtType().isCompletelyUnknown() || N->getExtType().isConcrete()) - return false; + for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) { + if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete()) + continue; + + // Otherwise, force its type to the first possibility (an arbitrary choice). + if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP)) + return true; + } - // Otherwise, force its type to the first possibility (an arbitrary choice). - return N->getExtType().MergeInTypeInfo(N->getExtType().getTypeList()[0], TP); + return false; } void CodeGenDAGPatterns::ParsePatterns() { std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern"); for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { - DagInit *Tree = Patterns[i]->getValueAsDag("PatternToMatch"); + Record *CurPattern = Patterns[i]; + DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); DefInit *OpDef = dynamic_cast<DefInit*>(Tree->getOperator()); Record *Operator = OpDef->getDef(); TreePattern *Pattern; if (Operator->getName() != "parallel") - Pattern = new TreePattern(Patterns[i], Tree, true, *this); + Pattern = new TreePattern(CurPattern, Tree, true, *this); else { std::vector<Init*> Values; RecTy *ListTy = 0; @@ -2419,17 +2571,17 @@ void CodeGenDAGPatterns::ParsePatterns() { } } ListInit *LI = new ListInit(Values, new ListRecTy(ListTy)); - Pattern = new TreePattern(Patterns[i], LI, true, *this); + Pattern = new TreePattern(CurPattern, LI, true, *this); } // Inline pattern fragments into it. Pattern->InlinePatternFragments(); - ListInit *LI = Patterns[i]->getValueAsListInit("ResultInstrs"); + ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); if (LI->getSize() == 0) continue; // no pattern. // Parse the instruction. - TreePattern *Result = new TreePattern(Patterns[i], LI, false, *this); + TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); // Inline pattern fragments into it. Result->InlinePatternFragments(); @@ -2451,14 +2603,20 @@ void CodeGenDAGPatterns::ParsePatterns() { InferredAllResultTypes = Result->InferAllTypes(&Pattern->getNamedNodesMap()); + IterateInference = false; + // Apply the type of the result to the source pattern. This helps us // resolve cases where the input type is known to be a pointer type (which // is considered resolved), but the result knows it needs to be 32- or // 64-bits. Infer the other way for good measure. - IterateInference = Pattern->getTree(0)-> - UpdateNodeType(Result->getTree(0)->getExtType(), *Result); - IterateInference |= Result->getTree(0)-> - UpdateNodeType(Pattern->getTree(0)->getExtType(), *Result); + for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(), + Pattern->getTree(0)->getNumTypes()); + i != e; ++i) { + IterateInference = Pattern->getTree(0)-> + UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result); + IterateInference |= Result->getTree(0)-> + UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); + } // If our iteration has converged and the input pattern's types are fully // resolved but the result pattern is not fully resolved, we may have a @@ -2473,7 +2631,6 @@ void CodeGenDAGPatterns::ParsePatterns() { !InferredAllResultTypes) IterateInference = ForceArbitraryInstResultType(Result->getTree(0), *Result); - } while (IterateInference); // Verify that we inferred enough types that we can do something with the @@ -2504,25 +2661,29 @@ void CodeGenDAGPatterns::ParsePatterns() { OpNode->setTransformFn(0); std::vector<TreePatternNode*> Children; Children.push_back(OpNode); - OpNode = new TreePatternNode(Xform, Children); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } ResultNodeOperands.push_back(OpNode); } DstPattern = Result->getOnlyTree(); if (!DstPattern->isLeaf()) DstPattern = new TreePatternNode(DstPattern->getOperator(), - ResultNodeOperands); - DstPattern->setType(Result->getOnlyTree()->getExtType()); + ResultNodeOperands, + DstPattern->getNumTypes()); + + for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i) + DstPattern->setType(i, Result->getOnlyTree()->getExtType(i)); + TreePattern Temp(Result->getRecord(), DstPattern, false, *this); Temp.InferAllTypes(); AddPatternToMatch(Pattern, - PatternToMatch(Patterns[i]->getValueAsListInit("Predicates"), - Pattern->getTree(0), - Temp.getOnlyTree(), InstImpResults, - Patterns[i]->getValueAsInt("AddedComplexity"), - Patterns[i]->getID())); + PatternToMatch(CurPattern->getValueAsListInit("Predicates"), + Pattern->getTree(0), + Temp.getOnlyTree(), InstImpResults, + CurPattern->getValueAsInt("AddedComplexity"), + CurPattern->getID())); } } @@ -2556,13 +2717,15 @@ static void CombineChildVariants(TreePatternNode *Orig, std::vector<TreePatternNode*> NewChildren; for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) NewChildren.push_back(ChildVariants[i][Idxs[i]]); - TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren); + TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren, + Orig->getNumTypes()); // Copy over properties. R->setName(Orig->getName()); R->setPredicateFns(Orig->getPredicateFns()); R->setTransformFn(Orig->getTransformFn()); - R->setType(Orig->getExtType()); + for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i) + R->setType(i, Orig->getExtType(i)); // If this pattern cannot match, do not include it as a variant. std::string ErrString; diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 44f82fe..f583f29 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -15,14 +15,14 @@ #ifndef CODEGEN_DAGPATTERNS_H #define CODEGEN_DAGPATTERNS_H -#include <set> -#include <algorithm> -#include <vector> - #include "CodeGenTarget.h" #include "CodeGenIntrinsics.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include <set> +#include <algorithm> +#include <vector> +#include <map> namespace llvm { class Record; @@ -41,11 +41,6 @@ namespace llvm { /// arbitrary integer, floating-point, and vector types, so only an unknown /// value is needed. namespace EEVT { - enum DAGISelGenValueType { - // FIXME: Remove EEVT::isUnknown! - isUnknown = MVT::LAST_VALUETYPE - }; - /// TypeSet - This is either empty if it's completely unknown, or holds a set /// of types. It is used during type inference because register classes can /// have multiple possible types and we don't know which one they get until @@ -59,7 +54,7 @@ namespace EEVT { /// Vector has one concrete type: The type is completely known. /// class TypeSet { - SmallVector<MVT::SimpleValueType, 2> TypeVec; + SmallVector<MVT::SimpleValueType, 4> TypeVec; public: TypeSet() {} TypeSet(MVT::SimpleValueType VT, TreePattern &TP); @@ -88,6 +83,10 @@ namespace EEVT { return TypeVec; } + bool isVoid() const { + return TypeVec.size() == 1 && TypeVec[0] == MVT::isVoid; + } + /// hasIntegerTypes - Return true if this TypeSet contains any integer value /// types. bool hasIntegerTypes() const; @@ -134,6 +133,14 @@ namespace EEVT { bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; } bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; } + + private: + /// FillWithPossibleTypes - Set to all legal types and return true, only + /// valid on completely unknown type sets. If Pred is non-null, only MVTs + /// that pass the predicate are added. + bool FillWithPossibleTypes(TreePattern &TP, + bool (*Pred)(MVT::SimpleValueType) = 0, + const char *PredicateName = 0); }; } @@ -175,11 +182,6 @@ struct SDTypeConstraint { /// exception. bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, TreePattern &TP) const; - - /// getOperandNum - Return the node corresponding to operand #OpNo in tree - /// N, which has NumResults results. - TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, - unsigned NumResults) const; }; /// SDNodeInfo - One of these records is created for each SDNode instance in @@ -208,8 +210,8 @@ public: /// 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; + /// MVT::SimpleValueType. Otherwise, return MVT::Other. + MVT::SimpleValueType getKnownType() const; /// hasProperty - Return true if this node has the specified property. /// @@ -231,10 +233,10 @@ public: /// patterns), and as such should be ref counted. We currently just leak all /// TreePatternNode objects! class TreePatternNode { - /// The type of this node. Before and during type inference, this may be a - /// set of possible types. After (successful) type inference, this is a - /// single type. - EEVT::TypeSet Type; + /// The type of each node result. Before and during type inference, each + /// result may be a set of possible types. After (successful) type inference, + /// each is a single concrete type. + SmallVector<EEVT::TypeSet, 1> Types; /// Operator - The Record for the operator if this is an interior node (not /// a leaf). @@ -258,10 +260,14 @@ class TreePatternNode { std::vector<TreePatternNode*> Children; public: - TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch) - : Operator(Op), Val(0), TransformFn(0), Children(Ch) { } - TreePatternNode(Init *val) // leaf ctor + TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch, + unsigned NumResults) + : Operator(Op), Val(0), TransformFn(0), Children(Ch) { + Types.resize(NumResults); + } + TreePatternNode(Init *val, unsigned NumResults) // leaf ctor : Operator(0), Val(val), TransformFn(0) { + Types.resize(NumResults); } ~TreePatternNode(); @@ -271,14 +277,24 @@ public: bool isLeaf() const { return Val != 0; } // Type accessors. - MVT::SimpleValueType getType() const { return Type.getConcrete(); } - const EEVT::TypeSet &getExtType() const { return Type; } - EEVT::TypeSet &getExtType() { return Type; } - void setType(const EEVT::TypeSet &T) { Type = T; } + unsigned getNumTypes() const { return Types.size(); } + MVT::SimpleValueType getType(unsigned ResNo) const { + return Types[ResNo].getConcrete(); + } + const SmallVectorImpl<EEVT::TypeSet> &getExtTypes() const { return Types; } + const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; } + EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; } + void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; } - bool hasTypeSet() const { return Type.isConcrete(); } - bool isTypeCompletelyUnknown() const { return Type.isCompletelyUnknown(); } - bool isTypeDynamicallyResolved() const { return Type.isDynamicallyResolved();} + bool hasTypeSet(unsigned ResNo) const { + return Types[ResNo].isConcrete(); + } + bool isTypeCompletelyUnknown(unsigned ResNo) const { + return Types[ResNo].isCompletelyUnknown(); + } + bool isTypeDynamicallyResolved(unsigned ResNo) const { + return Types[ResNo].isDynamicallyResolved(); + } Init *getLeafValue() const { assert(isLeaf()); return Val; } Record *getOperator() const { assert(!isLeaf()); return Operator; } @@ -371,18 +387,22 @@ public: // Higher level manipulation routines. /// information. If N already contains a conflicting type, then throw an /// exception. This returns true if any information was updated. /// - bool UpdateNodeType(const EEVT::TypeSet &InTy, TreePattern &TP) { - return Type.MergeInTypeInfo(InTy, TP); + bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy, + TreePattern &TP) { + return Types[ResNo].MergeInTypeInfo(InTy, TP); } - bool UpdateNodeType(MVT::SimpleValueType InTy, TreePattern &TP) { - return Type.MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP); + bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy, + TreePattern &TP) { + return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP); } /// ContainsUnresolvedType - Return true if this tree contains any /// unresolved types. bool ContainsUnresolvedType() const { - if (!hasTypeSet()) return true; + for (unsigned i = 0, e = Types.size(); i != e; ++i) + if (!Types[i].isConcrete()) return true; + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) if (getChild(i)->ContainsUnresolvedType()) return true; return false; @@ -672,6 +692,11 @@ public: assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); return PatternFragments.find(R)->second; } + TreePattern *getPatternFragmentIfRead(Record *R) const { + if (!PatternFragments.count(R)) return 0; + return PatternFragments.find(R)->second; + } + typedef std::map<Record*, TreePattern*, RecordPtrCmp>::const_iterator pf_iterator; pf_iterator pf_begin() const { return PatternFragments.begin(); } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index f5b52ec..eea5561 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -123,36 +123,43 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); hasOptionalDef = false; isVariadic = false; + ImplicitDefs = R->getValueAsListOfDefs("Defs"); + ImplicitUses = R->getValueAsListOfDefs("Uses"); if (neverHasSideEffects + hasSideEffects > 1) throw R->getName() + ": multiple conflicting side-effect flags set!"; - DagInit *DI; - try { - DI = R->getValueAsDag("OutOperandList"); - } catch (...) { - // Error getting operand list, just ignore it (sparcv9). - AsmString.clear(); - OperandList.clear(); - return; - } - NumDefs = DI->getNumArgs(); - - DagInit *IDI; - try { - IDI = R->getValueAsDag("InOperandList"); - } catch (...) { - // Error getting operand list, just ignore it (sparcv9). - AsmString.clear(); - OperandList.clear(); - return; - } - DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI, new DagRecTy))->Fold(R, 0); - + DagInit *OutDI = R->getValueAsDag("OutOperandList"); + + if (DefInit *Init = dynamic_cast<DefInit*>(OutDI->getOperator())) { + if (Init->getDef()->getName() != "outs") + throw R->getName() + ": invalid def name for output list: use 'outs'"; + } else + throw R->getName() + ": invalid output list: use 'outs'"; + + NumDefs = OutDI->getNumArgs(); + + DagInit *InDI = R->getValueAsDag("InOperandList"); + if (DefInit *Init = dynamic_cast<DefInit*>(InDI->getOperator())) { + if (Init->getDef()->getName() != "ins") + throw R->getName() + ": invalid def name for input list: use 'ins'"; + } else + throw R->getName() + ": invalid input list: use 'ins'"; + unsigned MIOperandNo = 0; std::set<std::string> OperandNames; - for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) { - DefInit *Arg = dynamic_cast<DefInit*>(DI->getArg(i)); + for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){ + Init *ArgInit; + std::string ArgName; + if (i < NumDefs) { + ArgInit = OutDI->getArg(i); + ArgName = OutDI->getArgName(i); + } else { + ArgInit = InDI->getArg(i-NumDefs); + ArgName = InDI->getArgName(i-NumDefs); + } + + DefInit *Arg = dynamic_cast<DefInit*>(ArgInit); if (!Arg) throw "Illegal operand for the '" + R->getName() + "' instruction!"; @@ -189,14 +196,14 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) "' in '" + R->getName() + "' instruction!"; // Check that the operand has a name and that it's unique. - if (DI->getArgName(i).empty()) + if (ArgName.empty()) throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + " has no name!"; - if (!OperandNames.insert(DI->getArgName(i)).second) + if (!OperandNames.insert(ArgName).second) throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + " has the same name as a previous operand!"; - OperandList.push_back(OperandInfo(Rec, DI->getArgName(i), PrintMethod, + OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, MIOperandNo, NumOps, MIOpInfo)); MIOperandNo += NumOps; } diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index aae2cac..c369123 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -105,7 +105,8 @@ namespace llvm { MINumOperands(MINO), MIOperandInfo(MIOI) {} }; - /// NumDefs - Number of def operands declared. + /// NumDefs - Number of def operands declared, this is the number of + /// elements in the instruction's (outs) list. /// unsigned NumDefs; @@ -113,6 +114,10 @@ namespace llvm { /// type (which is a record). std::vector<OperandInfo> OperandList; + /// ImplicitDefs/ImplicitUses - These are lists of registers that are + /// implicitly defined and used by the instruction. + std::vector<Record*> ImplicitDefs, ImplicitUses; + // Various boolean values we track for the instruction. bool isReturn; bool isBranch; diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index ec6a31f..79bc30d 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -120,24 +120,21 @@ const std::string &CodeGenTarget::getName() const { } std::string CodeGenTarget::getInstNamespace() const { - std::string InstNS; - for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) { - InstNS = i->second.Namespace; - - // Make sure not to pick up "TargetInstrInfo" by accidentally getting + // Make sure not to pick up "TargetOpcode" by accidentally getting // the namespace off the PHI instruction or something. - if (InstNS != "TargetInstrInfo") - break; + if ((*i)->Namespace != "TargetOpcode") + return (*i)->Namespace; } - return InstNS; + return ""; } Record *CodeGenTarget::getInstructionSet() const { return TargetRec->getValueAsDef("InstructionSet"); } + /// getAsmParser - Return the AssemblyParser definition for this target. /// Record *CodeGenTarget::getAsmParser() const { @@ -277,98 +274,92 @@ void CodeGenTarget::ReadInstructions() const { for (unsigned i = 0, e = Insts.size(); i != e; ++i) { std::string AsmStr = Insts[i]->getValueAsString(InstFormatName); - Instructions.insert(std::make_pair(Insts[i]->getName(), - CodeGenInstruction(Insts[i], AsmStr))); + Instructions[Insts[i]] = new CodeGenInstruction(Insts[i], AsmStr); } } -/// getInstructionsByEnumValue - Return all of the instructions defined by the -/// target, ordered by their enum value. -void CodeGenTarget:: -getInstructionsByEnumValue(std::vector<const CodeGenInstruction*> - &NumberedInstructions) { - std::map<std::string, CodeGenInstruction>::const_iterator I; - I = getInstructions().find("PHI"); - if (I == Instructions.end()) throw "Could not find 'PHI' instruction!"; - const CodeGenInstruction *PHI = &I->second; - - I = getInstructions().find("INLINEASM"); - if (I == Instructions.end()) throw "Could not find 'INLINEASM' instruction!"; - const CodeGenInstruction *INLINEASM = &I->second; - - I = getInstructions().find("DBG_LABEL"); - if (I == Instructions.end()) throw "Could not find 'DBG_LABEL' instruction!"; - const CodeGenInstruction *DBG_LABEL = &I->second; - - I = getInstructions().find("EH_LABEL"); - if (I == Instructions.end()) throw "Could not find 'EH_LABEL' instruction!"; - const CodeGenInstruction *EH_LABEL = &I->second; - - I = getInstructions().find("GC_LABEL"); - if (I == Instructions.end()) throw "Could not find 'GC_LABEL' instruction!"; - const CodeGenInstruction *GC_LABEL = &I->second; - - I = getInstructions().find("KILL"); - if (I == Instructions.end()) throw "Could not find 'KILL' instruction!"; - const CodeGenInstruction *KILL = &I->second; - - I = getInstructions().find("EXTRACT_SUBREG"); - if (I == Instructions.end()) - throw "Could not find 'EXTRACT_SUBREG' instruction!"; - const CodeGenInstruction *EXTRACT_SUBREG = &I->second; - - I = getInstructions().find("INSERT_SUBREG"); - if (I == Instructions.end()) - throw "Could not find 'INSERT_SUBREG' instruction!"; - const CodeGenInstruction *INSERT_SUBREG = &I->second; +static const CodeGenInstruction * +GetInstByName(const char *Name, + const DenseMap<const Record*, CodeGenInstruction*> &Insts) { + const Record *Rec = Records.getDef(Name); - I = getInstructions().find("IMPLICIT_DEF"); - if (I == Instructions.end()) - throw "Could not find 'IMPLICIT_DEF' instruction!"; - const CodeGenInstruction *IMPLICIT_DEF = &I->second; - - I = getInstructions().find("SUBREG_TO_REG"); - if (I == Instructions.end()) - throw "Could not find 'SUBREG_TO_REG' instruction!"; - const CodeGenInstruction *SUBREG_TO_REG = &I->second; + DenseMap<const Record*, CodeGenInstruction*>::const_iterator + I = Insts.find(Rec); + if (Rec == 0 || I == Insts.end()) + throw std::string("Could not find '") + Name + "' instruction!"; + return I->second; +} - I = getInstructions().find("COPY_TO_REGCLASS"); - if (I == Instructions.end()) - throw "Could not find 'COPY_TO_REGCLASS' instruction!"; - const CodeGenInstruction *COPY_TO_REGCLASS = &I->second; +namespace { +/// SortInstByName - Sorting predicate to sort instructions by name. +/// +struct SortInstByName { + bool operator()(const CodeGenInstruction *Rec1, + const CodeGenInstruction *Rec2) const { + return Rec1->TheDef->getName() < Rec2->TheDef->getName(); + } +}; +} - I = getInstructions().find("DBG_VALUE"); - if (I == Instructions.end()) - throw "Could not find 'DBG_VALUE' instruction!"; - const CodeGenInstruction *DBG_VALUE = &I->second; +/// getInstructionsByEnumValue - Return all of the instructions defined by the +/// target, ordered by their enum value. +void CodeGenTarget::ComputeInstrsByEnum() const { + const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); + const CodeGenInstruction *PHI = GetInstByName("PHI", Insts); + const CodeGenInstruction *INLINEASM = GetInstByName("INLINEASM", Insts); + const CodeGenInstruction *DBG_LABEL = GetInstByName("DBG_LABEL", Insts); + const CodeGenInstruction *EH_LABEL = GetInstByName("EH_LABEL", Insts); + const CodeGenInstruction *GC_LABEL = GetInstByName("GC_LABEL", Insts); + const CodeGenInstruction *KILL = GetInstByName("KILL", Insts); + const CodeGenInstruction *EXTRACT_SUBREG = + GetInstByName("EXTRACT_SUBREG", Insts); + const CodeGenInstruction *INSERT_SUBREG = + GetInstByName("INSERT_SUBREG", Insts); + const CodeGenInstruction *IMPLICIT_DEF = GetInstByName("IMPLICIT_DEF", Insts); + const CodeGenInstruction *SUBREG_TO_REG = + GetInstByName("SUBREG_TO_REG", Insts); + const CodeGenInstruction *COPY_TO_REGCLASS = + GetInstByName("COPY_TO_REGCLASS", Insts); + const CodeGenInstruction *DBG_VALUE = GetInstByName("DBG_VALUE", Insts); // Print out the rest of the instructions now. - NumberedInstructions.push_back(PHI); - NumberedInstructions.push_back(INLINEASM); - NumberedInstructions.push_back(DBG_LABEL); - NumberedInstructions.push_back(EH_LABEL); - NumberedInstructions.push_back(GC_LABEL); - NumberedInstructions.push_back(KILL); - NumberedInstructions.push_back(EXTRACT_SUBREG); - NumberedInstructions.push_back(INSERT_SUBREG); - NumberedInstructions.push_back(IMPLICIT_DEF); - NumberedInstructions.push_back(SUBREG_TO_REG); - NumberedInstructions.push_back(COPY_TO_REGCLASS); - NumberedInstructions.push_back(DBG_VALUE); - for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II) - if (&II->second != PHI && - &II->second != INLINEASM && - &II->second != DBG_LABEL && - &II->second != EH_LABEL && - &II->second != GC_LABEL && - &II->second != KILL && - &II->second != EXTRACT_SUBREG && - &II->second != INSERT_SUBREG && - &II->second != IMPLICIT_DEF && - &II->second != SUBREG_TO_REG && - &II->second != COPY_TO_REGCLASS && - &II->second != DBG_VALUE) - NumberedInstructions.push_back(&II->second); + InstrsByEnum.push_back(PHI); + InstrsByEnum.push_back(INLINEASM); + InstrsByEnum.push_back(DBG_LABEL); + InstrsByEnum.push_back(EH_LABEL); + InstrsByEnum.push_back(GC_LABEL); + InstrsByEnum.push_back(KILL); + InstrsByEnum.push_back(EXTRACT_SUBREG); + InstrsByEnum.push_back(INSERT_SUBREG); + InstrsByEnum.push_back(IMPLICIT_DEF); + InstrsByEnum.push_back(SUBREG_TO_REG); + InstrsByEnum.push_back(COPY_TO_REGCLASS); + InstrsByEnum.push_back(DBG_VALUE); + + unsigned EndOfPredefines = InstrsByEnum.size(); + + for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator + I = Insts.begin(), E = Insts.end(); I != E; ++I) { + const CodeGenInstruction *CGI = I->second; + if (CGI != PHI && + CGI != INLINEASM && + CGI != DBG_LABEL && + CGI != EH_LABEL && + CGI != GC_LABEL && + CGI != KILL && + CGI != EXTRACT_SUBREG && + CGI != INSERT_SUBREG && + CGI != IMPLICIT_DEF && + CGI != SUBREG_TO_REG && + CGI != COPY_TO_REGCLASS && + CGI != DBG_VALUE) + InstrsByEnum.push_back(CGI); + } + + // All of the instructions are now in random order based on the map iteration. + // Sort them by name. + std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(), + SortInstByName()); } @@ -404,6 +395,8 @@ ComplexPattern::ComplexPattern(Record *R) { Properties |= 1 << SDNPSideEffect; } else if (PropList[i]->getName() == "SDNPMemOperand") { Properties |= 1 << SDNPMemOperand; + } else if (PropList[i]->getName() == "SDNPVariadic") { + Properties |= 1 << SDNPVariadic; } else { errs() << "Unsupported SD Node property '" << PropList[i]->getName() << "' on ComplexPattern '" << R->getName() << "'!\n"; diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 1df74af..2926418 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -17,11 +17,11 @@ #ifndef CODEGEN_TARGET_H #define CODEGEN_TARGET_H -#include "llvm/Support/raw_ostream.h" #include "CodeGenRegisters.h" #include "CodeGenInstruction.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" #include <algorithm> -#include <map> namespace llvm { @@ -43,7 +43,8 @@ enum SDNP { SDNPMayLoad, SDNPMayStore, SDNPSideEffect, - SDNPMemOperand + SDNPMemOperand, + SDNPVariadic }; /// getValueType - Return the MVT::SimpleValueType that the specified TableGen @@ -62,7 +63,7 @@ std::string getQualifiedName(const Record *R); class CodeGenTarget { Record *TargetRec; - mutable std::map<std::string, CodeGenInstruction> Instructions; + mutable DenseMap<const Record*, CodeGenInstruction*> Instructions; mutable std::vector<CodeGenRegister> Registers; mutable std::vector<CodeGenRegisterClass> RegisterClasses; mutable std::vector<MVT::SimpleValueType> LegalValueTypes; @@ -70,6 +71,8 @@ class CodeGenTarget { void ReadRegisterClasses() const; void ReadInstructions() const; void ReadLegalValueTypes() const; + + mutable std::vector<const CodeGenInstruction*> InstrsByEnum; public: CodeGenTarget(); @@ -183,37 +186,40 @@ public: return false; } - /// getInstructions - Return all of the instructions defined for this target. - /// - const std::map<std::string, CodeGenInstruction> &getInstructions() const { +private: + DenseMap<const Record*, CodeGenInstruction*> &getInstructions() const { if (Instructions.empty()) ReadInstructions(); return Instructions; } - std::map<std::string, CodeGenInstruction> &getInstructions() { +public: + + CodeGenInstruction &getInstruction(const Record *InstRec) const { if (Instructions.empty()) ReadInstructions(); - return Instructions; + DenseMap<const Record*, CodeGenInstruction*>::iterator I = + Instructions.find(InstRec); + assert(I != Instructions.end() && "Not an instruction"); + return *I->second; } - CodeGenInstruction &getInstruction(const std::string &Name) const { - const std::map<std::string, CodeGenInstruction> &Insts = getInstructions(); - assert(Insts.count(Name) && "Not an instruction!"); - return const_cast<CodeGenInstruction&>(Insts.find(Name)->second); - } - - typedef std::map<std::string, - CodeGenInstruction>::const_iterator inst_iterator; - inst_iterator inst_begin() const { return getInstructions().begin(); } - inst_iterator inst_end() const { return Instructions.end(); } - /// getInstructionsByEnumValue - Return all of the instructions defined by the /// target, ordered by their enum value. - void getInstructionsByEnumValue(std::vector<const CodeGenInstruction*> - &NumberedInstructions); - + const std::vector<const CodeGenInstruction*> & + getInstructionsByEnumValue() const { + if (InstrsByEnum.empty()) ComputeInstrsByEnum(); + return InstrsByEnum; + } + typedef std::vector<const CodeGenInstruction*>::const_iterator inst_iterator; + inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();} + inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); } + + /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]? /// bool isLittleEndianEncoding() const; + +private: + void ComputeInstrsByEnum() const; }; /// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 73feac1..044086a 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -25,7 +25,6 @@ using namespace llvm; /// patterns before small ones. This is used to determine the size of a /// pattern. static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) { - assert(P->hasTypeSet() && "Not a valid pattern node to size!"); unsigned Size = 3; // The node itself. // If the root node is a ConstantSDNode, increases its size. // e.g. (set R32:$dst, 0). @@ -49,7 +48,8 @@ static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) { // Count children in the count if they are also nodes. for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) { TreePatternNode *Child = P->getChild(i); - if (!Child->isLeaf() && Child->getType() != MVT::Other) + if (!Child->isLeaf() && Child->getNumTypes() && + Child->getType(0) != MVT::Other) Size += getPatternSize(Child, CGP); else if (Child->isLeaf()) { if (dynamic_cast<IntInit*>(Child->getLeafValue())) @@ -75,7 +75,7 @@ static unsigned getResultPatternCost(TreePatternNode *P, Record *Op = P->getOperator(); if (Op->isSubClassOf("Instruction")) { Cost++; - CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op->getName()); + CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); if (II.usesCustomInserter) Cost += 10; } diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index 22d2fe8..cd3fad1 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -357,14 +357,13 @@ bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const { // 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; + MVT::SimpleValueType NodeType; if (getOpcode().getNumResults() == 0) NodeType = MVT::isVoid; else NodeType = getOpcode().getKnownType(); - if (NodeType != EEVT::isUnknown) - return TypesAreContradictory((MVT::SimpleValueType)NodeType, - CT->getType()); + if (NodeType != MVT::Other) + return TypesAreContradictory(NodeType, CT->getType()); } return false; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 375df6b..da6f6af 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -409,8 +409,10 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and // reinfer any correlated types. bool DoTypeCheck = false; - if (NodeNoTypes->getExtType() != N->getExtType()) { - NodeNoTypes->setType(N->getExtType()); + if (NodeNoTypes->getNumTypes() != 0 && + NodeNoTypes->getExtType(0) != N->getExtType(0)) { + assert(NodeNoTypes->getNumTypes() == 1 && "FIXME: Handle multiple results"); + NodeNoTypes->setType(0, N->getExtType(0)); InferPossibleTypes(); DoTypeCheck = true; } @@ -442,8 +444,10 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i])); - if (DoTypeCheck) - AddMatcher(new CheckTypeMatcher(N->getType())); + if (DoTypeCheck) { + assert(N->getNumTypes() == 1); + AddMatcher(new CheckTypeMatcher(N->getType(0))); + } } /// EmitMatcherCode - Generate the code that matches the predicate of this @@ -567,7 +571,7 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, assert(N->isLeaf() && "Must be a leaf"); if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { - AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType())); + AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } @@ -575,13 +579,13 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, // 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->getType())); + AddMatcher(new EmitRegisterMatcher(DI->getDef(), N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } if (DI->getDef()->getName() == "zero_reg") { - AddMatcher(new EmitRegisterMatcher(0, N->getType())); + AddMatcher(new EmitRegisterMatcher(0, N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } @@ -627,7 +631,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &OutputOps) { Record *Op = N->getOperator(); const CodeGenTarget &CGT = CGP.getTargetInfo(); - CodeGenInstruction &II = CGT.getInstruction(Op->getName()); + CodeGenInstruction &II = CGT.getInstruction(Op); const DAGInstruction &Inst = CGP.getInstruction(Op); // If we can, get the pattern for the instruction we're generating. We derive @@ -698,7 +702,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // 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)); + 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; @@ -708,12 +712,12 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // Determine the result types. SmallVector<MVT::SimpleValueType, 4> ResultVTs; - if (NumResults != 0 && N->getType() != MVT::isVoid) { + if (N->getNumTypes()) { // FIXME2: If the node has multiple results, we should add them. For now, // preserve existing behavior?! - ResultVTs.push_back(N->getType()); + assert(N->getNumTypes() == 1); + ResultVTs.push_back(N->getType(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: @@ -721,16 +725,26 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // 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)); + // If the root came from an implicit def in the instruction handling stuff, + // don't re-add it. + Record *HandledReg = 0; + if (NumResults == 0 && N->getNumTypes() != 0 && + !II.ImplicitDefs.empty()) + HandledReg = II.ImplicitDefs[0]; + + for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { + Record *Reg = Pattern.getDstRegs()[i]; + if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue; + ResultVTs.push_back(getRegisterValueType(Reg, 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. + // If this is the root of the pattern and the pattern we're matching includes + // a node that is variadic, mark the generated node as variadic so that it + // gets the excess operands from the input DAG. int NumFixedArityOperands = -1; - if (isRoot && II.isVariadic) + if (isRoot && + (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))) NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); // If this is the root node and any of the nodes matched nodes in the input diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index 61b9b15..a195c0b 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -108,8 +108,8 @@ void DisassemblerEmitter::run(raw_ostream &OS) { if (Target.getName() == "X86") { DisassemblerTables Tables; - std::vector<const CodeGenInstruction*> numberedInstructions; - Target.getInstructionsByEnumValue(numberedInstructions); + const std::vector<const CodeGenInstruction*> &numberedInstructions = + Target.getInstructionsByEnumValue(); for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i) RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i); diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 2149410..f83ab48 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -549,8 +549,8 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, /// @arg target - The CodeGenTarget to use as a source of instructions static void populateInstInfo(CompoundConstantEmitter &infoArray, CodeGenTarget &target) { - std::vector<const CodeGenInstruction*> numberedInstructions; - target.getInstructionsByEnumValue(numberedInstructions); + const std::vector<const CodeGenInstruction*> &numberedInstructions = + target.getInstructionsByEnumValue(); unsigned int index; unsigned int numInstructions = numberedInstructions.size(); diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index b94ded6..23f09a5 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -70,13 +70,16 @@ struct OperandsSignature { for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { TreePatternNode *Op = InstPatNode->getChild(i); // For now, filter out any operand with a predicate. - if (!Op->getPredicateFns().empty()) - return false; // For now, filter out any operand with multiple values. - assert(Op->hasTypeSet() && "Type infererence not done?"); + if (!Op->getPredicateFns().empty() || + Op->getNumTypes() != 1) + return false; + + assert(Op->hasTypeSet(0) && "Type infererence not done?"); // For now, all the operands must have the same type. - if (Op->getType() != VT) + if (Op->getType(0) != VT) return false; + if (!Op->isLeaf()) { if (Op->getOperator()->getName() == "imm") { Operands.push_back("i"); @@ -254,7 +257,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { Record *Op = Dst->getOperator(); if (!Op->isSubClassOf("Instruction")) continue; - CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op->getName()); + CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); if (II.OperandList.empty()) continue; @@ -295,10 +298,14 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { Record *InstPatOp = InstPatNode->getOperator(); std::string OpcodeName = getOpcodeName(InstPatOp, CGP); - MVT::SimpleValueType RetVT = InstPatNode->getType(); + assert(InstPatNode->getNumTypes() <= 1); + MVT::SimpleValueType RetVT = MVT::isVoid; + if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getType(0); MVT::SimpleValueType VT = RetVT; - if (InstPatNode->getNumChildren()) - VT = InstPatNode->getChild(0)->getType(); + if (InstPatNode->getNumChildren()) { + assert(InstPatNode->getChild(0)->getNumTypes() == 1); + VT = InstPatNode->getChild(0)->getType(0); + } // For now, filter out instructions which just set a register to // an Operand or an immediate, like MOV32ri. diff --git a/utils/TableGen/InstrEnumEmitter.cpp b/utils/TableGen/InstrEnumEmitter.cpp index d1e7f3d..47a8474 100644 --- a/utils/TableGen/InstrEnumEmitter.cpp +++ b/utils/TableGen/InstrEnumEmitter.cpp @@ -26,22 +26,15 @@ void InstrEnumEmitter::run(raw_ostream &OS) { CodeGenTarget Target; // We must emit the PHI opcode first... - std::string Namespace; - for (CodeGenTarget::inst_iterator II = Target.inst_begin(), - E = Target.inst_end(); II != E; ++II) { - if (II->second.Namespace != "TargetOpcode") { - Namespace = II->second.Namespace; - break; - } - } + std::string Namespace = Target.getInstNamespace(); if (Namespace.empty()) { fprintf(stderr, "No instructions defined!\n"); exit(1); } - std::vector<const CodeGenInstruction*> NumberedInstructions; - Target.getInstructionsByEnumValue(NumberedInstructions); + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); OS << "namespace " << Namespace << " {\n"; OS << " enum {\n"; diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 898c92a..8f7550b 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -39,16 +39,10 @@ static void PrintBarriers(std::vector<Record*> &Barriers, // Instruction Itinerary Information. //===----------------------------------------------------------------------===// -struct RecordNameComparator { - bool operator()(const Record *Rec1, const Record *Rec2) const { - return Rec1->getName() < Rec2->getName(); - } -}; - void InstrInfoEmitter::GatherItinClasses() { std::vector<Record*> DefList = Records.getAllDerivedDefinitions("InstrItinClass"); - std::sort(DefList.begin(), DefList.end(), RecordNameComparator()); + std::sort(DefList.begin(), DefList.end(), LessRecord()); for (unsigned i = 0, N = DefList.size(); i < N; i++) ItinClassMap[DefList[i]->getName()] = i; @@ -149,7 +143,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, const CodeGenTarget &Target = CDP.getTargetInfo(); for (CodeGenTarget::inst_iterator II = Target.inst_begin(), E = Target.inst_end(); II != E; ++II) { - std::vector<std::string> OperandInfo = GetOperandInfo(II->second); + std::vector<std::string> OperandInfo = GetOperandInfo(**II); unsigned &N = OperandInfoIDs[OperandInfo]; if (N != 0) continue; @@ -214,7 +208,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { // Emit all of the instruction's implicit uses and defs. for (CodeGenTarget::inst_iterator II = Target.inst_begin(), E = Target.inst_end(); II != E; ++II) { - Record *Inst = II->second.TheDef; + Record *Inst = (*II)->TheDef; std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses"); if (!Uses.empty()) { unsigned &IL = EmittedLists[Uses]; @@ -244,8 +238,8 @@ void InstrInfoEmitter::run(raw_ostream &OS) { // OS << "\nstatic const TargetInstrDesc " << TargetName << "Insts[] = {\n"; - std::vector<const CodeGenInstruction*> NumberedInstructions; - Target.getInstructionsByEnumValue(NumberedInstructions); + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index f9e2fe8..b9facb4 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -646,18 +646,8 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { if (LHSs && RHSs) { DefInit *LOp = dynamic_cast<DefInit*>(LHSs->getOperator()); DefInit *ROp = dynamic_cast<DefInit*>(RHSs->getOperator()); - if (LOp->getDef() != ROp->getDef()) { - bool LIsOps = - LOp->getDef()->getName() == "outs" || - LOp->getDef()->getName() != "ins" || - LOp->getDef()->getName() != "defs"; - bool RIsOps = - ROp->getDef()->getName() == "outs" || - ROp->getDef()->getName() != "ins" || - ROp->getDef()->getName() != "defs"; - if (!LIsOps || !RIsOps) - throw "Concated Dag operators do not match!"; - } + if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef()) + throw "Concated Dag operators do not match!"; std::vector<Init*> Args; std::vector<std::string> ArgNames; for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) { diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm index 1fa3fdf..f67794e 100755 --- a/utils/buildit/build_llvm +++ b/utils/buildit/build_llvm @@ -106,11 +106,10 @@ if [ "x$RC_ProjectName" = "xllvmCore_EmbeddedHosted" ]; then # Try to use the platform llvm-gcc. Fall back to gcc if it's not available. for prog in gcc g++ ; do P=$DIR/bin/arm-apple-darwin$DARWIN_VERS-${prog} -# FIXME: Uncomment once llvm-gcc works for this -# T=`xcrun -find llvm-${prog}` -# if [ "x$T" = "x" ] ; then + T=`xcrun -find llvm-${prog}` + if [ "x$T" = "x" ] ; then T=`xcrun -sdk $SDKROOT -find ${prog}` -# fi + fi echo '#!/bin/sh' > $P || exit 1 echo 'exec '$T' -arch armv6 -isysroot '${SDKROOT}' "$@"' >> $P || exit 1 chmod a+x $P || exit 1 diff --git a/utils/lit/lit/ExampleTests/Clang/lit.cfg b/utils/lit/lit/ExampleTests/Clang/lit.cfg index 114ac60..1e1e807 100644 --- a/utils/lit/lit/ExampleTests/Clang/lit.cfg +++ b/utils/lit/lit/ExampleTests/Clang/lit.cfg @@ -41,40 +41,7 @@ def inferClang(PATH): return clang -def inferClangCC(clang, PATH): - clangcc = os.getenv('CLANGCC') - - # If the user set clang in the environment, definitely use that and don't - # try to validate. - if clangcc: - return clangcc - - # Otherwise try adding -cc since we expect to be looking in a build - # directory. - if clang.endswith('.exe'): - clangccName = clang[:-4] + '-cc.exe' - else: - clangccName = clang + '-cc' - clangcc = lit.util.which(clangccName, PATH) - if not clangcc: - # Otherwise ask clang. - res = lit.util.capture([clang, '-print-prog-name=clang-cc']) - res = res.strip() - if res and os.path.exists(res): - clangcc = res - - if not clangcc: - lit.fatal("couldn't find 'clang-cc' program, try setting " - "CLANGCC in your environment") - - return clangcc - clang = inferClang(config.environment['PATH']) if not lit.quiet: lit.note('using clang: %r' % clang) config.substitutions.append( (' clang ', ' ' + clang + ' ') ) - -clang_cc = inferClangCC(clang, config.environment['PATH']) -if not lit.quiet: - lit.note('using clang-cc: %r' % clang_cc) -config.substitutions.append( (' clang-cc ', ' ' + clang_cc + ' ') ) diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py index 0e0a493..9b62470 100644 --- a/utils/lit/lit/LitConfig.py +++ b/utils/lit/lit/LitConfig.py @@ -15,7 +15,7 @@ class LitConfig: import Util as util def __init__(self, progname, path, quiet, - useValgrind, valgrindArgs, + useValgrind, valgrindLeakCheck, valgrindArgs, useTclAsSh, noExecute, debug, isWindows, params): @@ -25,7 +25,8 @@ class LitConfig: self.path = list(map(str, path)) self.quiet = bool(quiet) self.useValgrind = bool(useValgrind) - self.valgrindArgs = list(valgrindArgs) + self.valgrindLeakCheck = bool(valgrindLeakCheck) + self.valgrindUserArgs = list(valgrindArgs) self.useTclAsSh = bool(useTclAsSh) self.noExecute = noExecute self.debug = debug @@ -36,6 +37,22 @@ class LitConfig: self.numErrors = 0 self.numWarnings = 0 + self.valgrindArgs = [] + self.valgrindTriple = "" + if self.useValgrind: + self.valgrindTriple = "-vg" + self.valgrindArgs = ['valgrind', '-q', '--run-libc-freeres=no', + '--tool=memcheck', '--trace-children=yes', + '--error-exitcode=123'] + if self.valgrindLeakCheck: + self.valgrindTriple += "_leak" + self.valgrindArgs.append('--leak-check=full') + else: + # The default is 'summary'. + self.valgrindArgs.append('--leak-check=no') + self.valgrindArgs.extend(self.valgrindUserArgs) + + def load_config(self, config, path): """load_config(config, path) - Load a config object from an alternate path.""" diff --git a/utils/lit/lit/LitFormats.py b/utils/lit/lit/LitFormats.py index 270f087..e86f103 100644 --- a/utils/lit/lit/LitFormats.py +++ b/utils/lit/lit/LitFormats.py @@ -1,3 +1,2 @@ from TestFormats import GoogleTest, ShTest, TclTest from TestFormats import SyntaxCheckTest, OneCommandPerFileTest - diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py index 6ab3f9c..433e39a 100644 --- a/utils/lit/lit/TestFormats.py +++ b/utils/lit/lit/TestFormats.py @@ -73,12 +73,7 @@ class GoogleTest(object): cmd = [testPath, '--gtest_filter=' + testName] if litConfig.useValgrind: - valgrindArgs = ['valgrind', '-q', - '--tool=memcheck', '--trace-children=yes', - '--error-exitcode=123'] - valgrindArgs.extend(litConfig.valgrindArgs) - - cmd = valgrindArgs + cmd + cmd = litConfig.valgrindArgs + cmd out, err, exitCode = TestRunner.executeCommand( cmd, env=test.config.environment) diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index 20fbc6c..29adff2 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -252,6 +252,14 @@ def executeTclScriptInternal(test, litConfig, tmpBase, commands, cwd): except: return (Test.FAIL, "Tcl 'exec' parse error on: %r" % ln) + if litConfig.useValgrind: + for pipeline in cmds: + if pipeline.commands: + # Only valgrind the first command in each pipeline, to avoid + # valgrinding things like grep, not, and FileCheck. + cmd = pipeline.commands[0] + cmd.args = litConfig.valgrindArgs + cmd.args + cmd = cmds[0] for c in cmds[1:]: cmd = ShUtil.Seq(cmd, '&&', c) @@ -327,12 +335,7 @@ def executeScript(test, litConfig, tmpBase, commands, cwd): if litConfig.useValgrind: # FIXME: Running valgrind on sh is overkill. We probably could just # run on clang with no real loss. - valgrindArgs = ['valgrind', '-q', - '--tool=memcheck', '--trace-children=yes', - '--error-exitcode=123'] - valgrindArgs.extend(litConfig.valgrindArgs) - - command = valgrindArgs + command + command = litConfig.valgrindArgs + command return executeCommand(command, cwd=cwd, env=test.config.environment) diff --git a/utils/lit/lit/lit.py b/utils/lit/lit/lit.py index f1f19c4..e800754 100755 --- a/utils/lit/lit/lit.py +++ b/utils/lit/lit/lit.py @@ -362,6 +362,9 @@ def main(): group.add_option("", "--vg", dest="useValgrind", help="Run tests under valgrind", action="store_true", default=False) + group.add_option("", "--vg-leak", dest="valgrindLeakCheck", + help="Check for memory leaks under valgrind", + action="store_true", default=False) group.add_option("", "--vg-arg", dest="valgrindArgs", metavar="ARG", help="Specify an extra argument for valgrind", type=str, action="append", default=[]) @@ -411,7 +414,14 @@ def main(): gSiteConfigName = '%s.site.cfg' % opts.configPrefix if opts.numThreads is None: - opts.numThreads = Util.detectCPUs() +# Python <2.5 has a race condition causing lit to always fail with numThreads>1 +# http://bugs.python.org/issue1731717 +# I haven't seen this bug occur with 2.5.2 and later, so only enable multiple +# threads by default there. + if sys.hexversion >= 0x2050200: + opts.numThreads = Util.detectCPUs() + else: + opts.numThreads = 1 inputs = args @@ -429,6 +439,7 @@ def main(): path = opts.path, quiet = opts.quiet, useValgrind = opts.useValgrind, + valgrindLeakCheck = opts.valgrindLeakCheck, valgrindArgs = opts.valgrindArgs, useTclAsSh = opts.useTclAsSh, noExecute = opts.noExecute, |