blob: 0aff1cd646a4488b7f3e8f8954b47cab4b609888 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=slp-vectorizer < %s | FileCheck -check-prefixes=NOPACKED %s
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -passes=slp-vectorizer < %s | FileCheck -check-prefixes=GFX90A %s
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 -passes=slp-vectorizer < %s | FileCheck -check-prefixes=GFX1250 %s
; Both functions build the same tree: gather two scalars into <2 x float>, one
; packed fadd, then a pair of stores. The only difference is what feeds the
; gathered lanes.
; A lane fed by a load is packed for free by the memory pipeline, so the tree
; stays profitable on targets with v_pk_*_f32.
define amdgpu_kernel void @load_fed_gather(ptr addrspace(1) %out, ptr addrspace(1) %in) {
; NOPACKED-LABEL: define amdgpu_kernel void @load_fed_gather(
; NOPACKED-SAME: ptr addrspace(1) [[OUT:%.*]], ptr addrspace(1) [[IN:%.*]]) #[[ATTR0:[0-9]+]] {
; NOPACKED-NEXT: [[Q0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN]], i64 0
; NOPACKED-NEXT: [[Q1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN]], i64 17
; NOPACKED-NEXT: [[L0:%.*]] = load float, ptr addrspace(1) [[Q0]], align 4
; NOPACKED-NEXT: [[L1:%.*]] = load float, ptr addrspace(1) [[Q1]], align 4
; NOPACKED-NEXT: [[R0:%.*]] = fadd float [[L0]], 1.000000e+00
; NOPACKED-NEXT: [[R1:%.*]] = fadd float [[L1]], 2.000000e+00
; NOPACKED-NEXT: [[P0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 0
; NOPACKED-NEXT: [[P1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 1
; NOPACKED-NEXT: store float [[R0]], ptr addrspace(1) [[P0]], align 8
; NOPACKED-NEXT: store float [[R1]], ptr addrspace(1) [[P1]], align 4
; NOPACKED-NEXT: ret void
;
; GFX90A-LABEL: define amdgpu_kernel void @load_fed_gather(
; GFX90A-SAME: ptr addrspace(1) [[OUT:%.*]], ptr addrspace(1) [[IN:%.*]]) #[[ATTR0:[0-9]+]] {
; GFX90A-NEXT: [[Q0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN]], i64 0
; GFX90A-NEXT: [[Q1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN]], i64 17
; GFX90A-NEXT: [[L0:%.*]] = load float, ptr addrspace(1) [[Q0]], align 4
; GFX90A-NEXT: [[L1:%.*]] = load float, ptr addrspace(1) [[Q1]], align 4
; GFX90A-NEXT: [[P0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 0
; GFX90A-NEXT: [[TMP1:%.*]] = insertelement <2 x float> poison, float [[L0]], i64 0
; GFX90A-NEXT: [[TMP2:%.*]] = insertelement <2 x float> [[TMP1]], float [[L1]], i64 1
; GFX90A-NEXT: [[TMP3:%.*]] = fadd <2 x float> [[TMP2]], <float 1.000000e+00, float 2.000000e+00>
; GFX90A-NEXT: store <2 x float> [[TMP3]], ptr addrspace(1) [[P0]], align 8
; GFX90A-NEXT: ret void
;
; GFX1250-LABEL: define amdgpu_kernel void @load_fed_gather(
; GFX1250-SAME: ptr addrspace(1) [[OUT:%.*]], ptr addrspace(1) [[IN:%.*]]) #[[ATTR0:[0-9]+]] {
; GFX1250-NEXT: [[Q0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN]], i64 0
; GFX1250-NEXT: [[Q1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN]], i64 17
; GFX1250-NEXT: [[L0:%.*]] = load float, ptr addrspace(1) [[Q0]], align 4
; GFX1250-NEXT: [[L1:%.*]] = load float, ptr addrspace(1) [[Q1]], align 4
; GFX1250-NEXT: [[P0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 0
; GFX1250-NEXT: [[TMP1:%.*]] = insertelement <2 x float> poison, float [[L0]], i64 0
; GFX1250-NEXT: [[TMP2:%.*]] = insertelement <2 x float> [[TMP1]], float [[L1]], i64 1
; GFX1250-NEXT: [[TMP3:%.*]] = fadd <2 x float> [[TMP2]], <float 1.000000e+00, float 2.000000e+00>
; GFX1250-NEXT: store <2 x float> [[TMP3]], ptr addrspace(1) [[P0]], align 8
; GFX1250-NEXT: ret void
;
; PACKED-LABEL: define amdgpu_kernel void @load_fed_gather(
; PACKED-SAME: ptr addrspace(1) [[OUT:%.*]], ptr addrspace(1) [[IN:%.*]]) #[[ATTR0:[0-9]+]] {
; PACKED-NEXT: [[Q0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN]], i64 0
; PACKED-NEXT: [[Q1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN]], i64 17
; PACKED-NEXT: [[L0:%.*]] = load float, ptr addrspace(1) [[Q0]], align 4
; PACKED-NEXT: [[L1:%.*]] = load float, ptr addrspace(1) [[Q1]], align 4
; PACKED-NEXT: [[P0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 0
; PACKED-NEXT: [[TMP1:%.*]] = insertelement <2 x float> poison, float [[L0]], i64 0
; PACKED-NEXT: [[TMP2:%.*]] = insertelement <2 x float> [[TMP1]], float [[L1]], i64 1
; PACKED-NEXT: [[TMP3:%.*]] = fadd <2 x float> [[TMP2]], <float 1.000000e+00, float 2.000000e+00>
; PACKED-NEXT: store <2 x float> [[TMP3]], ptr addrspace(1) [[P0]], align 8
; PACKED-NEXT: ret void
%q0 = getelementptr inbounds float, ptr addrspace(1) %in, i64 0
%q1 = getelementptr inbounds float, ptr addrspace(1) %in, i64 17
%l0 = load float, ptr addrspace(1) %q0, align 4
%l1 = load float, ptr addrspace(1) %q1, align 4
%r0 = fadd float %l0, 1.0
%r1 = fadd float %l1, 2.0
%p0 = getelementptr inbounds float, ptr addrspace(1) %out, i64 0
%p1 = getelementptr inbounds float, ptr addrspace(1) %out, i64 1
store float %r0, ptr addrspace(1) %p0, align 8
store float %r1, ptr addrspace(1) %p1, align 4
ret void
}
; A lane fed by a computed value has to be moved into place, and that packing
; work eats the saving from the single packed fadd, so the tree is rejected.
define amdgpu_kernel void @compute_fed_gather(ptr addrspace(1) %out, float %a, float %b) {
; NOPACKED-LABEL: define amdgpu_kernel void @compute_fed_gather(
; NOPACKED-SAME: ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR0]] {
; NOPACKED-NEXT: [[L0:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[A]])
; NOPACKED-NEXT: [[L1:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[B]])
; NOPACKED-NEXT: [[R0:%.*]] = fadd float [[L0]], 1.000000e+00
; NOPACKED-NEXT: [[R1:%.*]] = fadd float [[L1]], 2.000000e+00
; NOPACKED-NEXT: [[P0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 0
; NOPACKED-NEXT: [[P1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 1
; NOPACKED-NEXT: store float [[R0]], ptr addrspace(1) [[P0]], align 8
; NOPACKED-NEXT: store float [[R1]], ptr addrspace(1) [[P1]], align 4
; NOPACKED-NEXT: ret void
;
; GFX90A-LABEL: define amdgpu_kernel void @compute_fed_gather(
; GFX90A-SAME: ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR0]] {
; GFX90A-NEXT: [[L0:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[A]])
; GFX90A-NEXT: [[L1:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[B]])
; GFX90A-NEXT: [[R0:%.*]] = fadd float [[L0]], 1.000000e+00
; GFX90A-NEXT: [[R1:%.*]] = fadd float [[L1]], 2.000000e+00
; GFX90A-NEXT: [[P0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 0
; GFX90A-NEXT: [[P1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 1
; GFX90A-NEXT: store float [[R0]], ptr addrspace(1) [[P0]], align 8
; GFX90A-NEXT: store float [[R1]], ptr addrspace(1) [[P1]], align 4
; GFX90A-NEXT: ret void
;
; GFX1250-LABEL: define amdgpu_kernel void @compute_fed_gather(
; GFX1250-SAME: ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR0]] {
; GFX1250-NEXT: [[L0:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[A]])
; GFX1250-NEXT: [[L1:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[B]])
; GFX1250-NEXT: [[R0:%.*]] = fadd float [[L0]], 1.000000e+00
; GFX1250-NEXT: [[R1:%.*]] = fadd float [[L1]], 2.000000e+00
; GFX1250-NEXT: [[P0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 0
; GFX1250-NEXT: [[P1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 1
; GFX1250-NEXT: store float [[R0]], ptr addrspace(1) [[P0]], align 8
; GFX1250-NEXT: store float [[R1]], ptr addrspace(1) [[P1]], align 4
; GFX1250-NEXT: ret void
;
; PACKED-LABEL: define amdgpu_kernel void @compute_fed_gather(
; PACKED-SAME: ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR0]] {
; PACKED-NEXT: [[L0:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[A]])
; PACKED-NEXT: [[L1:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[B]])
; PACKED-NEXT: [[R0:%.*]] = fadd float [[L0]], 1.000000e+00
; PACKED-NEXT: [[R1:%.*]] = fadd float [[L1]], 2.000000e+00
; PACKED-NEXT: [[P0:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 0
; PACKED-NEXT: [[P1:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 1
; PACKED-NEXT: store float [[R0]], ptr addrspace(1) [[P0]], align 8
; PACKED-NEXT: store float [[R1]], ptr addrspace(1) [[P1]], align 4
; PACKED-NEXT: ret void
%l0 = call float @llvm.amdgcn.rcp.f32(float %a)
%l1 = call float @llvm.amdgcn.rcp.f32(float %b)
%r0 = fadd float %l0, 1.0
%r1 = fadd float %l1, 2.0
%p0 = getelementptr inbounds float, ptr addrspace(1) %out, i64 0
%p1 = getelementptr inbounds float, ptr addrspace(1) %out, i64 1
store float %r0, ptr addrspace(1) %p0, align 8
store float %r1, ptr addrspace(1) %p1, align 4
ret void
}
declare float @llvm.amdgcn.rcp.f32(float)