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
21using namespace mlir;
22
23Tester::Tester(StringRef scriptName, ArrayRef<std::string> scriptArgs)
24 : testScript(scriptName), testScriptArgs(scriptArgs) {}
25
26std::pair<Tester::Interestingness, size_t>
27Tester::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(x: Interestingness::False, /*size=*/y: 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(Prefix: "mlir-reduce", Suffix: "mlir", ResultFD&: fd, ResultPath&: filepath);
40
41 if (ec)
42 llvm::report_fatal_error(reason: 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(reason: llvm::Twine("Error emitting the IR to file '") +
51 filepath);
52
53 size_t size = out.os().tell();
54 return std::make_pair(x: isInteresting(testCase: filepath), y&: 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.
60Tester::Interestingness Tester::isInteresting(StringRef testCase) const {
61 std::vector<StringRef> testerArgs;
62 testerArgs.push_back(x: testCase);
63
64 for (const std::string &arg : testScriptArgs)
65 testerArgs.emplace_back(args: arg);
66
67 testerArgs.push_back(x: testCase);
68
69 std::string errMsg;
70 int result = llvm::sys::ExecuteAndWait(
71 Program: testScript, Args: testerArgs, /*Env=*/std::nullopt, /*Redirects=*/std::nullopt,
72 /*SecondsToWait=*/0, /*MemoryLimit=*/0, ErrMsg: &errMsg);
73
74 if (result < 0)
75 llvm::report_fatal_error(
76 reason: llvm::Twine("Error running interestingness test: ") + errMsg, gen_crash_diag: false);
77
78 if (!result)
79 return Interestingness::False;
80
81 return Interestingness::True;
82}
83

source code of mlir/lib/Reducer/Tester.cpp