@@ -208,7 +208,15 @@ defmodule Emily.IR do
208208 linalg_qr: 117 ,
209209 linalg_eigh: 118 ,
210210 linalg_lu: 119 ,
211- linalg_svd: 120
211+ linalg_svd: 120 ,
212+ # SDPA with attention sinks (gpt-oss). The mask-only and sinks-only
213+ # variants of the existing `fast_sdpa{,_mask}` family — same
214+ # mx::fast::scaled_dot_product_attention entry point, with the
215+ # extra `sinks` operand wired through.
216+ # operands [q, k, v, sinks]; iattrs [[scale_bits], [causal]]
217+ fast_sdpa_sinks: 121 ,
218+ # operands [q, k, v, mask, sinks]; iattrs [[scale_bits]]
219+ fast_sdpa_mask_sinks: 122
212220 }
213221
214222 # Quant mode string -> code; decoded by qmode_from_code in
@@ -1261,6 +1269,59 @@ defmodule Emily.IR do
12611269 emit_coerced ( state , :fast_sdpa_mask , [ rq , rk , rv , rm ] , [ [ float_bits ( scale ) ] ] , t . type )
12621270 end
12631271
1272+ # SDPA with attention sinks (gpt-oss). Mirrors
1273+ # Emily.Backend.fast_scaled_dot_product_attention_with_sinks/6 —
1274+ # routes through the same mx::fast::scaled_dot_product_attention
1275+ # entry point as SDPA, with the sinks tensor as the kernel's `sinks`
1276+ # arg and the causal flag as the mask_mode discriminator
1277+ # ("causal" / "").
1278+ defp lower_block (
1279+ % FB.SDPAWithSinks { scale: scale , causal: causal } ,
1280+ [ q , k , v , sinks ] ,
1281+ _expr ,
1282+ t ,
1283+ state
1284+ ) do
1285+ { rq , state } = lower_node ( q , state )
1286+ { rk , state } = lower_node ( k , state )
1287+ { rv , state } = lower_node ( v , state )
1288+ { rs , state } = lower_node ( sinks , state )
1289+
1290+ emit_coerced (
1291+ state ,
1292+ :fast_sdpa_sinks ,
1293+ [ rq , rk , rv , rs ] ,
1294+ [ [ float_bits ( scale ) ] , [ bool_int ( causal ) ] ] ,
1295+ t . type
1296+ )
1297+ end
1298+
1299+ # SDPA with an additive mask *and* attention sinks (gpt-oss). Mirrors
1300+ # Emily.Backend.fast_scaled_dot_product_attention_with_mask_and_sinks/7 —
1301+ # mask_mode is fixed "array" (the dispatcher hard-codes it), so only the
1302+ # scale crosses as an iattr.
1303+ defp lower_block (
1304+ % FB.SDPAWithMaskAndSinks { scale: scale } ,
1305+ [ q , k , v , mask , sinks ] ,
1306+ _expr ,
1307+ t ,
1308+ state
1309+ ) do
1310+ { rq , state } = lower_node ( q , state )
1311+ { rk , state } = lower_node ( k , state )
1312+ { rv , state } = lower_node ( v , state )
1313+ { rm , state } = lower_node ( mask , state )
1314+ { rs , state } = lower_node ( sinks , state )
1315+
1316+ emit_coerced (
1317+ state ,
1318+ :fast_sdpa_mask_sinks ,
1319+ [ rq , rk , rv , rm , rs ] ,
1320+ [ [ float_bits ( scale ) ] ] ,
1321+ t . type
1322+ )
1323+ end
1324+
12641325 defp lower_block ( % QB.QuantizedMatmul { } = qb , [ x , q , s , b ] , _expr , t , state ) do
12651326 { rx , state } = lower_node ( x , state )
12661327 { rq , state } = lower_node ( q , state )
0 commit comments