Skip to content

warp_shuffle_op: avoid sub-int narrow↔wide roundtrip (IGC fp16 miscompile)#3

Merged
pvelesko merged 5 commits into
mainfrom
fix-warp-shuffle-fp16
Apr 17, 2026
Merged

warp_shuffle_op: avoid sub-int narrow↔wide roundtrip (IGC fp16 miscompile)#3
pvelesko merged 5 commits into
mainfrom
fix-warp-shuffle-fp16

Conversation

@pvelesko

@pvelesko pvelesko commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

IGC on Intel Arc A770 miscompiles OpSubgroupShuffleINTEL when all three conditions hold simultaneously:

  1. Shuffle value is OpUConvert %uint <- %ushort (widen before shuffle)
  2. Result is narrowed back with OpUConvert %ushort <- %uint
  3. The consumer lives in a block entered via OpBranchConditional

Result: the narrowed value reads as 0 instead of the neighbor lane's value.

Upstream IGC bug: intel/intel-graphics-compiler#402 (filed with 206-line pure Level Zero + spvasm reproducer).

rocPRIM's generic warp_shuffle_op<T> for sizeof(T) < 4 hits this pattern for __half / bf16 warp operations. Fix: for sub-int types, bounce the post-shuffle int through a volatile stack slot and load the low sizeof(T) bytes via byte-wise memcpy — emits OpBitcast + OpLoad instead of the offending OpUConvert ushort <- uint, dodging the IGC bug.

Impact (Arc A770, chipStar HEAD, Level Zero)

Test Before After
test_warp_reduce 292/294 294/294 (+2 __half ReduceSum)
test_warp_scan 287/294 294/294 (+7 __half/bf16 (Inclusive)ScanReduce)
test_block_reduce 239/240 240/240 (+1 block_params<__half,__half,64>)
test_warp_shuffle_fp16 (new regression) FAIL PASS

Likely also resolves a further ~20 rocThrust __half-bearing tests downstream (not individually minimized).

Commits

  • a8ad010 test: reproduce IGC fp16 narrow-wide shuffle miscompile in warp_shuffle
  • bc73c2f fix: specialize warp_shuffle_op for sizeof(T)<4 to avoid IGC fp16 miscompile

Scope / compatibility

  • Change is inside #ifdef __HIP_PLATFORM_SPIRV__ — AMD path is unchanged
  • Once IGC#402 is fixed upstream, this workaround can be reverted

Test plan

  • New regression test test_warp_shuffle_fp16 PASS on Arc A770 / Level Zero
  • test_warp_reduce / test_warp_scan / test_block_reduce fully green on Arc A770
  • Full rocPRIM test run pre-merge

Adds a minimal regression test that exercises the rocprim::warp_shuffle_down
chain on __half with a divergent consumer. This is the exact control-flow
shape emitted by warp_reduce_shuffle for sizeof(T)<4 types: a pair of
chained OpSubgroupShuffleINTEL ops on a value that round-trips through
OpUConvert ushort<->uint, with the narrowed result consumed inside a
block entered via OpBranchConditional.

IGC on Intel Arc miscompiles this pattern: the second shuffle returns 0
instead of the neighbor-lane value, so reductions are off by the lost
terms. With the current warp_shuffle_op implementation the test fails
with 16/16 mismatches (one per logical warp).

The test pairs with the rocprim.warp_reduce Floating/10 and /11
(ReduceSum on __half, LogicalWarpSize 4 and 8) failures.
…compile

IGC on Intel Arc A770 miscompiles chained OpSubgroupShuffleINTEL
when the shuffled value undergoes narrow->wide->shuffle->narrow
(OpUConvert ushort<->uint around the shuffle) and the narrowed
consumer sits in a block entered via OpBranchConditional. The
second chained shuffle returns 0 instead of the neighbor lane, so
rocPRIM warp_reduce_shuffle on __half with LogicalWarpSize < 32
produces systematically wrong sums.

The miscompile is deterministic and reproducible with a pure
Level Zero + SPIR-V assembler harness (see upstream IGC issue,
to be filed).

This patch adds a chipStar/SPIR-V-only warp_shuffle_op
specialization for trivially-copyable T with sizeof(T) < sizeof(int)
(covering __half and hip_bfloat16) that writes the post-shuffle
int into a volatile stack slot and loads the low sizeof(T) bytes
out via byte-wise memcpy from a volatile pointer. This emits
OpBitcast + OpLoad of the narrow type rather than a scalar-register
i32->i16 trunc, bypassing IGC's bad codegen path.

Upstream rocPRIM / AMD targets are unaffected: the specialization
is guarded on __HIP_PLATFORM_SPIRV__ and does not change the AMD
code path.

Resolves failures:
- test_warp_reduce  Floating/10,11 (__half ReduceSum)        2 -> 0
- test_warp_scan    Floating/11,12,20,21,22 (__half/bf16)    7 -> 0
- test_block_reduce Floating/9 (block_params<__half,__half,64>) 1 -> 0
- test_warp_shuffle_fp16 (new regression test)               FAIL -> PASS

Upstream IGC bug to be filed at intel/intel-graphics-compiler.
@pvelesko
pvelesko force-pushed the fix-warp-shuffle-fp16 branch from bc73c2f to b4d8bf0 Compare April 16, 2026 09:53
@pvelesko
pvelesko marked this pull request as ready for review April 17, 2026 05:38
@pvelesko
pvelesko merged commit 73eb0fa into main Apr 17, 2026
3 checks passed
@pvelesko
pvelesko deleted the fix-warp-shuffle-fp16 branch April 17, 2026 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant