.version 6.5
.target sm_30
.address_size 64

.visible .entry shfl_sync_mode_b32(
    .param .u64 output
)
{
    .reg .u64 	      out_addr;
    .reg .u64 	      out_index;
    .reg .u32         thread_id;
    .reg .u32         temp;
    .reg .u32         result;

    ld.param.u64  	  out_addr, [output];
    mov.u32           thread_id, %tid.x;

    // result = __shfl_up_sync(mask=0xFFFFFFFF, thread_id, delta=3, width=2)
    // c is ((32-width) << 8)
    shfl.sync.up.b32 temp, thread_id, 3, 7680, 0xFFFFFFFF;
    mov.u32 result, temp;

    // result += __shfl_down_sync(mask=0xFFFFFFFF, thread_id, delta=3, width=4)
    // c is ((32-width) << 8) | 31
    shfl.sync.down.b32 temp, thread_id, 3, 7199, 0xFFFFFFFF;
    add.u32 result, result, temp;

    // result = __shfl_xor_sync(mask=0xFFFFFFFF, thread_id, delta=3, width=8)
    // c is ((32-width) << 8) | 31
    shfl.sync.bfly.b32 temp, thread_id, 3, 6175, 0xFFFFFFFF;
    add.u32 result, result, temp;

    // result = __shfl_sync(mask=0xFFFFFFFF, thread_id, delta=3, width=16)
    // c is ((32-width) << 8) | 31
    shfl.sync.idx.b32 temp, thread_id, 3, 4127, 0xFFFFFFFF;
    add.u32 result, result, temp;

    // Return result

    cvt.u64.u32       out_index, thread_id;
    mul.lo.u64        out_index, out_index, 4;
    add.u64           out_addr, out_addr, out_index;
    st.u32            [out_addr], result;

    ret;
}
