Skip to content

Commit 9fbb68b

Browse files
Merge pull request #1987 from j2kun:pass-examples
PiperOrigin-RevId: 784751486
2 parents a5a180c + 0706033 commit 9fbb68b

File tree

6 files changed

+208
-52
lines changed

6 files changed

+208
-52
lines changed

.github/workflows/docs.yml

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,61 @@ on:
66
branches:
77
- main
88
pull_request:
9-
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
11+
cancel-in-progress: true
1012
jobs:
13+
check-cache:
14+
runs-on:
15+
labels: ubuntu-22.04-8core
16+
outputs:
17+
runner: ${{ steps.runner.outputs.runner }}
18+
steps:
19+
- name: Check out repository code
20+
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # pin@v3
21+
22+
- name: Cache bazel build artifacts
23+
id: cache
24+
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # [email protected]
25+
with:
26+
path: |
27+
~/.cache/bazel
28+
key: ${{ runner.os }}-${{ env.ImageVersion }}-bazel-${{ hashFiles('.bazelversion', '.bazelrc', 'WORKSPACE') }}-${{ hashFiles('bazel/import_llvm.bzl') }}
29+
restore-keys: |
30+
${{ runner.os }}-${{ env.ImageVersion }}-bazel-${{ hashFiles('.bazelversion', '.bazelrc', 'WORKSPACE') }}-
31+
lookup-only: true
32+
- name: Select runner
33+
id: runner
34+
env:
35+
CACHE_HIT: ${{ steps.cache.outputs.cache-hit == 'true' }}
36+
run: |
37+
set -euo pipefail
38+
39+
if [[ "${CACHE_HIT}" == "true" ]]; then
40+
echo "runner=ubuntu-22.04-8core" >> "$GITHUB_OUTPUT"
41+
else
42+
echo "runner=ubuntu-22.04-32core" >> "$GITHUB_OUTPUT"
43+
fi
44+
1145
build-and-deploy:
46+
needs: check-cache
47+
runs-on:
48+
labels: ${{ needs.check-cache.outputs.runner }}
1249
permissions:
1350
contents: write
14-
runs-on: ubuntu-22.04
15-
concurrency:
16-
group: ${{ github.workflow }}-${{ github.ref }}
1751
steps:
1852
- name: Checkout
1953
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # pin@v3
2054
with:
2155
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
56+
- name: Cache bazel build artifacts
57+
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # [email protected]
58+
with:
59+
path: |
60+
~/.cache/bazel
61+
key: ${{ runner.os }}-${{ env.ImageVersion }}-bazel-${{ hashFiles('.bazelversion', '.bazelrc', 'WORKSPACE') }}-${{ hashFiles('bazel/import_llvm.bzl') }}
62+
restore-keys: |
63+
${{ runner.os }}-${{ env.ImageVersion }}-bazel-${{ hashFiles('.bazelversion', '.bazelrc', 'WORKSPACE') }}-
2264
2365
# This requires building mlir-tblgen, but may not require a full llvm build
2466
# as a result. It results in the files being added to their respective
@@ -32,16 +74,22 @@ jobs:
3274
3375
- name: "Copy markdown files to docs/"
3476
run: |
35-
python .github/workflows/copy_tblgen_files.py
77+
python -m pip install --upgrade pip
78+
python -m pip install pyyaml==6.0.2 fire==0.7.0
79+
# heir-opt is needed to generate the doctest examples
80+
bazel build //tools:heir-opt
81+
python -m scripts.docs.copy_tblgen_files
3682
37-
# Please update the local install instructions at docs/README.md if changing hugo version
83+
# Please update the local install instructions at docs/README.md if
84+
# changing hugo version
3885
- name: Setup Hugo
3986
uses: peaceiris/actions-hugo@16361eb4acea8698b220b76c0d4e84e1fd22c61d # [email protected]
4087
with:
4188
hugo-version: '0.113.0'
4289
extended: true
4390

44-
# Please update the local install instructions at docs/README.md if changing node version
91+
# Please update the local install instructions at docs/README.md if
92+
# changing node version
4593
- name: Setup Node
4694
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
4795
with:

