xref: /llvm-project/mlir/lib/Reducer/Tester.cpp (revision c484c7dd9d2382f07216ae9142ceb76272e21dc4)
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