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(llvm::Twine("Error making unique filename: ") + 43 ec.message()); 44 45 llvm::ToolOutputFile out(filepath, fd); 46 module.print(out.os()); 47 out.os().close(); 48 49 if (out.os().has_error()) 50 llvm::report_fatal_error(llvm::Twine("Error emitting the IR to file '") + 51 filepath); 52 53 size_t size = out.os().tell(); 54 return std::make_pair(isInteresting(filepath), size); 55 } 56 57 /// Runs the interestingness testing script on a MLIR test case file. Returns 58 /// true if the interesting behavior is present in the test case or false 59 /// otherwise. 60 Tester::Interestingness Tester::isInteresting(StringRef testCase) const { 61 std::vector<StringRef> testerArgs; 62 testerArgs.push_back(testCase); 63 64 for (const std::string &arg : testScriptArgs) 65 testerArgs.emplace_back(arg); 66 67 testerArgs.push_back(testCase); 68 69 std::string errMsg; 70 int result = llvm::sys::ExecuteAndWait( 71 testScript, testerArgs, /*Env=*/None, /*Redirects=*/None, 72 /*SecondsToWait=*/0, /*MemoryLimit=*/0, &errMsg); 73 74 if (result < 0) 75 llvm::report_fatal_error( 76 llvm::Twine("Error running interestingness test: ") + errMsg, false); 77 78 if (!result) 79 return Interestingness::False; 80 81 return Interestingness::True; 82 } 83