| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: llc -mtriple=amdgpu9.00-amd-amdhsa < %s | FileCheck -check-prefix=GFX9 %s |
| ; RUN: llc -mtriple=amdgpu12.00-amd-amdhsa -mattr=+real-true16 < %s | FileCheck -check-prefixes=GFX12,GFX12-TRUE16 %s |
| ; RUN: llc -mtriple=amdgpu12.00-amd-amdhsa -mattr=-real-true16 < %s | FileCheck -check-prefixes=GFX12,GFX12-FAKE16 %s |
| |
| ; bitextract |
| define i1 @test_bitextract_b8_off0(b8 %src) { |
| ; GFX9-LABEL: test_bitextract_b8_off0: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-LABEL: test_bitextract_b8_off0: |
| ; GFX12: ; %bb.0: |
| ; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-NEXT: s_setpc_b64 s[30:31] |
| %result = bitextract i1, b8 %src, i32 0 |
| ret i1 %result |
| } |
| |
| define i4 @test_bitextract_b8_nibble_hi(b8 %src) { |
| ; GFX9-LABEL: test_bitextract_b8_nibble_hi: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_bfe_u32 v0, v0, 4, 4 |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-TRUE16-LABEL: test_bitextract_b8_nibble_hi: |
| ; GFX12-TRUE16: ; %bb.0: |
| ; GFX12-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-TRUE16-NEXT: v_lshrrev_b16 v0.l, 4, v0.l |
| ; GFX12-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) |
| ; GFX12-TRUE16-NEXT: v_and_b16 v0.l, v0.l, 15 |
| ; GFX12-TRUE16-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-FAKE16-LABEL: test_bitextract_b8_nibble_hi: |
| ; GFX12-FAKE16: ; %bb.0: |
| ; GFX12-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-FAKE16-NEXT: v_bfe_u32 v0, v0, 4, 4 |
| ; GFX12-FAKE16-NEXT: s_setpc_b64 s[30:31] |
| %result = bitextract i4, b8 %src, i32 4 |
| ret i4 %result |
| } |
| |
| define i1 @test_bitextract_b8_off_top(b8 %src) { |
| ; GFX9-LABEL: test_bitextract_b8_off_top: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_bfe_u32 v0, v0, 7, 1 |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-TRUE16-LABEL: test_bitextract_b8_off_top: |
| ; GFX12-TRUE16: ; %bb.0: |
| ; GFX12-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-TRUE16-NEXT: v_lshrrev_b16 v0.l, 7, v0.l |
| ; GFX12-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) |
| ; GFX12-TRUE16-NEXT: v_and_b16 v0.l, v0.l, 1 |
| ; GFX12-TRUE16-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-FAKE16-LABEL: test_bitextract_b8_off_top: |
| ; GFX12-FAKE16: ; %bb.0: |
| ; GFX12-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-FAKE16-NEXT: v_bfe_u32 v0, v0, 7, 1 |
| ; GFX12-FAKE16-NEXT: s_setpc_b64 s[30:31] |
| %result = bitextract i1, b8 %src, i32 7 |
| ret i1 %result |
| } |
| |
| define i8 @test_bitextract_b16_byte_hi(b16 %src) { |
| ; GFX9-LABEL: test_bitextract_b16_byte_hi: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_lshrrev_b16_e32 v0, 8, v0 |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-TRUE16-LABEL: test_bitextract_b16_byte_hi: |
| ; GFX12-TRUE16: ; %bb.0: |
| ; GFX12-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-TRUE16-NEXT: v_lshrrev_b16 v0.l, 8, v0.l |
| ; GFX12-TRUE16-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-FAKE16-LABEL: test_bitextract_b16_byte_hi: |
| ; GFX12-FAKE16: ; %bb.0: |
| ; GFX12-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-FAKE16-NEXT: v_lshrrev_b16 v0, 8, v0 |
| ; GFX12-FAKE16-NEXT: s_setpc_b64 s[30:31] |
| %result = bitextract i8, b16 %src, i32 8 |
| ret i8 %result |
| } |
| |
| define i32 @test_bitextract_b64_dword_hi(b64 %src) { |
| ; GFX9-LABEL: test_bitextract_b64_dword_hi: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_mov_b32_e32 v0, v1 |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-LABEL: test_bitextract_b64_dword_hi: |
| ; GFX12: ; %bb.0: |
| ; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-NEXT: v_mov_b32_e32 v0, v1 |
| ; GFX12-NEXT: s_setpc_b64 s[30:31] |
| %result = bitextract i32, b64 %src, i32 32 |
| ret i32 %result |
| } |
| |
| define i64 @test_bitextract_b128_lo64(b128 %src) { |
| ; GFX9-LABEL: test_bitextract_b128_lo64: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-LABEL: test_bitextract_b128_lo64: |
| ; GFX12: ; %bb.0: |
| ; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-NEXT: s_setpc_b64 s[30:31] |
| %result = bitextract i64, b128 %src, i32 0 |
| ret i64 %result |
| } |
| |
| define b8 @test_bitinsert_b8_off1(b8 %base, i1 %val) { |
| ; GFX9-LABEL: test_bitinsert_b8_off1: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_and_b32_e32 v1, 1, v1 |
| ; GFX9-NEXT: v_and_b32_e32 v0, -3, v0 |
| ; GFX9-NEXT: v_lshlrev_b16_e32 v1, 1, v1 |
| ; GFX9-NEXT: v_or_b32_e32 v0, v0, v1 |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-TRUE16-LABEL: test_bitinsert_b8_off1: |
| ; GFX12-TRUE16: ; %bb.0: |
| ; GFX12-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-TRUE16-NEXT: v_and_b16 v0.h, v1.l, 1 |
| ; GFX12-TRUE16-NEXT: v_and_b16 v0.l, v0.l, -3 |
| ; GFX12-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1) |
| ; GFX12-TRUE16-NEXT: v_lshlrev_b16 v0.h, 1, v0.h |
| ; GFX12-TRUE16-NEXT: v_or_b16 v0.l, v0.l, v0.h |
| ; GFX12-TRUE16-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-FAKE16-LABEL: test_bitinsert_b8_off1: |
| ; GFX12-FAKE16: ; %bb.0: |
| ; GFX12-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-FAKE16-NEXT: v_and_b32_e32 v1, 1, v1 |
| ; GFX12-FAKE16-NEXT: v_and_b32_e32 v0, -3, v0 |
| ; GFX12-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1) |
| ; GFX12-FAKE16-NEXT: v_lshlrev_b16 v1, 1, v1 |
| ; GFX12-FAKE16-NEXT: v_or_b32_e32 v0, v0, v1 |
| ; GFX12-FAKE16-NEXT: s_setpc_b64 s[30:31] |
| %result = bitinsert b8 %base, i1 %val, i32 1 |
| ret b8 %result |
| } |
| |
| define b16 @test_bitinsert_b16_off8(b16 %base, i8 %val) { |
| ; GFX9-LABEL: test_bitinsert_b16_off8: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_lshlrev_b16_e32 v1, 8, v1 |
| ; GFX9-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-TRUE16-LABEL: test_bitinsert_b16_off8: |
| ; GFX12-TRUE16: ; %bb.0: |
| ; GFX12-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-TRUE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l |
| ; GFX12-TRUE16-NEXT: v_and_b16 v0.l, 0xff, v0.l |
| ; GFX12-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) |
| ; GFX12-TRUE16-NEXT: v_or_b16 v0.l, v0.l, v0.h |
| ; GFX12-TRUE16-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-FAKE16-LABEL: test_bitinsert_b16_off8: |
| ; GFX12-FAKE16: ; %bb.0: |
| ; GFX12-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-FAKE16-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1 |
| ; GFX12-FAKE16-NEXT: v_and_b32_e32 v0, 0xff, v0 |
| ; GFX12-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) |
| ; GFX12-FAKE16-NEXT: v_or_b32_e32 v0, v0, v1 |
| ; GFX12-FAKE16-NEXT: s_setpc_b64 s[30:31] |
| %result = bitinsert b16 %base, i8 %val, i32 8 |
| ret b16 %result |
| } |
| |
| ; b32 container: offsets 1, 2, 4, 8, 16 |
| |
| define b32 @test_bitinsert_b32_off8(b32 %base, i8 %val) { |
| ; GFX9-LABEL: test_bitinsert_b32_off8: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_mov_b32_e32 v2, 8 |
| ; GFX9-NEXT: v_lshlrev_b32_sdwa v1, v2, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:BYTE_0 |
| ; GFX9-NEXT: s_mov_b32 s4, 0xffff00ff |
| ; GFX9-NEXT: v_and_or_b32 v0, v0, s4, v1 |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-LABEL: test_bitinsert_b32_off8: |
| ; GFX12: ; %bb.0: |
| ; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-NEXT: v_and_b32_e32 v1, 0xff, v1 |
| ; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) |
| ; GFX12-NEXT: v_lshlrev_b32_e32 v1, 8, v1 |
| ; GFX12-NEXT: v_and_or_b32 v0, 0xffff00ff, v0, v1 |
| ; GFX12-NEXT: s_setpc_b64 s[30:31] |
| %result = bitinsert b32 %base, i8 %val, i32 8 |
| ret b32 %result |
| } |
| |
| define b64 @test_bitinsert_b64_off32(b64 %base, i32 %val) { |
| ; GFX9-LABEL: test_bitinsert_b64_off32: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_mov_b32_e32 v1, v2 |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-LABEL: test_bitinsert_b64_off32: |
| ; GFX12: ; %bb.0: |
| ; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-NEXT: v_mov_b32_e32 v1, v2 |
| ; GFX12-NEXT: s_setpc_b64 s[30:31] |
| %result = bitinsert b64 %base, i32 %val, i32 32 |
| ret b64 %result |
| } |
| |
| |
| ; b128 container: offsets 1, 2, 4, 8, 16, 32, 64 |
| |
| define b128 @test_bitinsert_b128_off64(b128 %base, i64 %val) { |
| ; GFX9-LABEL: test_bitinsert_b128_off64: |
| ; GFX9: ; %bb.0: |
| ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) |
| ; GFX9-NEXT: v_mov_b32_e32 v3, v5 |
| ; GFX9-NEXT: v_mov_b32_e32 v2, v4 |
| ; GFX9-NEXT: s_setpc_b64 s[30:31] |
| ; |
| ; GFX12-LABEL: test_bitinsert_b128_off64: |
| ; GFX12: ; %bb.0: |
| ; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0 |
| ; GFX12-NEXT: s_wait_expcnt 0x0 |
| ; GFX12-NEXT: s_wait_samplecnt 0x0 |
| ; GFX12-NEXT: s_wait_bvhcnt 0x0 |
| ; GFX12-NEXT: s_wait_kmcnt 0x0 |
| ; GFX12-NEXT: v_dual_mov_b32 v3, v5 :: v_dual_mov_b32 v2, v4 |
| ; GFX12-NEXT: s_setpc_b64 s[30:31] |
| %result = bitinsert b128 %base, i64 %val, i32 64 |
| ret b128 %result |
| } |