summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-26 20:32:52 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-26 20:32:52 +0000
commit08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch)
tree80108f0f128657f8623f8f66ad9735b4d88e7b47 /utils
parent7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff)
downloadsrc-test2-08bbd35a80bf7765fe0d3043f9eb5a2f2786b649.tar.gz
src-test2-08bbd35a80bf7765fe0d3043f9eb5a2f2786b649.zip
Notes
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp30
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h12
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp6
-rw-r--r--utils/TableGen/GlobalISelEmitter.cpp120
-rw-r--r--utils/TableGen/OptParserEmitter.cpp10
-rwxr-xr-xutils/opt-viewer/opt-stats.py6
-rwxr-xr-xutils/opt-viewer/opt-viewer.py4
-rw-r--r--utils/opt-viewer/optrecord.py24
-rwxr-xr-xutils/release/test-release.sh8
9 files changed, 151 insertions, 69 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 7c41d9fad696..03914ef98952 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -2762,8 +2762,8 @@ public:
AnalyzeNode(Pat->getTree(0));
}
- void Analyze(const PatternToMatch *Pat) {
- AnalyzeNode(Pat->getSrcPattern());
+ void Analyze(const PatternToMatch &Pat) {
+ AnalyzeNode(Pat.getSrcPattern());
}
private:
@@ -3220,7 +3220,7 @@ static void FindNames(const TreePatternNode *P,
}
void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
- const PatternToMatch &PTM) {
+ PatternToMatch &&PTM) {
// Do some sanity checking on the pattern we're about to match.
std::string Reason;
if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) {
@@ -3259,7 +3259,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
SrcNames[Entry.first].second == 1)
Pattern->error("Pattern has dead named input: $" + Entry.first);
- PatternsToMatch.push_back(PTM);
+ PatternsToMatch.push_back(std::move(PTM));
}
@@ -3289,9 +3289,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() {
// Second, look for single-instruction patterns defined outside the
// instruction.
- for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) {
- const PatternToMatch &PTM = *I;
-
+ for (const PatternToMatch &PTM : ptms()) {
// We can only infer from single-instruction patterns, otherwise we won't
// know which instruction should get the flags.
SmallVector<Record*, 8> PatInstrs;
@@ -3307,7 +3305,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() {
continue;
InstAnalyzer PatInfo(*this);
- PatInfo.Analyze(&PTM);
+ PatInfo.Analyze(PTM);
Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord());
}
@@ -3367,7 +3365,7 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() {
// Analyze the source pattern.
InstAnalyzer PatInfo(*this);
- PatInfo.Analyze(&PTM);
+ PatInfo.Analyze(PTM);
// Collect error messages.
SmallVector<std::string, 4> Msgs;
@@ -3553,14 +3551,12 @@ void CodeGenDAGPatterns::ParsePatterns() {
TreePattern Temp(Result.getRecord(), DstPattern, false, *this);
Temp.InferAllTypes();
-
- AddPatternToMatch(Pattern,
- PatternToMatch(CurPattern,
- CurPattern->getValueAsListInit("Predicates"),
- Pattern->getTree(0),
- Temp.getOnlyTree(), InstImpResults,
- CurPattern->getValueAsInt("AddedComplexity"),
- CurPattern->getID()));
+ AddPatternToMatch(
+ Pattern,
+ PatternToMatch(
+ CurPattern, CurPattern->getValueAsListInit("Predicates"),
+ Pattern->getTree(0), Temp.getOnlyTree(), std::move(InstImpResults),
+ CurPattern->getValueAsInt("AddedComplexity"), CurPattern->getID()));
}
}
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index 5c56fb644e7f..8b3e19142370 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -684,12 +684,12 @@ public:
/// processed to produce isel.
class PatternToMatch {
public:
- PatternToMatch(Record *srcrecord, ListInit *preds,
- TreePatternNode *src, TreePatternNode *dst,
- const std::vector<Record*> &dstregs,
+ PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNode *src,
+ TreePatternNode *dst, std::vector<Record *> dstregs,
int complexity, unsigned uid)
- : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst),
- Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {}
+ : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src),
+ DstPattern(dst), Dstregs(std::move(dstregs)),
+ AddedComplexity(complexity), ID(uid) {}
Record *SrcRecord; // Originating Record for the pattern.
ListInit *Predicates; // Top level predicate conditions to match.
@@ -853,7 +853,7 @@ private:
void GenerateVariants();
void VerifyInstructionFlags();
- void AddPatternToMatch(TreePattern *Pattern, const PatternToMatch &PTM);
+ void AddPatternToMatch(TreePattern *Pattern, PatternToMatch &&PTM);
void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
std::map<std::string,
TreePatternNode*> &InstInputs,
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index aafc1157893e..d239f96d2a60 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -848,8 +848,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
HandledReg = II.ImplicitDefs[0];
- for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
- Record *Reg = Pattern.getDstRegs()[i];
+ for (Record *Reg : Pattern.getDstRegs()) {
if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
ResultVTs.push_back(getRegisterValueType(Reg, CGT));
}
@@ -972,8 +971,7 @@ void MatcherGen::EmitResultCode() {
HandledReg = II.ImplicitDefs[0];
}
- for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
- Record *Reg = Pattern.getDstRegs()[i];
+ for (Record *Reg : Pattern.getDstRegs()) {
if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
++NumSrcResults;
}
diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp
index 88ded1f25ffb..03d231a153dc 100644
--- a/utils/TableGen/GlobalISelEmitter.cpp
+++ b/utils/TableGen/GlobalISelEmitter.cpp
@@ -158,6 +158,16 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
return failedImport(Explanation);
}
+static Record *getInitValueAsRegClass(Init *V) {
+ if (DefInit *VDefInit = dyn_cast<DefInit>(V)) {
+ if (VDefInit->getDef()->isSubClassOf("RegisterOperand"))
+ return VDefInit->getDef()->getValueAsDef("RegClass");
+ if (VDefInit->getDef()->isSubClassOf("RegisterClass"))
+ return VDefInit->getDef();
+ }
+ return nullptr;
+}
+
//===- Matchers -----------------------------------------------------------===//
class OperandMatcher;
@@ -973,6 +983,7 @@ public:
/// into the desired instruction when this is possible.
class BuildMIAction : public MatchAction {
private:
+ std::string Name;
const CodeGenInstruction *I;
const InstructionMatcher &Matched;
std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers;
@@ -996,8 +1007,9 @@ private:
}
public:
- BuildMIAction(const CodeGenInstruction *I, const InstructionMatcher &Matched)
- : I(I), Matched(Matched) {}
+ BuildMIAction(const StringRef Name, const CodeGenInstruction *I,
+ const InstructionMatcher &Matched)
+ : Name(Name), I(I), Matched(Matched) {}
template <class Kind, class... Args>
Kind &addRenderer(Args&&... args) {
@@ -1032,7 +1044,7 @@ public:
}
}
- OS << " MachineInstr &NewI = " << RecycleVarName << ";\n";
+ OS << " MachineInstr &" << Name << " = " << RecycleVarName << ";\n";
return;
}
@@ -1050,7 +1062,40 @@ public:
OS << " for (const auto &MMO : FromMI->memoperands())\n";
OS << " MIB.addMemOperand(MMO);\n";
OS << " " << RecycleVarName << ".eraseFromParent();\n";
- OS << " MachineInstr &NewI = *MIB;\n";
+ OS << " MachineInstr &" << Name << " = *MIB;\n";
+ }
+};
+
+/// Generates code to constrain the operands of an output instruction to the
+/// register classes specified by the definition of that instruction.
+class ConstrainOperandsToDefinitionAction : public MatchAction {
+ std::string Name;
+
+public:
+ ConstrainOperandsToDefinitionAction(const StringRef Name) : Name(Name) {}
+
+ void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef RecycleVarName) const override {
+ OS << " constrainSelectedInstRegOperands(" << Name << ", TII, TRI, RBI);\n";
+ }
+};
+
+/// Generates code to constrain the specified operand of an output instruction
+/// to the specified register class.
+class ConstrainOperandToRegClassAction : public MatchAction {
+ std::string Name;
+ unsigned OpIdx;
+ const CodeGenRegisterClass &RC;
+
+public:
+ ConstrainOperandToRegClassAction(const StringRef Name, unsigned OpIdx,
+ const CodeGenRegisterClass &RC)
+ : Name(Name), OpIdx(OpIdx), RC(RC) {}
+
+ void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef RecycleVarName) const override {
+ OS << " constrainOperandRegToRegClass(" << Name << ", " << OpIdx
+ << ", " << RC.getQualifiedName() << "RegClass, TII, TRI, RBI);\n";
}
};
@@ -1205,7 +1250,6 @@ void RuleMatcher::emit(raw_ostream &OS,
MA->emitCxxActionStmts(OS, *this, "I");
}
- OS << " constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);\n";
OS << " return true;\n";
OS << " }\n";
OS << " return false;\n";
@@ -1439,15 +1483,10 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher,
auto *ChildRec = ChildDefInit->getDef();
// Check for register classes.
- if (ChildRec->isSubClassOf("RegisterClass")) {
- OM.addPredicate<RegisterBankOperandMatcher>(
- Target.getRegisterClass(ChildRec));
- return Error::success();
- }
-
- if (ChildRec->isSubClassOf("RegisterOperand")) {
+ if (ChildRec->isSubClassOf("RegisterClass") ||
+ ChildRec->isSubClassOf("RegisterOperand")) {
OM.addPredicate<RegisterBankOperandMatcher>(
- Target.getRegisterClass(ChildRec->getValueAsDef("RegClass")));
+ Target.getRegisterClass(getInitValueAsRegClass(ChildDefInit)));
return Error::success();
}
@@ -1554,22 +1593,33 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
"Pattern operator isn't an instruction (it's a ValueType)");
return failedImport("Pattern operator isn't an instruction");
}
- auto &DstI = Target.getInstruction(DstOp);
+ CodeGenInstruction *DstI = &Target.getInstruction(DstOp);
+
+ unsigned DstINumUses = DstI->Operands.size() - DstI->Operands.NumDefs;
+ unsigned ExpectedDstINumUses = Dst->getNumChildren();
+
+ // COPY_TO_REGCLASS is just a copy with a ConstrainOperandToRegClassAction
+ // attached.
+ if (DstI->TheDef->getName() == "COPY_TO_REGCLASS") {
+ DstI = &Target.getInstruction(RK.getDef("COPY"));
+ DstINumUses--; // Ignore the class constraint.
+ ExpectedDstINumUses--;
+ }
- auto &DstMIBuilder = M.addAction<BuildMIAction>(&DstI, InsnMatcher);
+ auto &DstMIBuilder = M.addAction<BuildMIAction>("NewI", DstI, InsnMatcher);
// Render the explicit defs.
- for (unsigned I = 0; I < DstI.Operands.NumDefs; ++I) {
- const auto &DstIOperand = DstI.Operands[I];
+ for (unsigned I = 0; I < DstI->Operands.NumDefs; ++I) {
+ const CGIOperandList::OperandInfo &DstIOperand = DstI->Operands[I];
DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstIOperand.Name);
}
// Render the explicit uses.
unsigned Child = 0;
- unsigned DstINumUses = DstI.Operands.size() - DstI.Operands.NumDefs;
unsigned NumDefaultOps = 0;
for (unsigned I = 0; I != DstINumUses; ++I) {
- const auto &DstIOperand = DstI.Operands[DstI.Operands.NumDefs + I];
+ const CGIOperandList::OperandInfo &DstIOperand =
+ DstI->Operands[DstI->Operands.NumDefs + I];
// If the operand has default values, introduce them now.
// FIXME: Until we have a decent test case that dictates we should do
@@ -1590,10 +1640,10 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
++Child;
}
- if (NumDefaultOps + Dst->getNumChildren() != DstINumUses)
+ if (NumDefaultOps + ExpectedDstINumUses != DstINumUses)
return failedImport("Expected " + llvm::to_string(DstINumUses) +
" used operands but found " +
- llvm::to_string(Dst->getNumChildren()) +
+ llvm::to_string(ExpectedDstINumUses) +
" explicit ones and " + llvm::to_string(NumDefaultOps) +
" default ones");
@@ -1684,10 +1734,16 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
const auto &DstIOperand = DstI.Operands[OpIdx];
Record *DstIOpRec = DstIOperand.Rec;
- if (DstIOpRec->isSubClassOf("RegisterOperand"))
+ if (DstI.TheDef->getName() == "COPY_TO_REGCLASS") {
+ DstIOpRec = getInitValueAsRegClass(Dst->getChild(1)->getLeafValue());
+
+ if (DstIOpRec == nullptr)
+ return failedImport(
+ "COPY_TO_REGCLASS operand #1 isn't a register class");
+ } else if (DstIOpRec->isSubClassOf("RegisterOperand"))
DstIOpRec = DstIOpRec->getValueAsDef("RegClass");
- if (!DstIOpRec->isSubClassOf("RegisterClass"))
- return failedImport("Dst MI def isn't a register class");
+ else if (!DstIOpRec->isSubClassOf("RegisterClass"))
+ return failedImport("Dst MI def isn't a register class" + to_string(*Dst));
OperandMatcher &OM = InsnMatcher.getOperand(OpIdx);
OM.setSymbolicName(DstIOperand.Name);
@@ -1707,6 +1763,22 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
if (auto Error = importImplicitDefRenderers(DstMIBuilder, P.getDstRegs()))
return std::move(Error);
+ // Constrain the registers to classes. This is normally derived from the
+ // emitted instruction but a few instructions require special handling.
+ if (DstI.TheDef->getName() == "COPY_TO_REGCLASS") {
+ // COPY_TO_REGCLASS does not provide operand constraints itself but the
+ // result is constrained to the class given by the second child.
+ Record *DstIOpRec =
+ getInitValueAsRegClass(Dst->getChild(1)->getLeafValue());
+
+ if (DstIOpRec == nullptr)
+ return failedImport("COPY_TO_REGCLASS operand #1 isn't a register class");
+
+ M.addAction<ConstrainOperandToRegClassAction>(
+ "NewI", 0, Target.getRegisterClass(DstIOpRec));
+ } else
+ M.addAction<ConstrainOperandsToDefinitionAction>("NewI");
+
// We're done with this pattern! It's eligible for GISel emission; return it.
++NumPatternImported;
return std::move(M);
diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp
index 04e6537f3d15..e3777d036a23 100644
--- a/utils/TableGen/OptParserEmitter.cpp
+++ b/utils/TableGen/OptParserEmitter.cpp
@@ -196,6 +196,9 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << ", nullptr";
// The option meta-variable name (unused).
+ OS << ", nullptr";
+
+ // The option Values (unused for groups).
OS << ", nullptr)\n";
}
OS << "\n";
@@ -285,6 +288,13 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
else
OS << "nullptr";
+ // The option Values. Used for shell autocompletion.
+ OS << ", ";
+ if (!isa<UnsetInit>(R.getValueInit("Values")))
+ write_cstring(OS, R.getValueAsString("Values"));
+ else
+ OS << "nullptr";
+
OS << ")\n";
}
OS << "#endif // OPTION\n";
diff --git a/utils/opt-viewer/opt-stats.py b/utils/opt-viewer/opt-stats.py
index 7ce935b492c5..79e5c03eca9f 100755
--- a/utils/opt-viewer/opt-stats.py
+++ b/utils/opt-viewer/opt-stats.py
@@ -24,10 +24,6 @@ if __name__ == '__main__':
help='Max job count (defaults to %(default)s, the current CPU count)')
args = parser.parse_args()
- if len(args.yaml_files) == 0:
- parser.print_help()
- sys.exit(1)
-
if args.jobs == 1:
pmap = map
else:
@@ -38,7 +34,7 @@ if __name__ == '__main__':
bypass = defaultdict(int)
byname = defaultdict(int)
- for r in all_remarks.itervalues():
+ for r in optrecord.itervalues(all_remarks):
bypass[r.Pass] += 1
byname[r.Pass + "/" + r.Name] += 1
diff --git a/utils/opt-viewer/opt-viewer.py b/utils/opt-viewer/opt-viewer.py
index 5e076d86dbe9..3f5503f26b1f 100755
--- a/utils/opt-viewer/opt-viewer.py
+++ b/utils/opt-viewer/opt-viewer.py
@@ -216,10 +216,6 @@ if __name__ == '__main__':
help='set source directory')
args = parser.parse_args()
- if len(args.yaml_files) == 0:
- parser.print_help()
- sys.exit(1)
-
if args.jobs == 1:
pmap = map
else:
diff --git a/utils/opt-viewer/optrecord.py b/utils/opt-viewer/optrecord.py
index 2f930a48a056..6dc1a32e536a 100644
--- a/utils/opt-viewer/optrecord.py
+++ b/utils/opt-viewer/optrecord.py
@@ -24,14 +24,32 @@ p = subprocess.Popen(['c++filt', '-n'], stdin=subprocess.PIPE, stdout=subprocess
p_lock = Lock()
+try:
+ dict.iteritems
+except AttributeError:
+ # Python 3
+ def itervalues(d):
+ return iter(d.values())
+ def iteritems(d):
+ return iter(d.items())
+else:
+ # Python 2
+ def itervalues(d):
+ return d.itervalues()
+ def iteritems(d):
+ return d.iteritems()
+
+
def demangle(name):
with p_lock:
p.stdin.write(name + '\n')
return p.stdout.readline().rstrip()
+
def html_file_name(filename):
return filename.replace('/', '_') + ".html"
+
def make_link(File, Line):
return "\"{}#L{}\"".format(html_file_name(File), Line)
@@ -117,7 +135,7 @@ class Remark(yaml.YAMLObject):
def key(self):
k = (self.__class__, self.PassWithDiffPrefix, self.Name, self.File, self.Line, self.Column, self.Function)
for arg in self.Args:
- for (key, value) in arg.iteritems():
+ for (key, value) in iteritems(arg):
if type(value) is dict:
value = tuple(value.items())
k += (key, value)
@@ -196,8 +214,8 @@ def gather_results(pmap, filenames):
max_hotness = max(entry[0] for entry in remarks)
def merge_file_remarks(file_remarks_job, all_remarks, merged):
- for filename, d in file_remarks_job.iteritems():
- for line, remarks in d.iteritems():
+ for filename, d in iteritems(file_remarks_job):
+ for line, remarks in iteritems(d):
for remark in remarks:
# Bring max_hotness into the remarks so that
# RelativeHotness does not depend on an external global.
diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh
index 560220cd53f4..8ec3abb17551 100755
--- a/utils/release/test-release.sh
+++ b/utils/release/test-release.sh
@@ -38,7 +38,7 @@ do_test_suite="yes"
do_openmp="yes"
do_lld="yes"
do_lldb="no"
-do_polly="no"
+do_polly="yes"
BuildDir="`pwd`"
ExtraConfigureFlags=""
ExportBranch=""
@@ -68,8 +68,7 @@ function usage() {
echo " -no-lld Disable check-out & build lld"
echo " -lldb Enable check-out & build lldb"
echo " -no-lldb Disable check-out & build lldb (default)"
- echo " -polly Enable check-out & build Polly"
- echo " -no-polly Disable check-out & build Polly (default)"
+ echo " -no-polly Disable check-out & build Polly"
}
while [ $# -gt 0 ]; do
@@ -154,9 +153,6 @@ while [ $# -gt 0 ]; do
-no-lldb )
do_lldb="no"
;;
- -polly )
- do_polly="yes"
- ;;
-no-polly )
do_polly="no"
;;