Skip to content

Commit 2e71f65

Browse files
authored
[docs] add frontend semantic restrictions for MLIR kernel authoring (#406)
1 parent a28e150 commit 2e71f65

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

.claude/skills/flydsl-kernel-authoring/SKILL.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,39 @@ for i in range(runtime_value):
224224
...
225225
```
226226

227+
### Frontend Semantic Restrictions
228+
When writing or reviewing `@flyc.kernel` / `@flyc.jit` code, proactively avoid these patterns because they can conflict with MLIR construction even if they look valid in plain Python.
229+
230+
1. **Do not define values inside `if/else` and use them later outside the branch.** Keep a single explicit definition path.
231+
```python
232+
if cond:
233+
dst = a
234+
else:
235+
dst = b
236+
use(dst) # avoid this pattern
237+
```
238+
239+
2. **Do not mutate captured outer variables inside nested helper functions.** Read-only closure capture is acceptable, but writes should go through explicit parameters and return values.
240+
```python
241+
def kernel():
242+
acc = fx.Float32(0.0)
243+
244+
def helper(acc):
245+
acc = acc + fx.Float32(1.0)
246+
return acc
247+
248+
acc = helper(acc)
249+
```
250+
251+
3. **Avoid early `return`, and do not place `return` / `yield` inside `if/else` branches.** Prefer a single explicit exit so the frontend can determine result types.
252+
```python
253+
if cond:
254+
out = v0
255+
else:
256+
out = v1
257+
return out
258+
```
259+
227260
### scf.for with Loop-Carried Values (Software Pipelining)
228261

229262
Use `init=` on `range()` to create an `scf.for` with explicit SSA phi nodes for loop-carried state. This is required for software pipelining (prefetch patterns) where data must flow across iterations.

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,6 @@ FLYDSL_DUMP_IR=1 PYTHONPATH=./ python tests/kernels/test_pa.py # Dump MLIR IR at
7474
- **Layout API vs buffer_ops**: New kernels should use `fx.rocdl.make_buffer_tensor()` + `copy_atom_call` (layout API). Raw `buffer_ops.create_buffer_resource()` is legacy
7575
- **Arch detection**: Use `from flydsl.runtime.device import get_rocm_arch`
7676
- **`range` vs `range_constexpr`**: Use `range_constexpr` for compile-time unrolled loops; `range(start, stop, step, init=[...])` for `scf.for` with loop-carried values
77+
- **Branch-local defs**: Do not define a value inside `if/else` and then use it after the branch. Hoist the variable or rewrite the logic so later uses see a single explicit definition path.
78+
- **Nested helper captures**: Inside `@flyc.kernel` / `@flyc.jit`, nested helper functions must not mutate captured outer variables. Read-only capture is acceptable, but writes should go through explicit parameters / returns.
79+
- **Single-exit control flow**: Avoid early `return`. Do not place `return` or `yield` inside `if/else` branches; keep a single explicit exit path so MLIR result types stay well-defined.

0 commit comments

Comments
 (0)