lib/Transforms/PolynomialApproximation/PolynomialApproximation.td

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,7 @@ def PolynomialApproximation : Pass<"polynomial-approximation"> {
5858
These ops are replaced with `polynomial.eval` ops with a static polynomial
5959
attribute.
6060

61-
Examples:
62-
63-
```mlir
64-
%0 = math.exp %x {
65-
degree = 3 : i32,
66-
domain_lower = -1.0 : f64,
67-
domain_upper = 1.0 : f64
68-
} : f32
69-
```
70-
71-
is converted to
72-
73-
```mlir
74-
#ring_f64_ = #polynomial.ring<coefficientType = f64>
75-
!poly = !polynomial.polynomial<ring = #ring_f64_>
76-
%0 = polynomial.eval
77-
#polynomial<typed_float_polynomial <
78-
0.99458116404270657
79-
+ 0.99565537253615788x
80-
+ 0.54297028147256321x**2
81-
+ 0.17954582110873779x**3> : !poly>, %arg0 : f32
82-
```
61+
(* example filepath=tests/Transforms/polynomial_approximation/doctest.mlir *)
8362
}];
8463
let dependentDialects = [
8564
"mlir::heir::polynomial::PolynomialDialect"

.github/workflows/copy_tblgen_files.py renamed to scripts/docs/copy_tblgen_files.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import yaml
55
from pathlib import Path
66

7+
from scripts.docs.lit_to_doc import lit_to_doc
8+
79
SRC_BASE = "bazel-bin/lib"
810
DEST_BASE = "docs/content/en/docs"
911
PASSES_FILE = f"{DEST_BASE}/passes.md"
@@ -47,9 +49,10 @@ def rebuild_content(frontmatter, sorted_sections):
4749
frontmatter_str = (
4850
"---\n" + yaml.dump(frontmatter) + "---\n\n" if frontmatter else ""
4951
)
50-
content_str = "".join(
51-
[f"{header}\n{body}\n" for header, body in sorted_sections]
52-
)
52+
content_str = "".join([
53+
f"{header.strip()}\n\n{body.strip()}\n\n"
54+
for header, body in sorted_sections
55+
])
5356
return frontmatter_str + content_str
5457

5558

@@ -66,6 +69,25 @@ def sort_markdown_file_by_header(path):
6669
f.write(sorted_content)
6770

6871

72+
def generate_doctest_examples():
73+
print("Generating doctests")
74+
pattern = re.compile(r"^ *(\(\* example filepath=)(.*?)(\s*\*\))")
75+
76+
def replacer(match):
77+
captured_filepath = match.group(2)
78+
print(f"Running doctest for {captured_filepath}")
79+
return lit_to_doc(lit_test_file=captured_filepath)
80+
81+
new_lines = []
82+
with open(PASSES_FILE, "r") as passes_file:
83+
for line in passes_file:
84+
modified_line = pattern.sub(replacer, line)
85+
new_lines.append(modified_line)
86+
87+
with open(PASSES_FILE, "w") as passes_file:
88+
passes_file.write("".join(new_lines))
89+
90+
6991
if __name__ == "__main__":
7092
# Create passes.md file with the front matter
7193
with open(PASSES_FILE, "w") as f:
@@ -87,6 +109,7 @@ def sort_markdown_file_by_header(path):
87109
dest_file.write("\n")
88110

89111
sort_markdown_file_by_header(PASSES_FILE)
112+
generate_doctest_examples()
90113

91114
print("Processing Dialects")
92115
Path(f"{DEST_BASE}/Dialects/").mkdir(parents=True, exist_ok=True)

scripts/docs/lit_to_doc.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import subprocess
2+
import os
3+
4+
import fire
5+
6+
from scripts.lit_to_bazel import (
7+
get_command_without_bazel_prefix,
8+
normalize_lit_test_file_arg,
9+
)
10+
11+
12+
def is_command_executable(command):
13+
"""Checks if a given command is executable on the system's PATH."""
14+
path_env = os.environ.get("PATH")
15+
treat_as_literal = os.path.sep in command or not path_env
16+
if os.path.altsep:
17+
treat_as_literal = treat_as_literal or os.path.altsep in command
18+
19+
if treat_as_literal:
20+
return os.path.isfile(command) and os.access(command, os.X_OK)
21+
22+
for directory in path_env.split(os.pathsep):
23+
full_path = os.path.join(directory, command)
24+
if os.path.isfile(full_path) and os.access(full_path, os.X_OK):
25+
return True
26+
return False
27+
28+
29+
def get_doctest_input(lit_test_file) -> str:
30+
"""Return the mlir part of the given file, omitting lit/filecheck stuff."""
31+
mlir_lines = []
32+
with open(lit_test_file, "r") as f:
33+
for line in f:
34+
if "// RUN" in line or "// CHECK" in line:
35+
continue
36+
mlir_lines.append(line)
37+
38+
return "".join(mlir_lines).strip()
39+
40+
41+
def lit_to_doc(
42+
lit_test_file: str,
43+
git_root: str = "",
44+
):
45+
"""A helper CLI that converts MLIR test files to bazel run commands.
46+
47+
Args:
48+
lit_test_file: The lit test file that should be converted to a bazel run
49+
command.
50+
"""
51+
lit_test_file = normalize_lit_test_file_arg(lit_test_file)
52+
mlir_input = get_doctest_input(lit_test_file)
53+
command = get_command_without_bazel_prefix(lit_test_file, git_root)
54+
command = command.replace("%s", lit_test_file)
55+
56+
if not is_command_executable("heir-opt"):
57+
command = command.replace("heir-opt", "bazel-bin/tools/heir-opt")
58+
59+
result = subprocess.run(
60+
command, shell=True, capture_output=True, text=True, check=True
61+
)
62+
mlir_output = result.stdout.strip()
63+
64+
if not is_command_executable("heir-opt"):
65+
command = command.replace("bazel-bin/tools/heir-opt", "heir-opt")
66+
67+
return f"""#### Example
68+
69+
Command: `{command}`
70+
71+
Input:
72+
73+
```mlir
74+
{mlir_input}
75+
```
76+
77+
Output:
78+
79+
```mlir
80+
{mlir_output}
81+
```
82+
"""
83+
84+
85+
if __name__ == "__main__":
86+
fire.Fire(lit_to_doc)

scripts/lit_to_bazel.py

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,7 @@ def normalize_lit_test_file_arg(lit_test_file: str) -> str:
8383
return lit_test_file
8484

8585

86-
def lit_to_bazel(
87-
lit_test_file: str,
88-
git_root: str = "",
89-
run: bool = False,
90-
debug_dir: str = "/tmp/mlir",
91-
):
92-
"""A helper CLI that converts MLIR test files to bazel run commands.
93-
94-
Args:
95-
lit_test_file: The lit test file that should be converted to a bazel run
96-
command.
97-
"""
98-
86+
def get_command_without_bazel_prefix(lit_test_file, git_root) -> str:
9987
if not git_root:
10088
git_root = pathlib.Path(__file__).parent.parent
10189
if not os.path.isdir(git_root / ".git"):
@@ -128,29 +116,48 @@ def lit_to_bazel(
128116
deduped_commands.append(command)
129117

130118
joined = " ".join(deduped_commands)
119+
return joined
120+
121+
122+
def lit_to_bazel(
123+
lit_test_file: str,
124+
git_root: str = "",
125+
run: bool = False,
126+
debug_dir: str = "/tmp/mlir",
127+
):
128+
"""A helper CLI that converts MLIR test files to bazel run commands.
129+
130+
Args:
131+
lit_test_file: The lit test file that should be converted to a bazel run
132+
command.
133+
"""
134+
135+
command = get_command_without_bazel_prefix(lit_test_file, git_root)
131136
# I would consider using bazel-bin/tools/heir-opt, but the yosys
132137
# requirement requires additional env vars to be set for the yosys and ABC
133138
# paths, which is not yet worth doing for this script.
134-
joined = joined.replace(
139+
command = command.replace(
135140
"heir-opt",
136141
"bazel run --noallow_analysis_cache_discard //tools:heir-opt --",
137142
)
138-
joined = joined.replace(
143+
command = command.replace(
139144
"heir-translate", f"{git_root}/bazel-bin/tools/heir-translate"
140145
)
141-
joined = joined.replace("%s", str(pathlib.Path(lit_test_file).absolute()))
146+
command = command.replace("%s", str(pathlib.Path(lit_test_file).absolute()))
142147

143148
if run:
144149
# delete the debug dir if it exists
145150
if os.path.isdir(debug_dir):
146151
shutil.rmtree(debug_dir)
147-
joined += f" --mlir-print-ir-after-all --mlir-print-ir-tree-dir={debug_dir}"
148-
print(joined)
152+
command += (
153+
f" --mlir-print-ir-after-all --mlir-print-ir-tree-dir={debug_dir}"
154+
)
155+
print(command)
149156

150157
# run the command
151-
subprocess.run(joined, shell=True)
158+
subprocess.run(command, shell=True)
152159
else:
153-
print(joined)
160+
print(command)
154161

155162

156163
if __name__ == "__main__":
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: heir-opt --polynomial-approximation %s | FileCheck %s
2+
3+
// CHECK: @test_exp
4+
func.func @test_exp(%x: f32) -> f32 {
5+
// CHECK: polynomial.eval
6+
// CHECK-SAME: x**3
7+
// CHECK-NOT: x**4
8+
%0 = math.exp %x {
9+
degree = 3 : i32,
10+
domain_lower = -1.0 : f64,
11+
domain_upper = 1.0 : f64} : f32
12+
return %0 : f32
13+
}

0 commit comments

Comments
 (0)