Skip to content

Commit 1a461b4

Browse files
authored
imex-runner.py: Add --requires option to control conditional execution. (#493)
* imex-runner.py: Add --requires option to control conditional execution. vulkan-runner, l0-runtime, sycl-runtime can used with --requires to conditionally execute the script. For example, if --requires=l0-runtime is given and l0 runtime is not available, imex-runner.py will skip execution. * Replace += with .append() to make code more consistent. * Windows shared libraries (.dll) are placed under "bin" not "lib"
1 parent 4b3f550 commit 1a461b4

File tree

3 files changed

+103
-19
lines changed

3 files changed

+103
-19
lines changed

CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,11 @@ set(LLVM_LIT_ARGS "-sv" CACHE STRING "lit default options")
109109
set(IMEX_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
110110
# LLVM_EXTERNAL_PROJECTS build puts library, executables and tools in LLVM's CMAKE_BINARY_DIR
111111
set(IMEX_BINARY_DIR ${CMAKE_BINARY_DIR})
112-
set(IMEX_LIB_DIR ${IMEX_BINARY_DIR}/lib)
112+
if(WIN32)
113+
set(IMEX_LIB_DIR ${IMEX_BINARY_DIR}/bin)
114+
else()
115+
set(IMEX_LIB_DIR ${IMEX_BINARY_DIR}/lib)
116+
endif()
113117

114118
include(sanitizers)
115119

@@ -120,7 +124,7 @@ add_subdirectory(test)
120124

121125
option(IMEX_INCLUDE_DOCS "Generate build targets for the IMEX docs." ON)
122126
if (IMEX_INCLUDE_DOCS)
123-
add_subdirectory(docs)
127+
add_subdirectory(docs)
124128
endif()
125129

126130
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/mlir

test/Integration/Dialect/Linalg/Vulkan/linalg_addf.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %python_executable %imex_runner -i %s --pass-pipeline-file=%p/linalg-to-gpu-vulkan.pp --runner mlir-vulkan-runner --shared-libs=%vulkan_runtime_wrappers,%mlir_runner_utils --entry-point-result=void | FileCheck %s --check-prefix=VULKAN
1+
// RUN: %python_executable %imex_runner -i %s --pass-pipeline-file=%p/linalg-to-gpu-vulkan.pp --runner mlir-vulkan-runner --shared-libs=%vulkan_runtime_wrappers,%mlir_runner_utils --entry-point-result=void --filecheck --check-prefix=VULKAN
22

33
#map = affine_map<(d0, d1) -> (d0, d1)>
44
module {

tools/imex-runner/imex-runner.py.in

Lines changed: 96 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313

1414
"""
1515
Run a mlir file through imex-opt using a user provided pass pipeline
16-
and run resulting output through mlir-runner.
17-
The pass pipeline is provided either in a file or as a string; expected
16+
and optionally(On by default and turned off by option --no-mlir-runner)
17+
run resulting output through an mlir runner
18+
(Default is mlir-cpu-runner and can be overridden by option --runner).
19+
After that, optionally(Option --filecheck), output can be passed to FileCheck utility.
20+
The pass pipeline for imex-opt is provided either in a file or as a string; expected
1821
syntax is similar to mlir-opt's syntax.
1922
2023
If provided in a file passes can be separted by newline or ',' and
@@ -32,10 +35,14 @@ func.func(scf-bufferize,
3235
Pass pipelines privded as strings will not be modified.
3336
3437
All unknown arguments will be forwarded to mlir-runner. Currently there is no
35-
option to forward user-provided args to imex-opt.
38+
option to forward user-provided args directly to imex-opt.
39+
Options --imex-print-before-all and --imex-print-after-all gets converted
40+
into --mlir-print-ir-before-all, --mlir-print-ir-after-all and forwarded to
41+
imex-opt to enable printing IR before and after running passes.
42+
Option --check-prefix gets forwarded to FileCheck.
3643
3744
To use this in a lit test, you can do something similar to
38-
`// RUN: %python_executable %imex-runner -i %s --pass-pipeline-file=%p/ptensor.pp -e main -entry-point-result=void --shared-libs=%mlir_c_runner_utils --shared-libs=%mlir_runner_utils | FileCheck %s`
45+
`// RUN: %python_executable %imex-runner -i %s --pass-pipeline-file=%p/ptensor.pp -e main -entry-point-result=void --shared-libs=%mlir_c_runner_utils,%mlir_runner_utils --filecheck`
3946
"""
4047

4148
import os, sys, re
@@ -44,23 +51,52 @@ import argparse
4451
import subprocess
4552

4653
imex_enable_vulkan_runner = @IMEX_ENABLE_VULKAN_RUNNER@
54+
imex_enable_l0_runtime = @IMEX_ENABLE_L0_RUNTIME@
55+
imex_enable_sycl_runtime = @IMEX_ENABLE_SYCL_RUNTIME@
56+
4757
runner_choices = ['mlir-cpu-runner']
58+
enabled_features = []
59+
all_features = ['vulkan-runner', 'l0-runtime', 'sycl-runtime']
4860
if imex_enable_vulkan_runner:
49-
runner_choices += ['mlir-vulkan-runner']
61+
runner_choices.append('mlir-vulkan-runner')
62+
enabled_features.append('vulkan-runner')
63+
if imex_enable_l0_runtime:
64+
enabled_features.append('l0-runtime')
65+
if imex_enable_sycl_runtime:
66+
enabled_features.append('sycl-runtime')
67+
68+
class SplitArgs(argparse.Action):
69+
def __call__(self, parser, namespace, values, option_string=None):
70+
setattr(namespace, self.dest, values.split(','))
5071

5172
parser = argparse.ArgumentParser(
52-
description="run imex-opt and pipe into mlir-runner"
73+
description="Run imex-opt, optionally pipe result into selected mlir runner (default: mlir-cpu-runner) and then optionally pipe output into FileCheck"
5374
)
5475
parser.add_argument("--input-file", "-i", default=None, help="input MLIR file")
5576
parser.add_argument("--pass-pipeline-file", "-f", default=None, help="file defining pass pipeline")
5677
parser.add_argument("--pass-pipeline", "-p", default=None, help="pass pipeline (string)")
5778
parser.add_argument("--imex-print-before-all", "-b", action='store_true', dest='before', help="print ir before all passes")
5879
parser.add_argument("--imex-print-after-all", "-a", action='store_true', dest='after', help="print ir after all passes")
5980
parser.add_argument("--no-mlir-runner", "-n", action='store_true', dest='no_mlir_runner', help="skip mlir runner")
81+
parser.add_argument("--filecheck", action='store_true', dest='run_filecheck', help="run FileCheck")
82+
parser.add_argument("--check-prefix", default=None, help="change check prefix (default: CHECK) used by FileCheck")
6083
parser.add_argument("--runner", "-r", default="mlir-cpu-runner", choices=runner_choices, help="mlir runner name")
84+
parser.add_argument('--requires', default=enabled_features, action=SplitArgs, help="skip if any of the required in the comma separated list is missing.")
6185

6286
args, unknown = parser.parse_known_args()
6387

88+
# Check if requirements are valid
89+
required_features = args.requires
90+
if not set(required_features) <= set(all_features):
91+
print('Invalid option passed to --requires')
92+
print('your options were: ', *required_features)
93+
print('valid options are: ', *all_features)
94+
exit(1)
95+
96+
# Skip runner if requirements are not met be enabled features
97+
if not set(required_features) <= set(enabled_features):
98+
exit(0)
99+
64100
ppipeline = None
65101
if args.pass_pipeline_file:
66102
with open(args.pass_pipeline_file, 'r') as infile:
@@ -82,6 +118,36 @@ if args.pass_pipeline_file:
82118
imex_binary_dir = '@IMEX_BINARY_DIR@'
83119
llvm_binary_dir = '@LLVM_BINARY_DIR@'
84120

121+
def run_pipeline(cmds):
122+
"""
123+
Run commands in PIPE, return the last process in chain.
124+
stdout of intermediate commands are sent to PIPE.
125+
stdout of last command is not sent to PIPE.
126+
"""
127+
first_cmd, *rest_cmds = cmds
128+
if len(cmds) == 1:
129+
procs = [subprocess.Popen(first_cmd)]
130+
else:
131+
procs = [subprocess.Popen(first_cmd, stdout=subprocess.PIPE)]
132+
if len(cmds) == 2:
133+
last_stdout = procs[-1].stdout
134+
cmd = rest_cmds[-1]
135+
proc = subprocess.Popen(cmd, stdin=last_stdout)
136+
procs.append(proc)
137+
else:
138+
for cmd in rest_cmds[:-1]:
139+
last_stdout = procs[-1].stdout
140+
proc = subprocess.Popen(cmd, stdin=last_stdout, stdout=subprocess.PIPE)
141+
procs.append(proc)
142+
last_stdout = procs[-1].stdout
143+
cmd = rest_cmds[-1]
144+
proc = subprocess.Popen(cmd, stdin=last_stdout)
145+
procs.append(proc)
146+
return procs[-1]
147+
148+
# All commands to create a pipeline
149+
cmds = []
150+
85151
# build imex-opt command
86152
cmd = [os.path.normpath(os.path.join(imex_binary_dir, 'bin', 'imex-opt'))]
87153
if ppipeline:
@@ -94,14 +160,28 @@ if args.before:
94160
cmd.append(f'--mlir-print-ir-before-all')
95161
if args.after:
96162
cmd.append(f'--mlir-print-ir-after-all')
97-
# run and feed into pipe
98-
if args.no_mlir_runner:
99-
subprocess.run(cmd)
100-
else:
101-
p1 = subprocess.Popen(cmd, stdout=subprocess.PIPE)
102-
# build mlir-opt command: all unknown args will be passed to imex-opt
163+
cmds.append(cmd)
164+
165+
# build runner command
166+
if not args.no_mlir_runner:
167+
# build runner command: all unknown args will be passed to the runner
103168
cmd = [os.path.normpath(os.path.join(llvm_binary_dir, 'bin', args.runner))] + unknown
104-
# get stdout from imex-opt and pipe into mlir-opt
105-
p2 = subprocess.Popen(cmd, stdin=p1.stdout)
106-
p1.wait()
107-
p2.wait()
169+
cmds.append(cmd)
170+
171+
# build FileCheck command
172+
if args.run_filecheck:
173+
cmd = [os.path.normpath(os.path.join(llvm_binary_dir, 'bin', 'FileCheck'))]
174+
if args.check_prefix:
175+
cmd.append(f'--check-prefix={args.check_prefix}')
176+
if not args.input_file:
177+
print('Error: --input-file is required for filecheck')
178+
exit(1)
179+
cmd.append(args.input_file)
180+
cmds.append(cmd)
181+
182+
# Run command pipeline
183+
last_proc = run_pipeline(cmds)
184+
185+
# Wait for last command completion and exit with returncode
186+
last_proc.wait()
187+
exit(last_proc.returncode)

0 commit comments

Comments
 (0)