summaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
authorAndrew V. Tischenko <andrew.v.tischenko@gmail.com>2018-07-31 12:33:48 +0000
committerAndrew V. Tischenko <andrew.v.tischenko@gmail.com>2018-07-31 12:33:48 +0000
commitb80d74e072c10a1946aa711ae0f7f13b31c671fe (patch)
treedeba1ea70fb0632d58f35e136b59a80a67288cbb /utils/TableGen
parentf8c29cb84b8dc447ae8e9d8c7f5132050334cdbb (diff)
[X86] Improved sched models for X86 BT*rr instructions.
https://reviews.llvm.org/D49243 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338365 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp92
-rw-r--r--utils/TableGen/CodeGenSchedule.h2
2 files changed, 94 insertions, 0 deletions
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index 9331fadf409..ebfdd36577a 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -21,6 +21,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"
@@ -33,6 +34,16 @@ using namespace llvm;
#define DEBUG_TYPE "subtarget-emitter"
+#ifdef EXPENSIVE_CHECKS
+// FIXME: TableGen is failed iff EXPENSIVE_CHECKS defined
+static constexpr bool OptCheckSchedClasses = true;
+#else
+// FIXME: the default value should be false
+static cl::opt<bool> OptCheckSchedClasses(
+ "check-sched-class-table", cl::init(true), cl::Hidden,
+ cl::desc("Check sched class table on different types of inconsistencies"));
+#endif
+
#ifndef NDEBUG
static void dumpIdxVec(ArrayRef<unsigned> V) {
for (unsigned Idx : V)
@@ -223,6 +234,7 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
collectOptionalProcessorInfo();
checkCompleteness();
+ checkSchedClasses();
}
void CodeGenSchedModels::collectRetireControlUnits() {
@@ -699,6 +711,86 @@ void CodeGenSchedModels::collectSchedClasses() {
}
}
+void CodeGenSchedModels::checkSchedClasses() {
+ if (!OptCheckSchedClasses)
+ return;
+
+ std::string str;
+ raw_string_ostream OS(str);
+
+ // Check each instruction for each model to see if its overridden too often.
+ // Iff YES it's a candidate for more fine-grained Sched Class.
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ StringRef InstName = Inst->TheDef->getName();
+ unsigned SCIdx = getSchedClassIdx(*Inst);
+ if (!SCIdx)
+ continue;
+ CodeGenSchedClass &SC = getSchedClass(SCIdx);
+ if (SC.Writes.empty())
+ continue;
+ const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
+ if (RWDefs.empty())
+ continue;
+ // FIXME: what should be threshold here?
+ if (RWDefs.size() > (ProcModels.size() / 2)) {
+ // FIXME: this dump hangs the execution !!!
+ // SC.dump(&Target.getSchedModels());
+ OS << "SchedRW machine model for inst '" << InstName << "' (";
+ for (auto I : SC.Writes)
+ OS << " " << SchedWrites[I].Name;
+ for (auto I : SC.Reads)
+ OS << " " << SchedReads[I].Name;
+ OS << " ) should be updated /improvedbecause it's overriden " << RWDefs.size()
+ << " times out of " << ProcModels.size() << " models:\n\t";
+ for (Record *RWDef : RWDefs)
+ OS << " " << getProcModel(RWDef->getValueAsDef("SchedModel")).ModelName;
+ PrintWarning(OS.str());
+ str.clear();
+ }
+
+ // TODO: here we should check latency/uop in SC vs. RWDef. Maybe we
+ // should do it iff RWDefs.size() == 1 only.
+ // Iff latency/uop are the same then warn about unnecessary redefine.
+ if (RWDefs.size()) {
+ for (Record *RWDef : RWDefs) {
+ IdxVec Writes;
+ IdxVec Reads;
+ findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"), Writes,
+ Reads);
+
+ if ((Writes.size() == SC.Writes.size()) &&
+ (Reads.size() == SC.Reads.size())) {
+ // TODO: do we need sorting Write & Reads?
+ for (unsigned I = 0, S = SC.Writes.size(); I < S; I++) {
+ auto SCSchedW = SchedWrites[SC.Writes[I]];
+ auto SchedW = SchedWrites[Writes[I]];
+ if (!SCSchedW.TheDef || !SchedW.TheDef)
+ continue;
+ const RecordVal *R = SCSchedW.TheDef->getValue("Latency");
+ // FIXME: We should deal with default Latency here
+ if (!R || !R->getValue())
+ continue;
+ auto SCLat = SCSchedW.TheDef->getValueAsInt("Latency");
+ auto SCuOp = SCSchedW.TheDef->getValueAsInt("NumMicroOps");
+ auto Lat = SchedW.TheDef->getValueAsInt("Latency");
+ auto uOp = SchedW.TheDef->getValueAsInt("NumMicroOps");
+ if ((SCLat == Lat) && (SCuOp == uOp))
+ OS << "Overridden verion of inst '" << InstName
+ << "' has the same latency & uOp values as the original one "
+ "for model '"
+ << getProcModel(RWDef->getValueAsDef("SchedModel")).ModelName
+ << "'\n";
+ }
+ if (!str.empty()) {
+ PrintWarning(OS.str());
+ str.clear();
+ }
+ }
+ }
+ }
+ }
+}
+
// Get the SchedClass index for an instruction.
unsigned
CodeGenSchedModels::getSchedClassIdx(const CodeGenInstruction &Inst) const {
diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h
index 07c11596ade..ce53d67bd81 100644
--- a/utils/TableGen/CodeGenSchedule.h
+++ b/utils/TableGen/CodeGenSchedule.h
@@ -443,6 +443,8 @@ private:
void collectSchedClasses();
+ void checkSchedClasses();
+
void collectRetireControlUnits();
void collectRegisterFiles();