1 //===- Tester.cpp ---------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the Tester class used in the MLIR Reduce tool. 10 // 11 // A Tester object is passed as an argument to the reduction passes and it is 12 // used to run the interestingness testing script on the different generated 13 // reduced variants of the test case. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "mlir/Reducer/Tester.h" 18 #include "mlir/IR/Verifier.h" 19 #include "llvm/Support/ToolOutputFile.h" 20 21 using namespace mlir; 22 23 Tester::Tester(StringRef scriptName, ArrayRef<std::string> scriptArgs) 24 : testScript(scriptName), testScriptArgs(scriptArgs) {} 25 26 std::pair<Tester::Interestingness, size_t> 27 Tester::isInteresting(ModuleOp module) const { 28 // The reduced module should always be vaild, or we may end up retaining the 29 // error message by an invalid case. Besides, an invalid module may not be 30 // able to print properly. 31 if (failed(verify(module))) 32 return std::make_pair(Interestingness::False, /*size=*/0); 33 34 SmallString<128> filepath; 35 int fd; 36 37 // Print module to temporary file. 38 std::error_code ec = 39 llvm::sys::fs::createTemporaryFile("mlir-reduce", "mlir", fd, filepath); 40 41 if (ec) 42 llvm::report_fatal_error("Error making unique filename: " + ec.message()); 43 44 llvm::ToolOutputFile out(filepath, fd); 45 module.print(out.os()); 46 out.os().close(); 47 48 if (out.os().has_error()) 49 llvm::report_fatal_error("Error emitting the IR to file '" + filepath); 50 51 size_t size = out.os().tell(); 52 return std::make_pair(isInteresting(filepath), size); 53 } 54 55 /// Runs the interestingness testing script on a MLIR test case file. Returns 56 /// true if the interesting behavior is present in the test case or false 57 /// otherwise. 58 Tester::Interestingness Tester::isInteresting(StringRef testCase) const { 59 std::vector<StringRef> testerArgs; 60 testerArgs.push_back(testCase); 61 62 for (const std::string &arg : testScriptArgs) 63 testerArgs.push_back(arg); 64 65 testerArgs.push_back(testCase); 66 67 std::string errMsg; 68 int result = llvm::sys::ExecuteAndWait( 69 testScript, testerArgs, /*Env=*/None, /*Redirects=*/None, 70 /*SecondsToWait=*/0, /*MemoryLimit=*/0, &errMsg); 71 72 if (result < 0) 73 llvm::report_fatal_error("Error running interestingness test: " + errMsg, 74 false); 75 76 if (!result) 77 return Interestingness::False; 78 79 return Interestingness::True; 80 } 81