From df43d03b63f81c4c0b33e5b10b9d7a924ae97cfe Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Thu, 24 Jun 2021 18:18:51 -0700 Subject: [PATCH 1/4] Remove DataDepGraph's latency precision member This member was only used in a particular subclass, so it should belong to that subclass. --- include/opt-sched/Scheduler/data_dep.h | 3 +-- lib/Scheduler/data_dep.cpp | 4 +--- lib/Wrapper/OptSchedDDGWrapperBasic.cpp | 21 ++++++++++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/include/opt-sched/Scheduler/data_dep.h b/include/opt-sched/Scheduler/data_dep.h index da2e6eab..4a5c8f25 100644 --- a/include/opt-sched/Scheduler/data_dep.h +++ b/include/opt-sched/Scheduler/data_dep.h @@ -173,7 +173,7 @@ class DataDepGraph : public llvm::opt_sched::OptSchedDDGWrapperBase, public DirAcycGraph, public DataDepStruct { public: - DataDepGraph(MachineModel *machMdl, LATENCY_PRECISION ltncyPcsn); + DataDepGraph(MachineModel *machMdl); virtual ~DataDepGraph(); // Reads the data dependence graph from a text file. @@ -367,7 +367,6 @@ class DataDepGraph : public llvm::opt_sched::OptSchedDDGWrapperBase, int entryInstCnt_; int exitInstCnt_; - LATENCY_PRECISION ltncyPrcsn_; int edgeCntPerLtncy_[MAX_LATENCY_VALUE + 1]; // Tracks all registers in the scheduling region. Each RegisterFile diff --git a/lib/Scheduler/data_dep.cpp b/lib/Scheduler/data_dep.cpp index 1a31ae63..6c67fc42 100644 --- a/lib/Scheduler/data_dep.cpp +++ b/lib/Scheduler/data_dep.cpp @@ -144,8 +144,7 @@ InstCount DataDepStruct::CmputAbslutUprBound_() { return schedUprBound_; } -DataDepGraph::DataDepGraph(MachineModel *machMdl, LATENCY_PRECISION ltncyPrcsn) - : DataDepStruct(machMdl) { +DataDepGraph::DataDepGraph(MachineModel *machMdl) : DataDepStruct(machMdl) { int i; type_ = DGT_FULL; @@ -154,7 +153,6 @@ DataDepGraph::DataDepGraph(MachineModel *machMdl, LATENCY_PRECISION ltncyPrcsn) weight_ = 1.0; outptDags_ = ODG_ALL; maxOutptDagSize_ = 1000; - ltncyPrcsn_ = ltncyPrcsn; includesCall_ = false; includesUnpipelined_ = false; diff --git a/lib/Wrapper/OptSchedDDGWrapperBasic.cpp b/lib/Wrapper/OptSchedDDGWrapperBasic.cpp index d90ec76e..c38b038b 100644 --- a/lib/Wrapper/OptSchedDDGWrapperBasic.cpp +++ b/lib/Wrapper/OptSchedDDGWrapperBasic.cpp @@ -52,8 +52,8 @@ OptSchedDDGWrapperBasic::OptSchedDDGWrapperBasic( MachineSchedContext *Context, ScheduleDAGOptSched *DAG, OptSchedMachineModel *MM, LATENCY_PRECISION LatencyPrecision, const std::string &RegionID) - : DataDepGraph(MM, LatencyPrecision), MM(MM), Contex(Context), DAG(DAG), - RTFilter(nullptr) { + : DataDepGraph(MM), MM(MM), Contex(Context), DAG(DAG), + LatencyPrecision(LatencyPrecision), RTFilter(nullptr) { dagFileFormat_ = DFF_BB; isTraceFormat_ = false; TreatOrderDepsAsDataDeps = @@ -447,11 +447,14 @@ void OptSchedDDGWrapperBasic::convertEdges(const SUnit &SU, } int16_t Latency; - if (ltncyPrcsn_ == LTP_PRECISE) { // get latency from the machine model + switch (LatencyPrecision) { + case LTP_PRECISE: { // get latency from the machine model const auto &InstName = DAG->TII->getName(instr->getOpcode()); const auto &InstType = MM->GetInstTypeByName(InstName); Latency = MM->GetLatency(InstType, DepType); - } else if (ltncyPrcsn_ == LTP_ROUGH) { // rough latency = llvm latency + break; + } + case LTP_ROUGH: { // rough latency = llvm latency Latency = I->getLatency(); // If latency is above a specified target then reduce the latency // by the specified divisor @@ -468,12 +471,16 @@ void OptSchedDDGWrapperBasic::convertEdges(const SUnit &SU, Logger::Event("ReduceLatency", "FromInstruction", InstFromName.c_str(), "ToInstruction", InstToName.c_str(), "OriginalLatency", OldLatency, "NewLatency", Latency); + break; } - } else + } + case LTP_UNITY: Latency = 1; // unit latency = ignore ilp - CreateEdge_(SU.NodeNum, I->getSUnit()->NodeNum, Latency, DepType, - IsArtificial); + CreateEdge_(SU.NodeNum, I->getSUnit()->NodeNum, Latency, DepType, + IsArtificial); + break; + } } } From 4556a006c5d70891d0492286c8b8d0a6ed7377b4 Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Thu, 24 Jun 2021 18:34:48 -0700 Subject: [PATCH 2/4] Simplify creating DataDepGraph for tests Allow it to be made from a string. --- include/opt-sched/Scheduler/data_dep.h | 1 + lib/Scheduler/data_dep.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/include/opt-sched/Scheduler/data_dep.h b/include/opt-sched/Scheduler/data_dep.h index 4a5c8f25..54da1004 100644 --- a/include/opt-sched/Scheduler/data_dep.h +++ b/include/opt-sched/Scheduler/data_dep.h @@ -178,6 +178,7 @@ class DataDepGraph : public llvm::opt_sched::OptSchedDDGWrapperBase, // Reads the data dependence graph from a text file. FUNC_RESULT ReadFrmFile(SpecsBuffer *buf, bool &endOfFileReached); + FUNC_RESULT ReadFromString(const std::string &Str); // Continues reading until the end of the current graph definition, // discarding the data. FUNC_RESULT SkipGraph(SpecsBuffer *buf, bool &endOfFileReached); diff --git a/lib/Scheduler/data_dep.cpp b/lib/Scheduler/data_dep.cpp index 6c67fc42..b4ed8126 100644 --- a/lib/Scheduler/data_dep.cpp +++ b/lib/Scheduler/data_dep.cpp @@ -337,6 +337,16 @@ void DataDepGraph::SetDynmcLwrBounds() { } } +FUNC_RESULT DataDepGraph::ReadFromString(const std::string &Str) { + char *BufData = new char[Str.size() + 1]; + std::copy_n(Str.data(), Str.size() + 1, BufData); + SpecsBuffer Buf; + Buf.SetBuf(BufData, Str.size() + 1); + + bool EndReached = false; + return ReadFrmFile(&Buf, EndReached); +} + FUNC_RESULT DataDepGraph::ReadFrmFile(SpecsBuffer *buf, bool &endOfFileReached) { int pieceCnt; From bf32b468e75a5e6f9768c22800c50f027e01c353 Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Thu, 24 Jun 2021 19:47:27 -0700 Subject: [PATCH 3/4] Add test utility to create a DataDepGraph --- unittests/Basic/CMakeLists.txt | 1 + unittests/Basic/ddg.h | 45 +++++++++++++ unittests/Basic/ddg_test.cpp | 114 +++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 unittests/Basic/ddg.h create mode 100644 unittests/Basic/ddg_test.cpp diff --git a/unittests/Basic/CMakeLists.txt b/unittests/Basic/CMakeLists.txt index 8009c25d..76cf3b16 100644 --- a/unittests/Basic/CMakeLists.txt +++ b/unittests/Basic/CMakeLists.txt @@ -5,4 +5,5 @@ add_optsched_unittest(OptSchedBasicTests LoggerTest.cpp UtilitiesTest.cpp simple_machine_model_test.cpp + ddg_test.cpp ) diff --git a/unittests/Basic/ddg.h b/unittests/Basic/ddg.h new file mode 100644 index 00000000..49087de6 --- /dev/null +++ b/unittests/Basic/ddg.h @@ -0,0 +1,45 @@ +#ifndef OPTSCHED_TESTS_DDG_H +#define OPTSCHED_TESTS_DDG_H + +#include "opt-sched/Scheduler/data_dep.h" +#include "simple_machine_model.h" +#include "gtest/gtest.h" +#include +#include + +std::shared_ptr +makeDDG(const std::string &DDG, + llvm::opt_sched::MachineModel *Model = nullptr) { + using namespace llvm::opt_sched; + + class SimpleDDG : public DataDepGraph { + public: + using DataDepGraph::DataDepGraph; + + void convertSUnits(bool, bool) override { + FAIL() << "Unsupported operation convertSUnits()"; + } + void convertRegFiles() override { + FAIL() << "Unsupported operation convertRegFile()"; + } + }; + + struct DDGData { + std::unique_ptr Model = nullptr; + SimpleDDG DDG; + + DDGData(MachineModel *Model) : DDG(Model) {} + DDGData() + : Model(llvm::make_unique(simpleMachineModel())), + DDG(Model.get()) {} + }; + + auto Result = + Model ? std::make_shared(Model) : std::make_shared(); + auto Ret = Result->DDG.ReadFromString(DDG); + EXPECT_TRUE(Ret != RES_ERROR && Ret != RES_FAIL && Ret != RES_TIMEOUT) + << "Failed to parse DDG"; + return std::shared_ptr(Result, &Result->DDG); +} + +#endif diff --git a/unittests/Basic/ddg_test.cpp b/unittests/Basic/ddg_test.cpp new file mode 100644 index 00000000..f76ffbdd --- /dev/null +++ b/unittests/Basic/ddg_test.cpp @@ -0,0 +1,114 @@ +#include "ddg.h" + +#include "gtest/gtest.h" + +using namespace llvm::opt_sched; + +namespace { +TEST(SimpleDDG, CanBeMade) { + std::shared_ptr DDG = makeDDG(R"( +dag 7 "Simple" +{ +dag_id fake:3 +dag_weight 1.000000 +compiler LLVM +dag_lb -1 +dag_ub -1 +nodes +node 0 "Inst" + sched_order 0 + issue_cycle 0 +node 1 "Inst" + sched_order 1 + issue_cycle 1 +node 2 "Inst" + sched_order 2 + issue_cycle 2 +node 3 "Inst" + sched_order 3 + issue_cycle 3 +node 4 "Inst" + sched_order 4 + issue_cycle 4 +node 5 "artificial" "__optsched_entry" +node 6 "artificial" +dependencies +dep 0 1 "other" 0 +dep 1 2 "other" 0 +dep 2 6 "other" 0 +dep 3 4 "data" 1 +dep 4 6 "other" 0 +dep 5 3 "other" 0 +dep 5 0 "other" 0 +} + )"); + + EXPECT_EQ(7, DDG->GetNodeCnt()); +} + +TEST(SimpleDDG, CanBeMadeWithRealData) { + MachineModel Model = simpleMachineModel(); + { + InstTypeInfo Info; + Info.issuType = Model.getDefaultIssueType(); + Info.name = "ATOMIC_FENCE"; + Info.isCntxtDep = false; + Info.ltncy = 0; + Info.pipelined = true; + Info.sprtd = true; + Info.blksCycle = true; + Model.AddInstType(Info); + + Info.name = "S_BARRIER"; + Model.AddInstType(Info); + + Info.name = "S_ADD_I32"; + Info.ltncy = 1; + Model.AddInstType(Info); + + Info.name = "S_CMP_LT_U32"; + Info.ltncy = 1; + Model.AddInstType(Info); + } + + std::shared_ptr DDG = makeDDG(R"( +dag 7 "Simple" +{ +dag_id kernel_c18_sdk_94:3 +dag_weight 1.000000 +compiler LLVM +dag_lb -1 +dag_ub -1 +nodes +node 0 "ATOMIC_FENCE" + sched_order 0 + issue_cycle 0 +node 1 "S_BARRIER" "S_BARRIER" + sched_order 1 + issue_cycle 1 +node 2 "ATOMIC_FENCE" "ATOMIC_FENCE" + sched_order 2 + issue_cycle 2 +node 3 "S_ADD_I32" "S_ADD_I32" + sched_order 3 + issue_cycle 3 +node 4 "S_CMP_LT_U32" "S_CMP_LT_U32" + sched_order 4 + issue_cycle 4 +node 5 "artificial" "__optsched_entry" +node 6 "artificial" +dependencies +dep 0 1 "other" 0 +dep 1 2 "other" 0 +dep 2 6 "other" 0 +dep 3 4 "data" 1 +dep 4 6 "other" 0 +dep 5 3 "other" 0 +dep 5 0 "other" 0 +} + )", + &Model); + + EXPECT_EQ(7, DDG->GetNodeCnt()); +} +} // namespace From 7b5e8e0657934060c382545156bc49a99200aa9c Mon Sep 17 00:00:00 2001 From: Justin Bassett Date: Thu, 24 Jun 2021 20:08:55 -0700 Subject: [PATCH 4/4] Add tests for rough edges --- unittests/Basic/ddg.h | 2 +- unittests/Basic/ddg_test.cpp | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/unittests/Basic/ddg.h b/unittests/Basic/ddg.h index 49087de6..5376ce70 100644 --- a/unittests/Basic/ddg.h +++ b/unittests/Basic/ddg.h @@ -20,7 +20,7 @@ makeDDG(const std::string &DDG, FAIL() << "Unsupported operation convertSUnits()"; } void convertRegFiles() override { - FAIL() << "Unsupported operation convertRegFile()"; + FAIL() << "Unsupported operation convertRegFiles()"; } }; diff --git a/unittests/Basic/ddg_test.cpp b/unittests/Basic/ddg_test.cpp index f76ffbdd..214e1dad 100644 --- a/unittests/Basic/ddg_test.cpp +++ b/unittests/Basic/ddg_test.cpp @@ -1,5 +1,6 @@ #include "ddg.h" +#include "gtest/gtest-spi.h" #include "gtest/gtest.h" using namespace llvm::opt_sched; @@ -111,4 +112,52 @@ dep 5 0 "other" 0 EXPECT_EQ(7, DDG->GetNodeCnt()); } + +TEST(SimpleDDG, VirtualFunctionsFailWell) { + static std::shared_ptr DDG = makeDDG(R"( +dag 3 "Simple" +{ +dag_id fake:3 +dag_weight 1.000000 +compiler LLVM +dag_lb -1 +dag_ub -1 +nodes +node 0 "Inst" + sched_order 0 + issue_cycle 0 +node 1 "artificial" "__optsched_entry" +node 2 "artificial" +dependencies +dep 0 1 "other" 0 +dep 1 2 "other" 0 +} + )"); + + EXPECT_FATAL_FAILURE(DDG->convertRegFiles(), + "Unsupported operation convertRegFiles"); + EXPECT_FATAL_FAILURE(DDG->convertSUnits(true, true), + "Unsupported operation convertSUnits"); +} + +TEST(SimpleDDG, MakeInvalidDDGFailsWell) { + EXPECT_NONFATAL_FAILURE(makeDDG(R"( +dag 3 "Simple" +{ +dag_id fake:3 +dag_weight 1.000000 +compiler LLVM +dag_lb -1 +dag_ub -1 +nodes +node 0 "Inst" + sched_order 0 + issue_cycle 0 +node 1 "artificial" "__optsched_entry" +node 2 "artificial" +dependencies +} + )"), + "parse DDG"); +} } // namespace