Commit daee90e
DSL-ify raw arith float ops in kernels (flash/mla/pa/moe), fastmath v… (#930)
* DSL-ify raw arith float ops in kernels (flash/mla/pa/moe), fastmath via fast_fp_math
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* kernels: DSL-ify raw integer arith ops into operators
Replace raw MLIR integer arith in kernels with DSL operators:
- arith.cmpi(pred, a, b) -> a == / != / < / <= / > / >=
- arith.divsi/divui -> //, remsi/remui -> %
- arith.andi/ori/xori -> & / | / ^, shli -> <<, shrui/shrsi -> >>
Operands stay DSL values (drop _raw/as_mlir_value/.ir_value unwraps).
At raw-i1 consumers (scf.IfOp / llvm.intr_expect / arith.select cond),
use as_ir_value(...), which handles both ArithValue (comparison over
ArithValue operands) and Boolean (comparison over Numeric operands).
Deliberately left as raw arith, with reasons:
- unsigned compare where an operand can be negative (signed compare would
misclassify) — must stay ult
- pow2 strength-reduced shift/and standing in for divide/remainder
- unsigned-division helpers whose contract is unsigned
- integer min/max (no DSL integer min/max), ceil-div (no operator)
- operands that are genuinely raw ir.Value (ballot / readfirstlane /
scf result / dpp) with no DSL wrapper
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* kernels: replace raw MLIR index builders with DSL
De-index kernel code by replacing raw MLIR index builders with DSL:
- arith.index(n) / arith.constant(v, index=True) -> fx.Index(v)
- arith.index_cast(T.i32/i64, x) -> fx.Int32(x) / fx.Int64(x)
At raw low-level consumers (get_llvm_ptr / llvm.* / rocdl.* / buffer
DMA offset), the DSL value is unwrapped with as_ir_value(...). scf.for
loop-carried counters that were arith.constant(0, index=True) become
fx.Index(0) (type-preserving).
Left as-is (with reasons):
- index values used as layout coordinates (vec_load/vec_store/
linear_offset/cs_off/memref) and anything combined or compared with
them: the layout shim casts coordinates from index, so they must stay
index-typed
- arith.index_cast(T.index, x) producing grid/launch or coordinate
index values
- raw index operands of raw shift/and builders (strength-reduced
pow2 paths)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* kernels: DSL-ify unsigned expert-id compare in dispatch kernel
The last raw arith.cmpi here needed unsigned ult (local_expert_id can be
negative for non-local experts; a signed compare would misclassify them).
fx.Uint32 reinterprets the same i32 bits as unsigned, so the DSL `<`
emits ult — behavior-preserving. Result feeds a dynamic if, so wrap with
as_ir_value.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* kernels: drop redundant as_ir_value at arith.select conditions
arith.select unwraps DSL Numeric/Boolean conditions itself (via
_to_raw), so wrapping the condition in as_ir_value was unnecessary.
Pass the DSL comparison directly. as_ir_value stays only where the
consumer is a raw MLIR builder that requires an ir.Value (scf.IfOp,
llvm.*, rocdl.*, get_llvm_ptr, vector.*, buffer DMA offsets).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* kernels: keep is_local as a DSL Boolean in dispatch kernel
The as_ir_value wrapper was redundant: is_local feeds a dynamic `if`
(the AST rewriter converts the condition to i1 itself) and is_local.select(...)
(a DSL method). Keep it as the DSL Boolean from fx.Uint32 comparison.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* attention/pa: use contract fastmath (not fast) to preserve fp8 accuracy
The paged-decode accumulation/reduction ops originally used the narrow
`contract` fastmath flag (FMA fusion only, preserves accumulation order).
DSL-ifying them under a `fast_fp_math` hint widened the flag to `fast`,
whose reassoc reorders fp accumulation and loses precision on fp8 (bf16/
fp16 tolerate it). Switch the pa launchers' compile hint from
{"fast_fp_math": True} to {"fastmath": contract} so the DSL operators emit
`contract`, matching the original per-op flag.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* attention: minimal parens + .maximumf()->fx.maxnumf() cleanup
Behavior-preserving cleanup of the DSL-ified attention kernels:
- drop redundant parentheses left by the operand-wrapping conversion
(e.g. `(a) - ((b) * (c))` -> `a - b * c`), keeping only precedence-
required grouping
- replace the `X.maximumf(Y)` method form with the `fx.maxnumf(X, Y)`
free function (and `.minimumf` -> `fx.minnumf`); maxnumf matches the
original flash reduction op and differs from maximumf only on NaN,
which softmax max operands never produce
Verified behavior-identical by AST equivalence (redundant parens do not
appear in the AST; only the exact maximumf->maxnumf transform differs),
plus flash gfx942 numerics.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* attention: use top-level fx.* math instead of the fmath alias
fmath is just `flydsl.expr.math`, and fx.rsqrt/fx.log/fx.fma/... are the
same functions re-exported at top level (fmath is fx.math; fx.rsqrt is
fmath.rsqrt). Use the fx.* names for consistency with the rest of the DSL
and drop the redundant as_mlir_value on fx.log args (fx.log unwraps its
argument internally). Behavior-identical (same function objects); flash
gfx942 numerics unchanged.
Note: rocdl.exp2/rcp are intentionally kept -- they lower to the bare
v_exp/v_rcp hardware instructions, whereas fx.exp2 lowers to an
__ocml_exp2_f32 call (slower, range-reduced), so they are not equivalent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* moe/mxfp: DSL-ify the e8m0 amax bit-extract in the fp4 epilogue
The amax exponent extraction used raw arith.bitcast/shrui/shli on
_raw-unwrapped DSL operands. Rewrite with DSL ops (bit-exact):
- arith.bitcast(T.i32, amax_f) + arith.shrui(.., 16) -> amax_f.bitcast(Uint32) >> 16
(Uint32 so >> emits the unsigned shift, matching shrui)
- arith.shli(amax_dpp, 16) -> amax_dpp << 16
- arith.bitcast(T.f32, f32b) -> f32b.bitcast(Float32)
- .maximumf() -> fx.maxnumf() for consistency
Pure bit manipulation, no fastmath involved; moe a8w4/fp4 numerics pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* moe/mxfp: use fx.absf instead of the _fabs_f32 llvm-intrinsic helper
_fabs_f32 wrapped a raw llvm.call_intrinsic("llvm.fabs.f32"). fx.absf
(math.absf) lowers to the same llvm.fabs.f32 (via llvm.intr.fabs), so
replace the helper with fx.absf at all call sites and delete it. Also
`.maximumf()` -> fx.maxnumf() in gemm1 for consistency. Pure bit-op abs,
behavior-identical; moe a8w4/fp4 numerics pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* kernels: DSL-ify remaining bit-exact bitcast/fabs sites
Full-scan follow-up. Replace raw ops whose operands are already DSL and
whose DSL form lowers to the same instruction (bit-exact / same intrinsic):
- mfma_preshuffle: arith.bitcast(T.i32/f32, x) -> x.bitcast(fx.Int32/Float32)
- silu_and_mul_fq: llvm.call_intrinsic("llvm.fabs.f32") -> fx.absf; and
arith.maximumf -> fx.maxnumf
- pa_decode_swa: arith.bitcast(T.i32, weight_local) -> weight_local.bitcast(fx.Int32)
Left as-is (raw operands / no equivalent / unvalidatable): rocdl.exp2/rcp
(bare v_exp/v_rcp), arith.minsi/maxsi (no DSL int min/max), the shrui on a
raw index param, cmpf-result andi, ds_bpermute-result bitcast, and the
multi-gpu dispatch bitcasts (raw i64 operand, no local validation path).
Validated: test_preshuffle_gemm 58 passed; imports clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* moe/2stage: broadcast DSL bf16 scale via fx.Vector.filled
extract_bf16_scale now returns a DSL Float32 (correct). The bf16 groupwise
accumulator broadcast fed it to the raw vector.broadcast builder, which
only takes an ir.Value -> "must be a Value". Use fx.Vector.filled(4,
scale_val, fx.Float32) which accepts a DSL scalar and lowers to the same
vector.broadcast. Bit-identical; bf16 moe_gemm_2stage passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* moe/mma: drop the now-unused arith param from extract_bf16_scale
extract_bf16_scale no longer uses the passed-in arith module (its body is
DSL << / & / .bitcast now), so remove the parameter and drop it at the
three call sites in moe_gemm_2stage gemm1/gemm2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* mma/preshuffle: fix bitcast on ArithValue operands (w4a16 path)
The earlier .bitcast(fx.Int32/Float32) conversions in the w4a16 unpack
functions operate on raw ArithValue operands, but ArithValue.bitcast
expects an ir.Type (T.i32), not a Numeric class -> "must be a Type
(std::bad_cast)" on the int4_bf16 groupwise moe path (not covered by
test_preshuffle_gemm). Revert the two unpack sites to arith.bitcast(T.i32,
...) (they run on raw ArithValue with raw downstream). For extract_bf16_scale,
keep it DSL by wrapping the raw dword in fx.Uint32 first so Numeric.bitcast
applies; its DSL Float32 result is consumed by the fx.Vector.filled scale
broadcast.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* moe/2stage: normalize scale_val to fx.Float32 before Vector.filled
The bf16 scale broadcast can receive scale_val either as a DSL Float32
(bf16 groupwise via extract_bf16_scale) or as a raw ArithValue (other
paths, e.g. gfx950 g32-eager int4_bf16). fx.Vector.filled requires a
Numeric fill_value, so wrap scale_val in fx.Float32 first (passthrough
for DSL, wraps a raw ArithValue). Fixes the gfx950 int4_bf16 failures.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Felix Li <felix.li@amd.com>1 parent 47009a3 commit daee90e
13 files changed
Lines changed: 241 additions & 339 deletions
File tree
- kernels
- attention
- common
- mma
- comm
- conv
- moe/mxfp_moe
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | | - | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| |||
329 | 329 | | |
330 | 330 | | |
331 | 331 | | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
338 | | - | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | 332 | | |
343 | 333 | | |
344 | 334 | | |
345 | 335 | | |
346 | | - | |
347 | | - | |
348 | | - | |
349 | | - | |
350 | | - | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | | - | |
355 | | - | |
356 | | - | |
357 | | - | |
358 | 336 | | |
359 | 337 | | |
360 | 338 | | |
| |||
757 | 735 | | |
758 | 736 | | |
759 | 737 | | |
760 | | - | |
| 738 | + | |
761 | 739 | | |
762 | 740 | | |
763 | 741 | | |
| |||
917 | 895 | | |
918 | 896 | | |
919 | 897 | | |
920 | | - | |
| 898 | + | |
921 | 899 | | |
922 | 900 | | |
923 | 901 | | |
| |||
927 | 905 | | |
928 | 906 | | |
929 | 907 | | |
930 | | - | |
| 908 | + | |
931 | 909 | | |
932 | | - | |
933 | | - | |
| 910 | + | |
| 911 | + | |
934 | 912 | | |
935 | 913 | | |
936 | 914 | | |
937 | 915 | | |
938 | 916 | | |
939 | | - | |
| 917 | + | |
940 | 918 | | |
941 | | - | |
| 919 | + | |
942 | 920 | | |
943 | 921 | | |
944 | 922 | | |
| |||
947 | 925 | | |
948 | 926 | | |
949 | 927 | | |
950 | | - | |
| 928 | + | |
951 | 929 | | |
952 | 930 | | |
953 | 931 | | |
| |||
1824 | 1802 | | |
1825 | 1803 | | |
1826 | 1804 | | |
1827 | | - | |
1828 | | - | |
| 1805 | + | |
| 1806 | + | |
1829 | 1807 | | |
1830 | 1808 | | |
1831 | 1809 | | |
| |||
2078 | 2056 | | |
2079 | 2057 | | |
2080 | 2058 | | |
2081 | | - | |
2082 | | - | |
2083 | | - | |
2084 | | - | |
2085 | | - | |
2086 | | - | |
2087 | | - | |
2088 | | - | |
2089 | | - | |
2090 | | - | |
2091 | | - | |
2092 | | - | |
2093 | | - | |
2094 | | - | |
2095 | | - | |
2096 | | - | |
| 2059 | + | |
| 2060 | + | |
| 2061 | + | |
| 2062 | + | |
| 2063 | + | |
| 2064 | + | |
| 2065 | + | |
| 2066 | + | |
| 2067 | + | |
| 2068 | + | |
| 2069 | + | |
| 2070 | + | |
| 2071 | + | |
| 2072 | + | |
| 2073 | + | |
| 2074 | + | |
| 2075 | + | |
| 2076 | + | |
| 2077 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | | - | |
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| |||
397 | 397 | | |
398 | 398 | | |
399 | 399 | | |
400 | | - | |
401 | 400 | | |
402 | 401 | | |
403 | 402 | | |
| |||
452 | 451 | | |
453 | 452 | | |
454 | 453 | | |
455 | | - | |
| 454 | + | |
456 | 455 | | |
457 | | - | |
| 456 | + | |
458 | 457 | | |
459 | 458 | | |
460 | 459 | | |
| |||
742 | 741 | | |
743 | 742 | | |
744 | 743 | | |
745 | | - | |
| 744 | + | |
746 | 745 | | |
747 | 746 | | |
748 | 747 | | |
| |||
751 | 750 | | |
752 | 751 | | |
753 | 752 | | |
754 | | - | |
755 | | - | |
756 | | - | |
| 753 | + | |
757 | 754 | | |
758 | 755 | | |
759 | 756 | | |
| |||
879 | 876 | | |
880 | 877 | | |
881 | 878 | | |
882 | | - | |
| 879 | + | |
883 | 880 | | |
884 | 881 | | |
885 | 882 | | |
886 | 883 | | |
887 | 884 | | |
888 | 885 | | |
889 | 886 | | |
890 | | - | |
891 | | - | |
892 | | - | |
| 887 | + | |
893 | 888 | | |
894 | 889 | | |
895 | 890 | | |
| |||
919 | 914 | | |
920 | 915 | | |
921 | 916 | | |
922 | | - | |
923 | | - | |
924 | | - | |
925 | | - | |
926 | | - | |
927 | | - | |
928 | | - | |
| 917 | + | |
929 | 918 | | |
930 | 919 | | |
931 | 920 | | |
| |||
983 | 972 | | |
984 | 973 | | |
985 | 974 | | |
986 | | - | |
987 | | - | |
988 | | - | |
989 | | - | |
990 | | - | |
991 | | - | |
992 | | - | |
993 | | - | |
994 | | - | |
995 | | - | |
996 | | - | |
997 | | - | |
998 | | - | |
999 | | - | |
1000 | | - | |
1001 | | - | |
1002 | | - | |
1003 | | - | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
1004 | 994 | | |
1005 | 995 | | |
1006 | 996 | | |
| |||
0 commit comments