@@ -520,8 +520,6 @@ def build_graph_passes(
520520 partial (partition_ops_with_gpr_offsets , trace , launchable .constraints ),
521521 partial (partition_strided_operators , trace , launchable .constraints ),
522522 partial (remove_chained_extractslice , trace ),
523- # Run an early coalescing pass so scheduling (including manual schedules)
524- # can reason about merged read widths/counts instead of only pre-merge reads.
525523 partial (
526524 merge_contiguous_reads ,
527525 trace ,
@@ -1295,7 +1293,9 @@ def _generate_asm_code(mb, options):
12951293 mlir_path = mlir_file .name
12961294
12971295 try :
1298- base_passes = [
1296+ cmd = [
1297+ waveasm_translate ,
1298+ f"--target={ options .target } " ,
12991299 "--mlir-cse" ,
13001300 "--waveasm-scoped-cse" ,
13011301 "--waveasm-peephole" ,
@@ -1306,63 +1306,17 @@ def _generate_asm_code(mb, options):
13061306 "--waveasm-memory-offset-opt" ,
13071307 "--canonicalize" ,
13081308 "--waveasm-scoped-cse" ,
1309- ]
1310- # (2,2) wave shapes generate extract_strided_slice -> V_BFE_U32
1311- # for scale extraction, creating load->VALU data hazards that
1312- # require ticketed waitcnt. (1,4) shapes use scalesIdxA on the
1313- # MFMA directly and don't hit this path.
1314- # (1,4): wg=(64,4,1) == waves_in_m=1, waves_in_n=4 == off
1315- # (2,2): wg=(128,2,1) == waves_in_m=2, waves_in_n=2 == on
1316- # (4,1): wg=(256,1,1) == waves_in_m=4, waves_in_n=1 == off
1317- threads_per_wave = 64
1318- waves_in_m = wg [0 ] // threads_per_wave
1319- waves_in_n = wg [1 ]
1320- # TODO: improve Ticketing logic (better latency-covering heuristics,
1321- # smarter coalescing) so ticketed waitcnt can be always-on without
1322- # a performance hit, removing this wave-shape conditional.
1323- use_ticketed_waitcnt = waves_in_m >= 2 and waves_in_n >= 2
1324- waitcnt_flag = (
1325- "--waveasm-insert-waitcnt"
1326- if use_ticketed_waitcnt
1327- else "--waveasm-insert-waitcnt=ticketed-waitcnt=false"
1328- )
1329- tail_passes = [
1309+ "--waveasm-loop-address-promotion" ,
13301310 "--waveasm-linear-scan=max-vgprs=512 max-agprs=512" ,
1331- waitcnt_flag ,
1311+ "--waveasm-insert-waitcnt=ticketed-waitcnt=false" ,
13321312 f"--waveasm-hazard-mitigation=target={ options .target } " ,
13331313 "--emit-assembly" ,
13341314 f"--workgroup-size-x={ wg [0 ]} " ,
13351315 f"--workgroup-size-y={ wg [1 ]} " ,
13361316 f"--workgroup-size-z={ wg [2 ]} " ,
13371317 mlir_path ,
13381318 ]
1339-
1340- def _run_translate (extra_passes ):
1341- full_cmd = (
1342- [waveasm_translate , f"--target={ options .target } " ]
1343- + base_passes
1344- + extra_passes
1345- + tail_passes
1346- )
1347- return subprocess .run (full_cmd , capture_output = True , text = True , timeout = 60 )
1348-
1349- import re
1350-
1351- HW_VGPR_LIMIT = 256
1352-
1353- # loop-address-promotion converts per-iteration LDS address
1354- # arithmetic (V_ADD_U32) into precomputed rotating VGPR iter-args,
1355- # removing VALU ops from the critical path. The trade-off is extra
1356- # live VGPRs for the promoted addresses. For large block sizes
1357- # (e.g. 256x160x256, 256x192x256) this can push the VGPR count
1358- # past the gfx9 hardware limit of 256. We try with the pass
1359- # first and fall back without it when the limit is exceeded.
1360- result = _run_translate (["--waveasm-loop-address-promotion" ])
1361- if result .returncode == 0 :
1362- m = re .search (r"\.vgpr_count:\s*(\d+)" , result .stdout )
1363- if m and int (m .group (1 )) > HW_VGPR_LIMIT :
1364- result = _run_translate ([])
1365-
1319+ result = subprocess .run (cmd , capture_output = True , text = True , timeout = 60 )
13661320 if result .returncode != 0 :
13671321 raise RuntimeError (f"waveasm-translate failed:\n { result .stderr } " )
13681322 asm_text = result .stdout
0 commit comments