// Copyright Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #include #include #include #include "TestContext.hpp" #include #include #include #include #include #include #include using namespace rocRoller; using namespace Catch::Matchers; namespace RemoveImplicitSchedulingTest { TEST_CASE("RemoveImplicitScheduling handles empty graph", "[kernel-graph][graph-transforms]") { using namespace rocRoller::KernelGraph::ControlGraph; rocRoller::KernelGraph::KernelGraph graph; auto kernel = graph.control.addElement(Kernel()); // Apply transform on graph with no multiply nodes auto transformedGraph = rocRoller::KernelGraph::RemoveImplicitScheduling().apply(graph); // Graph structure should be unchanged CHECK(transformedGraph.control.getNodes().to().size() == graph.control.getNodes().to().size()); } TEST_CASE("RemoveImplicitScheduling works with unrolled loops", "[kernel-graph][graph-transforms]") { using namespace rocRoller::KernelGraph; auto dataTypeAB = GENERATE(DataType::Float, DataType::FP4); DYNAMIC_SECTION("dataTypeAB=" << dataTypeAB) { auto dataTypeCD = dataTypeAB == DataType::Float ? DataType::Float : DataType::Half; auto example = rocRollerTest::Graphs::GEMM(dataTypeAB, dataTypeAB, dataTypeCD, dataTypeCD); auto context = TestContext::ForDefaultTarget(); example.setUseLDS(true, true, false); example.setPrefetch(true, 2, 1, true); if(dataTypeAB == DataType::Float) { example.setMFMA(32, 32, 2, 1); example.setTileSize(128, 128, 16); } else { example.setTileSize(128, 128, 256); example.setMFMA(16, 16, 128, 1); example.setScaling(Operations::ScaleMode::Separate, Operations::ScaleMode::Separate, DataType::E8M0, DataType::E8M0, 32); example.setScaleLoadPaths(SolutionParams::LoadPath::BufferToLDS, SolutionParams::LoadPath::BufferToLDS); } auto graph = example.getKernelGraph(); auto params = example.getCommandParameters(); // Apply full transform pipeline up to RemoveImplicitScheduling graph = transform(graph); graph = transform(graph, true); graph = transform(graph, params); graph = transform(graph, params, context.get()); graph = transform(graph, context.get()); graph = transform(graph, params, context.get()); graph = transform(graph, params, context.get()); graph = transform(graph); graph = transform(graph); graph = transform(graph); graph = transform(graph, context.get()); graph = transform(graph, params, context.get()); graph = transform(graph); graph = transform(graph); graph = transform(graph); graph = transform(graph); graph = transform(graph); graph = transform(graph, params, context.get()); auto multiplyNodesBefore = graph.control.getNodes().to(); REQUIRE(!multiplyNodesBefore.empty()); // Apply RemoveImplicitScheduling auto transformedGraph = transform(graph); REQUIRE(!multiplyNodesBefore.empty()); auto colouring = rocRoller::KernelGraph::colourByUnrollValue(graph); REQUIRE(!multiplyNodesBefore.empty()); auto multiplyNodesAfter = transformedGraph.control.getNodes().to(); CHECK(multiplyNodesAfter == multiplyNodesBefore); std::set> orderedPairsBefore; for(auto iter = multiplyNodesBefore.begin(); iter != multiplyNodesBefore.end(); ++iter) { for(auto iter2 = std::next(iter); iter2 != multiplyNodesBefore.end(); ++iter2) { if(graph.control.compareNodes(UpdateCache, *iter, *iter2) != ControlGraph::NodeOrdering::Undefined) { orderedPairsBefore.insert({*iter, *iter2}); } } } int newlyUnorderedPairs = 0; for(auto const& [node1, node2] : orderedPairsBefore) { auto order = transformedGraph.control.compareNodes(UpdateCache, node1, node2); if(order == ControlGraph::NodeOrdering::Undefined) { CHECK(colouring.operationColour.at(node1) != colouring.operationColour.at(node2)); newlyUnorderedPairs++; } else { CHECK(order == graph.control.compareNodes(UpdateCache, node1, node2)); } } CHECK(newlyUnorderedPairs > 0); } } } // namespace RemoveImplicitSchedulingTest