summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/FileCheck/FileCheck.cpp11
-rwxr-xr-xutils/NewNightlyTest.pl23
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp37
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp12
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.cpp2
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp8
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp683
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h97
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp61
-rw-r--r--utils/TableGen/CodeGenInstruction.h7
-rw-r--r--utils/TableGen/CodeGenTarget.cpp177
-rw-r--r--utils/TableGen/CodeGenTarget.h52
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp6
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp7
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp52
-rw-r--r--utils/TableGen/DisassemblerEmitter.cpp4
-rw-r--r--utils/TableGen/EDEmitter.cpp4
-rw-r--r--utils/TableGen/FastISelEmitter.cpp23
-rw-r--r--utils/TableGen/InstrEnumEmitter.cpp13
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp16
-rw-r--r--utils/TableGen/Record.cpp14
-rwxr-xr-xutils/buildit/build_llvm7
-rw-r--r--utils/lit/lit/ExampleTests/Clang/lit.cfg33
-rw-r--r--utils/lit/lit/LitConfig.py21
-rw-r--r--utils/lit/lit/LitFormats.py1
-rw-r--r--utils/lit/lit/TestFormats.py7
-rw-r--r--utils/lit/lit/TestRunner.py15
-rwxr-xr-xutils/lit/lit/lit.py13
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,
OpenPOWER on IntegriCloud