blob: 6a6e7675eb40743fc47c9df6887e04a11d378c17 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=amdgpu9.00 < %s | FileCheck -check-prefix=GFX9 %s
; RUN: llc -mtriple=amdgpu10.10 < %s | FileCheck -check-prefix=GFX10 %s
; Verify that uniform (SGPR) byte-packing operations produce v_perm_b32
; instead of scalar s_and/s_lshl/s_or sequences. The OR and AND DAG combines
; that create PERM nodes were previously gated on isDivergent(), preventing
; uniform values from using the more efficient v_perm_b32 instruction.
; OR combine: pack low bytes of two uniform values.
define amdgpu_kernel void @or_uniform_two_bytes(ptr addrspace(1) %out, i32 inreg %a, i32 inreg %b) {
; GFX9-LABEL: or_uniform_two_bytes:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x24
; GFX9-NEXT: v_mov_b32_e32 v2, 0x6050400
; GFX9-NEXT: v_mov_b32_e32 v0, 0
; GFX9-NEXT: s_waitcnt lgkmcnt(0)
; GFX9-NEXT: s_and_b32 s3, s3, 0xff
; GFX9-NEXT: v_mov_b32_e32 v1, s2
; GFX9-NEXT: v_perm_b32 v1, s3, v1, v2
; GFX9-NEXT: global_store_dword v0, v1, s[0:1]
; GFX9-NEXT: s_endpgm
;
; GFX10-LABEL: or_uniform_two_bytes:
; GFX10: ; %bb.0:
; GFX10-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x24
; GFX10-NEXT: v_mov_b32_e32 v0, 0x6050400
; GFX10-NEXT: v_mov_b32_e32 v1, 0
; GFX10-NEXT: s_waitcnt lgkmcnt(0)
; GFX10-NEXT: s_and_b32 s3, s3, 0xff
; GFX10-NEXT: v_perm_b32 v0, s3, s2, v0
; GFX10-NEXT: global_store_dword v1, v0, s[0:1]
; GFX10-NEXT: s_endpgm
%a.byte = and i32 %a, 255
%b.byte = and i32 %b, 255
%b.shifted = shl i32 %b.byte, 8
%packed = or i32 %a.byte, %b.shifted
store i32 %packed, ptr addrspace(1) %out
ret void
}
; OR combine: pack 4 uniform i8 values (the WMMA scale operand pattern).
define amdgpu_kernel void @or_uniform_v4i8(ptr addrspace(1) %out, i8 inreg %a, i8 inreg %b) {
; GFX9-LABEL: or_uniform_v4i8:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_load_dword s2, s[4:5], 0x2c
; GFX9-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24
; GFX9-NEXT: v_mov_b32_e32 v2, 0x1010104
; GFX9-NEXT: v_mov_b32_e32 v0, 0
; GFX9-NEXT: s_waitcnt lgkmcnt(0)
; GFX9-NEXT: s_and_b32 s3, s2, 0xff
; GFX9-NEXT: v_mov_b32_e32 v1, s2
; GFX9-NEXT: v_perm_b32 v1, s3, v1, v2
; GFX9-NEXT: global_store_dword v0, v1, s[0:1]
; GFX9-NEXT: s_endpgm
;
; GFX10-LABEL: or_uniform_v4i8:
; GFX10: ; %bb.0:
; GFX10-NEXT: s_clause 0x1
; GFX10-NEXT: s_load_dword s2, s[4:5], 0x2c
; GFX10-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24
; GFX10-NEXT: v_mov_b32_e32 v0, 0x1010104
; GFX10-NEXT: v_mov_b32_e32 v1, 0
; GFX10-NEXT: s_waitcnt lgkmcnt(0)
; GFX10-NEXT: s_and_b32 s3, s2, 0xff
; GFX10-NEXT: v_perm_b32 v0, s3, s2, v0
; GFX10-NEXT: global_store_dword v1, v0, s[0:1]
; GFX10-NEXT: s_endpgm
%v0 = insertelement <4 x i8> poison, i8 %a, i64 0
%v1 = insertelement <4 x i8> %v0, i8 %b, i64 1
%v2 = insertelement <4 x i8> %v1, i8 %b, i64 2
%v3 = insertelement <4 x i8> %v2, i8 %b, i64 3
%packed = bitcast <4 x i8> %v3 to i32
store i32 %packed, ptr addrspace(1) %out
ret void
}
; OR combine: splat a uniform i8 into all 4 byte lanes.
define amdgpu_kernel void @or_uniform_splat_i8(ptr addrspace(1) %out, i8 inreg %a) {
; GFX9-LABEL: or_uniform_splat_i8:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_load_dword s2, s[4:5], 0x2c
; GFX9-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24
; GFX9-NEXT: v_mov_b32_e32 v1, 0x4040404
; GFX9-NEXT: v_mov_b32_e32 v0, 0
; GFX9-NEXT: s_waitcnt lgkmcnt(0)
; GFX9-NEXT: s_and_b32 s2, s2, 0xff
; GFX9-NEXT: v_perm_b32 v1, s2, s2, v1
; GFX9-NEXT: global_store_dword v0, v1, s[0:1]
; GFX9-NEXT: s_endpgm
;
; GFX10-LABEL: or_uniform_splat_i8:
; GFX10: ; %bb.0:
; GFX10-NEXT: s_clause 0x1
; GFX10-NEXT: s_load_dword s2, s[4:5], 0x2c
; GFX10-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24
; GFX10-NEXT: v_mov_b32_e32 v0, 0
; GFX10-NEXT: s_waitcnt lgkmcnt(0)
; GFX10-NEXT: s_and_b32 s2, s2, 0xff
; GFX10-NEXT: v_perm_b32 v1, s2, s2, 0x4040404
; GFX10-NEXT: global_store_dword v0, v1, s[0:1]
; GFX10-NEXT: s_endpgm
%v0 = insertelement <4 x i8> poison, i8 %a, i64 0
%v1 = insertelement <4 x i8> %v0, i8 %a, i64 1
%v2 = insertelement <4 x i8> %v1, i8 %a, i64 2
%v3 = insertelement <4 x i8> %v2, i8 %a, i64 3
%packed = bitcast <4 x i8> %v3 to i32
store i32 %packed, ptr addrspace(1) %out
ret void
}
; AND combine: interleave bytes from two uniform sources using complementary
; OR masks. and(or(a, 0xFF00FF00), or(b, 0x00FF00FF)) selects even bytes from
; b and odd bytes from a.
define amdgpu_kernel void @and_uniform_interleave_bytes(ptr addrspace(1) %out, i32 inreg %a, i32 inreg %b) {
; GFX9-LABEL: and_uniform_interleave_bytes:
; GFX9: ; %bb.0:
; GFX9-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x24
; GFX9-NEXT: v_mov_b32_e32 v2, 0x7020500
; GFX9-NEXT: v_mov_b32_e32 v0, 0
; GFX9-NEXT: s_waitcnt lgkmcnt(0)
; GFX9-NEXT: v_mov_b32_e32 v1, s2
; GFX9-NEXT: v_perm_b32 v1, s3, v1, v2
; GFX9-NEXT: global_store_dword v0, v1, s[0:1]
; GFX9-NEXT: s_endpgm
;
; GFX10-LABEL: and_uniform_interleave_bytes:
; GFX10: ; %bb.0:
; GFX10-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x24
; GFX10-NEXT: v_mov_b32_e32 v0, 0x7020500
; GFX10-NEXT: v_mov_b32_e32 v1, 0
; GFX10-NEXT: s_waitcnt lgkmcnt(0)
; GFX10-NEXT: v_perm_b32 v0, s3, s2, v0
; GFX10-NEXT: global_store_dword v1, v0, s[0:1]
; GFX10-NEXT: s_endpgm
%a.or = or i32 %a, -16711936
%b.or = or i32 %b, 16711935
%result = and i32 %a.or, %b.or
store i32 %result, ptr addrspace(1) %out
ret void
}