blob: 12f0a684a8e8241df9cb2c0d0737b79db48f0c12 [file] [edit]
# RUN: llc -mtriple=amdgpu10.10 -run-pass=gcn-dpp-combine -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,PRE-GFX11 %s
# RUN: llc -mtriple=amdgpu10.30 -run-pass=gcn-dpp-combine -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,PRE-GFX11 %s
# RUN: llc -mtriple=amdgpu11.00 -run-pass=gcn-dpp-combine -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,GFX11PLUS %s
# RUN: llc -mtriple=amdgpu12.00 -run-pass=gcn-dpp-combine -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,GFX11PLUS %s
---
# The DPP value is src1 of a subtract, so folding requires commuting
# V_SUB_U32_e32 into V_SUBREV_U32_dpp, which is not allowed.
# CHECK-LABEL: name: dpp_commute_to_rev_sub
# CHECK: %3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
# CHECK-NEXT: %4:vgpr_32 = V_SUB_U32_e32 %1, %3, implicit $exec
name: dpp_commute_to_rev_sub
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0, $vgpr1
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = COPY $vgpr1
%2:vgpr_32 = IMPLICIT_DEF
%3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%4:vgpr_32 = V_SUB_U32_e32 %1, %3, implicit $exec
S_NOP 0, implicit %4
...
---
# Both sources of the subtract are the same register, so a mis-routed DPP
# silently yields the negated result rather than an obviously wrong instruction.
# CHECK-LABEL: name: dpp_commute_to_rev_sub_same_reg
# CHECK: %2:vgpr_32 = V_MOV_B32_dpp %1, %0, 0, 15, 15, 1, implicit $exec
# CHECK-NEXT: %3:vgpr_32 = V_SUB_U32_e32 %0, %2, implicit $exec
name: dpp_commute_to_rev_sub_same_reg
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = IMPLICIT_DEF
%2:vgpr_32 = V_MOV_B32_dpp %1, %0, 0, 15, 15, 1, implicit $exec
%3:vgpr_32 = V_SUB_U32_e32 %0, %2, implicit $exec
S_NOP 0, implicit %3
...
---
# A DPP mov feeding src0 of a REV opcode directly is rejected the same way as
# one that has to be commuted into it.
# CHECK-LABEL: name: dpp_rev_sub_src0
# CHECK: %3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
# CHECK-NEXT: %4:vgpr_32 = V_SUBREV_U32_e32 %3, %1, implicit $exec
name: dpp_rev_sub_src0
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0, $vgpr1
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = COPY $vgpr1
%2:vgpr_32 = IMPLICIT_DEF
%3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%4:vgpr_32 = V_SUBREV_U32_e32 %3, %1, implicit $exec
S_NOP 0, implicit %4
...
---
# The carry in subtract commutes into V_SUBBREV_U32 (V_SUBREV_CO_CI_U32 on
# gfx10+), which is a REV opcode as well.
# CHECK-LABEL: name: dpp_commute_to_rev_subb
# CHECK: %4:vgpr_32 = V_MOV_B32_dpp %3, %0, 1, 15, 15, 1, implicit $exec
# CHECK-NEXT: %5:vgpr_32, %6:sreg_32_xm0_xexec = V_SUBB_U32_e64 %1, %4, %2, 0, implicit $exec
name: dpp_commute_to_rev_subb
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0, $vgpr1, $sgpr0
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = COPY $vgpr1
%2:sreg_32_xm0_xexec = COPY $sgpr0
%3:vgpr_32 = IMPLICIT_DEF
%4:vgpr_32 = V_MOV_B32_dpp %3, %0, 1, 15, 15, 1, implicit $exec
%5:vgpr_32, %6:sreg_32_xm0_xexec = V_SUBB_U32_e64 %1, %4, %2, 0, implicit $exec
S_NOP 0, implicit %5
...
---
# The shift REV opcodes take the shift amount in src0, and reversed their
# operands before GFX11.
# CHECK-LABEL: name: dpp_rev_shift_src0
# PRE-GFX11: %3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
# PRE-GFX11-NEXT: %4:vgpr_32 = V_LSHLREV_B32_e32 %3, %1, implicit $exec
# PRE-GFX11: %5:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
# PRE-GFX11-NEXT: %6:vgpr_32 = V_LSHRREV_B32_e32 %5, %1, implicit $exec
# PRE-GFX11: %7:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
# PRE-GFX11-NEXT: %8:vgpr_32 = V_ASHRREV_I32_e32 %7, %1, implicit $exec
# GFX11PLUS: %4:vgpr_32 = V_LSHLREV_B32_dpp %2, %0, %1, 1, 15, 15, 1, implicit $exec
# GFX11PLUS: %6:vgpr_32 = V_LSHRREV_B32_dpp %2, %0, %1, 1, 15, 15, 1, implicit $exec
# GFX11PLUS: %8:vgpr_32 = V_ASHRREV_I32_dpp %2, %0, %1, 1, 15, 15, 1, implicit $exec
name: dpp_rev_shift_src0
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0, $vgpr1
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = COPY $vgpr1
%2:vgpr_32 = IMPLICIT_DEF
%3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%4:vgpr_32 = V_LSHLREV_B32_e32 %3, %1, implicit $exec
%5:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%6:vgpr_32 = V_LSHRREV_B32_e32 %5, %1, implicit $exec
%7:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%8:vgpr_32 = V_ASHRREV_I32_e32 %7, %1, implicit $exec
S_NOP 0, implicit %4, implicit %6, implicit %8
...
---
# Float subtracts are an add with a negate modifier rather than a real operand
# reversal, so V_SUBREV_F32 still takes the fold.
# CHECK-LABEL: name: dpp_commute_to_rev_sub_f32
# CHECK: %4:vgpr_32 = V_SUBREV_F32_dpp %2, 0, %0, 0, %1, 1, 15, 15, 1, implicit $mode, implicit $exec
name: dpp_commute_to_rev_sub_f32
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0, $vgpr1
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = COPY $vgpr1
%2:vgpr_32 = IMPLICIT_DEF
%3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%4:vgpr_32 = V_SUB_F32_e32 %1, %3, implicit $mode, implicit $exec
S_NOP 0, implicit %4
...
---
# Positive control: the DPP value is already src0 of a non-REV opcode, so no
# commute is needed and the fold is legal.
# CHECK-LABEL: name: dpp_no_commute_needed
# CHECK: %4:vgpr_32 = V_SUB_U32_dpp %2, %0, %1, 1, 15, 15, 1, implicit $exec
name: dpp_no_commute_needed
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0, $vgpr1
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = COPY $vgpr1
%2:vgpr_32 = IMPLICIT_DEF
%3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%4:vgpr_32 = V_SUB_U32_e32 %3, %1, implicit $exec
S_NOP 0, implicit %4
...
---
# Positive control: commuting an opcode that is its own reverse keeps the same
# opcode, so it still folds.
# CHECK-LABEL: name: dpp_commute_symmetric
# CHECK: %4:vgpr_32 = V_ADD_U32_dpp %2, %0, %1, 1, 15, 15, 1, implicit $exec
# CHECK: %6:vgpr_32 = V_OR_B32_dpp %2, %0, %1, 1, 15, 15, 1, implicit $exec
name: dpp_commute_symmetric
tracksRegLiveness: true
body: |
bb.0:
liveins: $vgpr0, $vgpr1
%0:vgpr_32 = COPY $vgpr0
%1:vgpr_32 = COPY $vgpr1
%2:vgpr_32 = IMPLICIT_DEF
%3:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%4:vgpr_32 = V_ADD_U32_e32 %1, %3, implicit $exec
%5:vgpr_32 = V_MOV_B32_dpp %2, %0, 1, 15, 15, 1, implicit $exec
%6:vgpr_32 = V_OR_B32_e32 %1, %5, implicit $exec
S_NOP 0, implicit %4, implicit %6
...