| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgpu12.50-amd-amdhsa -o - %s | FileCheck %s --check-prefix GCN |
| |
| define amdgpu_kernel void @test_with_wmma( ptr addrspace(1) %input, ptr addrspace(1) %output, float %scaled_max, <16 x i32> %A, <16 x i32> %B, i32 %scale_idx) { |
| ; GCN-LABEL: define amdgpu_kernel void @test_with_wmma( |
| ; GCN-SAME: ptr addrspace(1) [[INPUT:%.*]], ptr addrspace(1) [[OUTPUT:%.*]], float [[SCALED_MAX:%.*]], <16 x i32> [[A:%.*]], <16 x i32> [[B:%.*]], i32 [[SCALE_IDX:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[IN0:%.*]] = load float, ptr addrspace(1) [[INPUT]], align 4 |
| ; GCN-NEXT: [[PTR1:%.*]] = getelementptr float, ptr addrspace(1) [[INPUT]], i64 1 |
| ; GCN-NEXT: [[IN1:%.*]] = load float, ptr addrspace(1) [[PTR1]], align 4 |
| ; GCN-NEXT: [[MUL0:%.*]] = fmul contract float [[IN0]], f0x3E0293EE |
| ; GCN-NEXT: [[MUL1:%.*]] = fmul contract float [[IN1]], f0x3E0293EE |
| ; GCN-NEXT: [[SUB0:%.*]] = fsub contract float [[MUL0]], [[SCALED_MAX]] |
| ; GCN-NEXT: [[SUB1:%.*]] = fsub contract float [[MUL1]], [[SCALED_MAX]] |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[SUB0]]) |
| ; GCN-NEXT: [[EXP1:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[SUB1]]) |
| ; GCN-NEXT: [[VEC0:%.*]] = insertelement <2 x float> poison, float [[EXP0]], i64 0 |
| ; GCN-NEXT: [[VEC1:%.*]] = insertelement <2 x float> [[VEC0]], float [[EXP1]], i64 1 |
| ; GCN-NEXT: [[VEC_I32:%.*]] = bitcast <2 x float> [[VEC1]] to <2 x i32> |
| ; GCN-NEXT: [[SCALE0:%.*]] = extractelement <2 x i32> [[VEC_I32]], i64 0 |
| ; GCN-NEXT: [[SCALE1:%.*]] = extractelement <2 x i32> [[VEC_I32]], i64 1 |
| ; GCN-NEXT: [[WMMA0:%.*]] = tail call <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32(i32 0, <16 x i32> [[A]], i32 0, <16 x i32> [[B]], i16 0, <8 x float> zeroinitializer, i32 0, i32 0, i32 [[SCALE0]], i32 0, i32 0, i32 [[SCALE_IDX]], i1 false, i1 false) |
| ; GCN-NEXT: [[WMMA1:%.*]] = tail call <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32(i32 0, <16 x i32> [[A]], i32 0, <16 x i32> [[B]], i16 0, <8 x float> [[WMMA0]], i32 0, i32 0, i32 [[SCALE1]], i32 0, i32 0, i32 [[SCALE_IDX]], i1 false, i1 false) |
| ; GCN-NEXT: store <8 x float> [[WMMA1]], ptr addrspace(1) [[OUTPUT]], align 32 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| |
| %in0 = load float, ptr addrspace(1) %input, align 4 |
| %ptr1 = getelementptr float, ptr addrspace(1) %input, i64 1 |
| %in1 = load float, ptr addrspace(1) %ptr1, align 4 |
| |
| %mul0 = fmul contract float %in0, 0x3FC0527DC0000000 |
| %mul1 = fmul contract float %in1, 0x3FC0527DC0000000 |
| |
| %sub0 = fsub contract float %mul0, %scaled_max |
| %sub1 = fsub contract float %mul1, %scaled_max |
| |
| %exp0 = tail call float @llvm.amdgcn.exp2.f32(float %sub0) |
| %exp1 = tail call float @llvm.amdgcn.exp2.f32(float %sub1) |
| |
| %vec0 = insertelement <2 x float> poison, float %exp0, i64 0 |
| %vec1 = insertelement <2 x float> %vec0, float %exp1, i64 1 |
| |
| %vec_i32 = bitcast <2 x float> %vec1 to <2 x i32> |
| |
| %scale0 = extractelement <2 x i32> %vec_i32, i64 0 |
| %scale1 = extractelement <2 x i32> %vec_i32, i64 1 |
| |
| %wmma0 = tail call <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32( |
| i32 0, <16 x i32> %A, i32 0, <16 x i32> %B, i16 0, <8 x float> zeroinitializer, |
| i32 0, i32 0, i32 %scale0, i32 0, i32 0, i32 %scale_idx, i1 false, i1 false) |
| |
| %wmma1 = tail call <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32( |
| i32 0, <16 x i32> %A, i32 0, <16 x i32> %B, i16 0, <8 x float> %wmma0, |
| i32 0, i32 0, i32 %scale1, i32 0, i32 0, i32 %scale_idx, i1 false, i1 false) |
| |
| store <8 x float> %wmma1, ptr addrspace(1) %output, align 32 |
| ret void |
| } |
| |
| define amdgpu_kernel void @test_amdgcn_exp_log(ptr addrspace(1) %input, ptr addrspace(1) %scales, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @test_amdgcn_exp_log( |
| ; GCN-SAME: ptr addrspace(1) [[INPUT:%.*]], ptr addrspace(1) [[SCALES:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr addrspace(1) [[INPUT]], align 4 |
| ; GCN-NEXT: [[TMP1:%.*]] = load <2 x float>, ptr addrspace(1) [[SCALES]], align 4 |
| ; GCN-NEXT: [[TMP2:%.*]] = fmul contract <2 x float> [[TMP0]], splat (float f0x3E0293EE) |
| ; GCN-NEXT: [[TMP3:%.*]] = fsub contract <2 x float> [[TMP2]], [[TMP1]] |
| ; GCN-NEXT: [[SUB0:%.*]] = extractelement <2 x float> [[TMP3]], i64 0 |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[SUB0]]) |
| ; GCN-NEXT: [[LOG0:%.*]] = tail call float @llvm.amdgcn.log.f32(float [[EXP0]]) |
| ; GCN-NEXT: [[SUB1:%.*]] = extractelement <2 x float> [[TMP3]], i64 1 |
| ; GCN-NEXT: [[EXP1:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[SUB1]]) |
| ; GCN-NEXT: [[LOG1:%.*]] = tail call float @llvm.amdgcn.log.f32(float [[EXP1]]) |
| ; GCN-NEXT: [[SUM:%.*]] = fadd fast float [[LOG0]], [[LOG1]] |
| ; GCN-NEXT: store float [[SUM]], ptr addrspace(1) [[OUTPUT]], align 4 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| %in0 = load float, ptr addrspace(1) %input, align 4 |
| %ptr1 = getelementptr float, ptr addrspace(1) %input, i64 1 |
| %in1 = load float, ptr addrspace(1) %ptr1, align 4 |
| %scale0 = load float, ptr addrspace(1) %scales, align 4 |
| %sptr1 = getelementptr float, ptr addrspace(1) %scales, i64 1 |
| %scale1 = load float, ptr addrspace(1) %sptr1, align 4 |
| %mul0 = fmul contract float %in0, 0x3FC0527DC0000000 |
| %mul1 = fmul contract float %in1, 0x3FC0527DC0000000 |
| %sub0 = fsub contract float %mul0, %scale0 |
| %sub1 = fsub contract float %mul1, %scale1 |
| %exp0 = tail call float @llvm.amdgcn.exp2.f32(float %sub0) |
| %log0 = tail call float @llvm.amdgcn.log.f32(float %exp0) |
| %exp1 = tail call float @llvm.amdgcn.exp2.f32(float %sub1) |
| %log1 = tail call float @llvm.amdgcn.log.f32(float %exp1) |
| %sum = fadd fast float %log0, %log1 |
| store float %sum, ptr addrspace(1) %output, align 4 |
| ret void |
| } |
| |
| define amdgpu_kernel void @test_amdgcn_exp_f16(ptr addrspace(1) %input, ptr addrspace(1) %scales, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @test_amdgcn_exp_f16( |
| ; GCN-SAME: ptr addrspace(1) [[INPUT:%.*]], ptr addrspace(1) [[SCALES:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr addrspace(1) [[INPUT]], align 2 |
| ; GCN-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[SCALES]], align 2 |
| ; GCN-NEXT: [[TMP2:%.*]] = fmul contract <2 x half> [[TMP0]], splat (half 1.519530e+00) |
| ; GCN-NEXT: [[TMP3:%.*]] = fsub contract <2 x half> [[TMP2]], [[TMP1]] |
| ; GCN-NEXT: [[SUB0:%.*]] = extractelement <2 x half> [[TMP3]], i64 0 |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[SUB0]]) |
| ; GCN-NEXT: [[SUB1:%.*]] = extractelement <2 x half> [[TMP3]], i64 1 |
| ; GCN-NEXT: [[EXP1:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[SUB1]]) |
| ; GCN-NEXT: [[SUM:%.*]] = fadd fast half [[EXP0]], [[EXP1]] |
| ; GCN-NEXT: store half [[SUM]], ptr addrspace(1) [[OUTPUT]], align 2 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| %in0 = load half, ptr addrspace(1) %input, align 2 |
| %ptr1 = getelementptr half, ptr addrspace(1) %input, i64 1 |
| %in1 = load half, ptr addrspace(1) %ptr1, align 2 |
| %scale0 = load half, ptr addrspace(1) %scales, align 2 |
| %sptr1 = getelementptr half, ptr addrspace(1) %scales, i64 1 |
| %scale1 = load half, ptr addrspace(1) %sptr1, align 2 |
| %mul0 = fmul contract half %in0, 0xH3E14 |
| %mul1 = fmul contract half %in1, 0xH3E14 |
| %sub0 = fsub contract half %mul0, %scale0 |
| %sub1 = fsub contract half %mul1, %scale1 |
| %exp0 = tail call half @llvm.amdgcn.exp2.f16(half %sub0) |
| %exp1 = tail call half @llvm.amdgcn.exp2.f16(half %sub1) |
| %sum = fadd fast half %exp0, %exp1 |
| store half %sum, ptr addrspace(1) %output, align 2 |
| ret void |
| } |
| |
| define amdgpu_kernel void @kernel_f16(ptr addrspace(1) %input, ptr addrspace(1) %scales, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @kernel_f16( |
| ; GCN-SAME: ptr addrspace(1) [[INPUT:%.*]], ptr addrspace(1) [[SCALES:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr addrspace(1) [[INPUT]], align 2 |
| ; GCN-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[SCALES]], align 2 |
| ; GCN-NEXT: [[TMP2:%.*]] = fmul contract <2 x half> [[TMP0]], splat (half 1.519530e+00) |
| ; GCN-NEXT: [[TMP3:%.*]] = fsub contract <2 x half> [[TMP2]], [[TMP1]] |
| ; GCN-NEXT: [[SUB0:%.*]] = extractelement <2 x half> [[TMP3]], i64 0 |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[SUB0]]) |
| ; GCN-NEXT: [[SUB1:%.*]] = extractelement <2 x half> [[TMP3]], i64 1 |
| ; GCN-NEXT: [[EXP1:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[SUB1]]) |
| ; GCN-NEXT: [[LOG0:%.*]] = tail call half @llvm.amdgcn.log.f16(half [[EXP0]]) |
| ; GCN-NEXT: [[LOG1:%.*]] = tail call half @llvm.amdgcn.log.f16(half [[EXP1]]) |
| ; GCN-NEXT: [[SUM:%.*]] = fadd fast half [[LOG0]], [[LOG1]] |
| ; GCN-NEXT: store half [[SUM]], ptr addrspace(1) [[OUTPUT]], align 2 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| %in0 = load half, ptr addrspace(1) %input, align 2 |
| %ptr1 = getelementptr half, ptr addrspace(1) %input, i64 1 |
| %in1 = load half, ptr addrspace(1) %ptr1, align 2 |
| %scale0 = load half, ptr addrspace(1) %scales, align 2 |
| %sptr1 = getelementptr half, ptr addrspace(1) %scales, i64 1 |
| %scale1 = load half, ptr addrspace(1) %sptr1, align 2 |
| %mul0 = fmul contract half %in0, 0xH3E14 |
| %mul1 = fmul contract half %in1, 0xH3E14 |
| %sub0 = fsub contract half %mul0, %scale0 |
| %sub1 = fsub contract half %mul1, %scale1 |
| %exp0 = tail call half @llvm.amdgcn.exp2.f16(half %sub0) |
| %exp1 = tail call half @llvm.amdgcn.exp2.f16(half %sub1) |
| %log0 = tail call half @llvm.amdgcn.log.f16(half %exp0) |
| %log1 = tail call half @llvm.amdgcn.log.f16(half %exp1) |
| %sum = fadd fast half %log0, %log1 |
| store half %sum, ptr addrspace(1) %output, align 2 |
| ret void |
| } |
| |
| define amdgpu_kernel void @look_through_reuse_shuffle( |
| ; GCN-LABEL: define amdgpu_kernel void @look_through_reuse_shuffle( |
| ; GCN-SAME: ptr addrspace(1) noalias [[INPUT:%.*]], ptr addrspace(1) noalias [[SCALES:%.*]], ptr addrspace(1) noalias [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[TMP4:%.*]] = load <2 x half>, ptr addrspace(1) [[INPUT]], align 2 |
| ; GCN-NEXT: [[TMP5:%.*]] = load <2 x half>, ptr addrspace(1) [[SCALES]], align 2 |
| ; GCN-NEXT: [[TMP6:%.*]] = fadd contract <2 x half> [[TMP4]], splat (half 1.519530e+00) |
| ; GCN-NEXT: [[TMP3:%.*]] = fmul contract <2 x half> [[TMP6]], [[TMP5]] |
| ; GCN-NEXT: [[MUL0:%.*]] = extractelement <2 x half> [[TMP3]], i64 0 |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[MUL0]]) |
| ; GCN-NEXT: [[MUL1:%.*]] = extractelement <2 x half> [[TMP3]], i64 1 |
| ; GCN-NEXT: [[EXP1:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[MUL1]]) |
| ; GCN-NEXT: [[TMP7:%.*]] = insertelement <4 x half> poison, half [[EXP0]], i64 0 |
| ; GCN-NEXT: [[TMP1:%.*]] = insertelement <4 x half> [[TMP7]], half [[EXP1]], i64 1 |
| ; GCN-NEXT: [[TMP2:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 1> |
| ; GCN-NEXT: store <4 x half> [[TMP2]], ptr addrspace(1) [[OUTPUT]], align 2 |
| ; GCN-NEXT: ret void |
| ; |
| ptr addrspace(1) noalias %input, ptr addrspace(1) noalias %scales, |
| ptr addrspace(1) noalias %output) { |
| entry: |
| %iptr1 = getelementptr half, ptr addrspace(1) %input, i64 1 |
| %sptr1 = getelementptr half, ptr addrspace(1) %scales, i64 1 |
| %optr1 = getelementptr half, ptr addrspace(1) %output, i64 1 |
| %optr2 = getelementptr half, ptr addrspace(1) %output, i64 2 |
| %optr3 = getelementptr half, ptr addrspace(1) %output, i64 3 |
| |
| %in0 = load half, ptr addrspace(1) %input, align 2 |
| %in1 = load half, ptr addrspace(1) %iptr1, align 2 |
| %s0 = load half, ptr addrspace(1) %scales, align 2 |
| %s1 = load half, ptr addrspace(1) %sptr1, align 2 |
| |
| %add0 = fadd contract half %in0, 0xH3E14 |
| %add1 = fadd contract half %in1, 0xH3E14 |
| |
| %mul0 = fmul contract half %add0, %s0 |
| %mul1 = fmul contract half %add1, %s1 |
| |
| %exp0 = tail call half @llvm.amdgcn.exp2.f16(half %mul0) |
| %exp1 = tail call half @llvm.amdgcn.exp2.f16(half %mul1) |
| |
| store half %exp0, ptr addrspace(1) %output, align 2 |
| store half %exp1, ptr addrspace(1) %optr1, align 2 |
| store half %exp1, ptr addrspace(1) %optr2, align 2 |
| store half %exp1, ptr addrspace(1) %optr3, align 2 |
| ret void |
| } |
| |
| define amdgpu_kernel void @wider_exp2_f32(ptr addrspace(1) %input, ptr addrspace(1) %scales, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @wider_exp2_f32( |
| ; GCN-SAME: ptr addrspace(1) [[INPUT:%.*]], ptr addrspace(1) [[SCALES:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[PTR2:%.*]] = getelementptr float, ptr addrspace(1) [[INPUT]], i64 2 |
| ; GCN-NEXT: [[SPTR2:%.*]] = getelementptr float, ptr addrspace(1) [[SCALES]], i64 2 |
| ; GCN-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr addrspace(1) [[INPUT]], align 4 |
| ; GCN-NEXT: [[TMP1:%.*]] = load <2 x float>, ptr addrspace(1) [[SCALES]], align 4 |
| ; GCN-NEXT: [[TMP2:%.*]] = fmul contract <2 x float> [[TMP0]], splat (float f0x3E0293EE) |
| ; GCN-NEXT: [[TMP3:%.*]] = fsub contract <2 x float> [[TMP2]], [[TMP1]] |
| ; GCN-NEXT: [[TMP4:%.*]] = load <2 x float>, ptr addrspace(1) [[PTR2]], align 4 |
| ; GCN-NEXT: [[TMP5:%.*]] = load <2 x float>, ptr addrspace(1) [[SPTR2]], align 4 |
| ; GCN-NEXT: [[TMP6:%.*]] = fmul contract <2 x float> [[TMP4]], splat (float f0x3E0293EE) |
| ; GCN-NEXT: [[TMP7:%.*]] = fsub contract <2 x float> [[TMP6]], [[TMP5]] |
| ; GCN-NEXT: [[SUB0:%.*]] = extractelement <2 x float> [[TMP3]], i64 0 |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[SUB0]]) |
| ; GCN-NEXT: [[SUB1:%.*]] = extractelement <2 x float> [[TMP3]], i64 1 |
| ; GCN-NEXT: [[EXP1:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[SUB1]]) |
| ; GCN-NEXT: [[SUB2:%.*]] = extractelement <2 x float> [[TMP7]], i64 0 |
| ; GCN-NEXT: [[EXP2:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[SUB2]]) |
| ; GCN-NEXT: [[SUB3:%.*]] = extractelement <2 x float> [[TMP7]], i64 1 |
| ; GCN-NEXT: [[EXP3:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[SUB3]]) |
| ; GCN-NEXT: [[SUM01:%.*]] = fadd fast float [[EXP0]], [[EXP1]] |
| ; GCN-NEXT: [[SUM23:%.*]] = fadd fast float [[EXP2]], [[EXP3]] |
| ; GCN-NEXT: [[SUM:%.*]] = fadd fast float [[SUM01]], [[SUM23]] |
| ; GCN-NEXT: store float [[SUM]], ptr addrspace(1) [[OUTPUT]], align 4 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| %in0 = load float, ptr addrspace(1) %input, align 4 |
| %ptr1 = getelementptr float, ptr addrspace(1) %input, i64 1 |
| %in1 = load float, ptr addrspace(1) %ptr1, align 4 |
| %ptr2 = getelementptr float, ptr addrspace(1) %input, i64 2 |
| %in2 = load float, ptr addrspace(1) %ptr2, align 4 |
| %ptr3 = getelementptr float, ptr addrspace(1) %input, i64 3 |
| %in3 = load float, ptr addrspace(1) %ptr3, align 4 |
| |
| %scale0 = load float, ptr addrspace(1) %scales, align 4 |
| %sptr1 = getelementptr float, ptr addrspace(1) %scales, i64 1 |
| %scale1 = load float, ptr addrspace(1) %sptr1, align 4 |
| %sptr2 = getelementptr float, ptr addrspace(1) %scales, i64 2 |
| %scale2 = load float, ptr addrspace(1) %sptr2, align 4 |
| %sptr3 = getelementptr float, ptr addrspace(1) %scales, i64 3 |
| %scale3 = load float, ptr addrspace(1) %sptr3, align 4 |
| |
| %mul0 = fmul contract float %in0, 0x3FC0527DC0000000 |
| %mul1 = fmul contract float %in1, 0x3FC0527DC0000000 |
| %mul2 = fmul contract float %in2, 0x3FC0527DC0000000 |
| %mul3 = fmul contract float %in3, 0x3FC0527DC0000000 |
| |
| %sub0 = fsub contract float %mul0, %scale0 |
| %sub1 = fsub contract float %mul1, %scale1 |
| %sub2 = fsub contract float %mul2, %scale2 |
| %sub3 = fsub contract float %mul3, %scale3 |
| |
| %exp0 = tail call float @llvm.amdgcn.exp2.f32(float %sub0) |
| %exp1 = tail call float @llvm.amdgcn.exp2.f32(float %sub1) |
| %exp2 = tail call float @llvm.amdgcn.exp2.f32(float %sub2) |
| %exp3 = tail call float @llvm.amdgcn.exp2.f32(float %sub3) |
| |
| %sum01 = fadd fast float %exp0, %exp1 |
| %sum23 = fadd fast float %exp2, %exp3 |
| %sum = fadd fast float %sum01, %sum23 |
| |
| store float %sum, ptr addrspace(1) %output, align 4 |
| ret void |
| } |
| |
| define amdgpu_kernel void @wider_exp2_half(ptr addrspace(1) %input, ptr addrspace(1) %scales, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @wider_exp2_half( |
| ; GCN-SAME: ptr addrspace(1) [[INPUT:%.*]], ptr addrspace(1) [[SCALES:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[PTR2:%.*]] = getelementptr half, ptr addrspace(1) [[INPUT]], i64 2 |
| ; GCN-NEXT: [[SPTR2:%.*]] = getelementptr half, ptr addrspace(1) [[SCALES]], i64 2 |
| ; GCN-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr addrspace(1) [[INPUT]], align 2 |
| ; GCN-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr addrspace(1) [[SCALES]], align 2 |
| ; GCN-NEXT: [[TMP2:%.*]] = fmul contract <2 x half> [[TMP0]], splat (half 1.519530e+00) |
| ; GCN-NEXT: [[TMP3:%.*]] = fsub contract <2 x half> [[TMP2]], [[TMP1]] |
| ; GCN-NEXT: [[TMP4:%.*]] = load <2 x half>, ptr addrspace(1) [[PTR2]], align 2 |
| ; GCN-NEXT: [[TMP5:%.*]] = load <2 x half>, ptr addrspace(1) [[SPTR2]], align 2 |
| ; GCN-NEXT: [[TMP6:%.*]] = fmul contract <2 x half> [[TMP4]], splat (half 1.519530e+00) |
| ; GCN-NEXT: [[TMP7:%.*]] = fsub contract <2 x half> [[TMP6]], [[TMP5]] |
| ; GCN-NEXT: [[SUB0:%.*]] = extractelement <2 x half> [[TMP3]], i64 0 |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[SUB0]]) |
| ; GCN-NEXT: [[SUB1:%.*]] = extractelement <2 x half> [[TMP3]], i64 1 |
| ; GCN-NEXT: [[EXP1:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[SUB1]]) |
| ; GCN-NEXT: [[SUB2:%.*]] = extractelement <2 x half> [[TMP7]], i64 0 |
| ; GCN-NEXT: [[EXP2:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[SUB2]]) |
| ; GCN-NEXT: [[SUB3:%.*]] = extractelement <2 x half> [[TMP7]], i64 1 |
| ; GCN-NEXT: [[EXP3:%.*]] = tail call half @llvm.amdgcn.exp2.f16(half [[SUB3]]) |
| ; GCN-NEXT: [[SUM01:%.*]] = fadd fast half [[EXP0]], [[EXP1]] |
| ; GCN-NEXT: [[SUM23:%.*]] = fadd fast half [[EXP2]], [[EXP3]] |
| ; GCN-NEXT: [[SUM:%.*]] = fadd fast half [[SUM01]], [[SUM23]] |
| ; GCN-NEXT: store half [[SUM]], ptr addrspace(1) [[OUTPUT]], align 2 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| ;; Same 4-wide pattern as wider_exp2_f32. Cost model gives half higher |
| ;; LookThrough cost, so we get 2-wide vectorization (or none on stricter targets). |
| %in0 = load half, ptr addrspace(1) %input, align 2 |
| %ptr1 = getelementptr half, ptr addrspace(1) %input, i64 1 |
| %in1 = load half, ptr addrspace(1) %ptr1, align 2 |
| %ptr2 = getelementptr half, ptr addrspace(1) %input, i64 2 |
| %in2 = load half, ptr addrspace(1) %ptr2, align 2 |
| %ptr3 = getelementptr half, ptr addrspace(1) %input, i64 3 |
| %in3 = load half, ptr addrspace(1) %ptr3, align 2 |
| |
| %scale0 = load half, ptr addrspace(1) %scales, align 2 |
| %sptr1 = getelementptr half, ptr addrspace(1) %scales, i64 1 |
| %scale1 = load half, ptr addrspace(1) %sptr1, align 2 |
| %sptr2 = getelementptr half, ptr addrspace(1) %scales, i64 2 |
| %scale2 = load half, ptr addrspace(1) %sptr2, align 2 |
| %sptr3 = getelementptr half, ptr addrspace(1) %scales, i64 3 |
| %scale3 = load half, ptr addrspace(1) %sptr3, align 2 |
| |
| %mul0 = fmul contract half %in0, 0xH3E14 |
| %mul1 = fmul contract half %in1, 0xH3E14 |
| %mul2 = fmul contract half %in2, 0xH3E14 |
| %mul3 = fmul contract half %in3, 0xH3E14 |
| |
| %sub0 = fsub contract half %mul0, %scale0 |
| %sub1 = fsub contract half %mul1, %scale1 |
| %sub2 = fsub contract half %mul2, %scale2 |
| %sub3 = fsub contract half %mul3, %scale3 |
| |
| %exp0 = tail call half @llvm.amdgcn.exp2.f16(half %sub0) |
| %exp1 = tail call half @llvm.amdgcn.exp2.f16(half %sub1) |
| %exp2 = tail call half @llvm.amdgcn.exp2.f16(half %sub2) |
| %exp3 = tail call half @llvm.amdgcn.exp2.f16(half %sub3) |
| |
| %sum01 = fadd fast half %exp0, %exp1 |
| %sum23 = fadd fast half %exp2, %exp3 |
| %sum = fadd fast half %sum01, %sum23 |
| |
| store half %sum, ptr addrspace(1) %output, align 2 |
| ret void |
| } |
| |
| define amdgpu_kernel void @kernel_div_scale(ptr addrspace(1) %num, ptr addrspace(1) %den, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @kernel_div_scale( |
| ; GCN-SAME: ptr addrspace(1) [[NUM:%.*]], ptr addrspace(1) [[DEN:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[NPTR2:%.*]] = getelementptr float, ptr addrspace(1) [[NUM]], i64 2 |
| ; GCN-NEXT: [[N2:%.*]] = load float, ptr addrspace(1) [[NPTR2]], align 4 |
| ; GCN-NEXT: [[DPTR2:%.*]] = getelementptr float, ptr addrspace(1) [[DEN]], i64 2 |
| ; GCN-NEXT: [[D2:%.*]] = load float, ptr addrspace(1) [[DPTR2]], align 4 |
| ; GCN-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr addrspace(1) [[NUM]], align 4 |
| ; GCN-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[TMP0]], splat (float 2.000000e+00) |
| ; GCN-NEXT: [[MUL_N2:%.*]] = fmul float [[N2]], 2.000000e+00 |
| ; GCN-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr addrspace(1) [[DEN]], align 4 |
| ; GCN-NEXT: [[TMP3:%.*]] = fmul <2 x float> [[TMP2]], splat (float 4.000000e+00) |
| ; GCN-NEXT: [[MUL_D2:%.*]] = fmul float [[D2]], 4.000000e+00 |
| ; GCN-NEXT: [[MUL_N0:%.*]] = extractelement <2 x float> [[TMP1]], i64 0 |
| ; GCN-NEXT: [[MUL_D0:%.*]] = extractelement <2 x float> [[TMP3]], i64 0 |
| ; GCN-NEXT: [[DS0:%.*]] = call { float, i1 } @llvm.amdgcn.div.scale.f32(float [[MUL_N0]], float [[MUL_D0]], i1 false) |
| ; GCN-NEXT: [[MUL_N1:%.*]] = extractelement <2 x float> [[TMP1]], i64 1 |
| ; GCN-NEXT: [[MUL_D1:%.*]] = extractelement <2 x float> [[TMP3]], i64 1 |
| ; GCN-NEXT: [[DS1:%.*]] = call { float, i1 } @llvm.amdgcn.div.scale.f32(float [[MUL_N1]], float [[MUL_D1]], i1 false) |
| ; GCN-NEXT: [[DS2:%.*]] = call { float, i1 } @llvm.amdgcn.div.scale.f32(float [[MUL_N2]], float [[MUL_D2]], i1 false) |
| ; GCN-NEXT: [[R0:%.*]] = extractvalue { float, i1 } [[DS0]], 0 |
| ; GCN-NEXT: [[R1:%.*]] = extractvalue { float, i1 } [[DS1]], 0 |
| ; GCN-NEXT: [[R2:%.*]] = extractvalue { float, i1 } [[DS2]], 0 |
| ; GCN-NEXT: [[SUM01:%.*]] = fadd float [[R0]], [[R1]] |
| ; GCN-NEXT: [[SUM:%.*]] = fadd float [[SUM01]], [[R2]] |
| ; GCN-NEXT: store float [[SUM]], ptr addrspace(1) [[OUTPUT]], align 4 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| %n0 = load float, ptr addrspace(1) %num, align 4 |
| %nptr1 = getelementptr float, ptr addrspace(1) %num, i64 1 |
| %n1 = load float, ptr addrspace(1) %nptr1, align 4 |
| %nptr2 = getelementptr float, ptr addrspace(1) %num, i64 2 |
| %n2 = load float, ptr addrspace(1) %nptr2, align 4 |
| %d0 = load float, ptr addrspace(1) %den, align 4 |
| %dptr1 = getelementptr float, ptr addrspace(1) %den, i64 1 |
| %d1 = load float, ptr addrspace(1) %dptr1, align 4 |
| %dptr2 = getelementptr float, ptr addrspace(1) %den, i64 2 |
| %d2 = load float, ptr addrspace(1) %dptr2, align 4 |
| %mul_n0 = fmul float %n0, 2.0 |
| %mul_n1 = fmul float %n1, 2.0 |
| %mul_n2 = fmul float %n2, 2.0 |
| %mul_d0 = fmul float %d0, 4.0 |
| %mul_d1 = fmul float %d1, 4.0 |
| %mul_d2 = fmul float %d2, 4.0 |
| %ds0 = call { float, i1 } @llvm.amdgcn.div.scale.f32(float %mul_n0, float %mul_d0, i1 false) |
| %ds1 = call { float, i1 } @llvm.amdgcn.div.scale.f32(float %mul_n1, float %mul_d1, i1 false) |
| %ds2 = call { float, i1 } @llvm.amdgcn.div.scale.f32(float %mul_n2, float %mul_d2, i1 false) |
| %r0 = extractvalue { float, i1 } %ds0, 0 |
| %r1 = extractvalue { float, i1 } %ds1, 0 |
| %r2 = extractvalue { float, i1 } %ds2, 0 |
| %sum01 = fadd float %r0, %r1 |
| %sum = fadd float %sum01, %r2 |
| store float %sum, ptr addrspace(1) %output, align 4 |
| ret void |
| } |
| |
| define amdgpu_kernel void @kernel_fmed3(ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @kernel_fmed3( |
| ; GCN-SAME: ptr addrspace(1) [[A:%.*]], ptr addrspace(1) [[B:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[APTR2:%.*]] = getelementptr float, ptr addrspace(1) [[A]], i64 2 |
| ; GCN-NEXT: [[A2:%.*]] = load float, ptr addrspace(1) [[APTR2]], align 4 |
| ; GCN-NEXT: [[BPTR2:%.*]] = getelementptr float, ptr addrspace(1) [[B]], i64 2 |
| ; GCN-NEXT: [[B2:%.*]] = load float, ptr addrspace(1) [[BPTR2]], align 4 |
| ; GCN-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr addrspace(1) [[A]], align 4 |
| ; GCN-NEXT: [[TMP1:%.*]] = load <2 x float>, ptr addrspace(1) [[B]], align 4 |
| ; GCN-NEXT: [[TMP2:%.*]] = fadd <2 x float> [[TMP0]], [[TMP1]] |
| ; GCN-NEXT: [[ADD2:%.*]] = fadd float [[A2]], [[B2]] |
| ; GCN-NEXT: [[ADD0:%.*]] = extractelement <2 x float> [[TMP2]], i64 0 |
| ; GCN-NEXT: [[MED0:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ADD0]], float [[ADD0]], float 1.000000e+00) |
| ; GCN-NEXT: [[ADD1:%.*]] = extractelement <2 x float> [[TMP2]], i64 1 |
| ; GCN-NEXT: [[MED1:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ADD1]], float [[ADD1]], float 1.000000e+00) |
| ; GCN-NEXT: [[MED2:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ADD2]], float [[ADD2]], float 1.000000e+00) |
| ; GCN-NEXT: [[SUM01:%.*]] = fadd float [[MED0]], [[MED1]] |
| ; GCN-NEXT: [[SUM:%.*]] = fadd float [[SUM01]], [[MED2]] |
| ; GCN-NEXT: store float [[SUM]], ptr addrspace(1) [[OUTPUT]], align 4 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| %a0 = load float, ptr addrspace(1) %a, align 4 |
| %aptr1 = getelementptr float, ptr addrspace(1) %a, i64 1 |
| %a1 = load float, ptr addrspace(1) %aptr1, align 4 |
| %aptr2 = getelementptr float, ptr addrspace(1) %a, i64 2 |
| %a2 = load float, ptr addrspace(1) %aptr2, align 4 |
| |
| %b0 = load float, ptr addrspace(1) %b, align 4 |
| %bptr1 = getelementptr float, ptr addrspace(1) %b, i64 1 |
| %b1 = load float, ptr addrspace(1) %bptr1, align 4 |
| %bptr2 = getelementptr float, ptr addrspace(1) %b, i64 2 |
| %b2 = load float, ptr addrspace(1) %bptr2, align 4 |
| |
| %add0 = fadd float %a0, %b0 |
| %add1 = fadd float %a1, %b1 |
| %add2 = fadd float %a2, %b2 |
| |
| %med0 = call float @llvm.amdgcn.fmed3.f32(float %add0, float %add0, float 1.0) |
| %med1 = call float @llvm.amdgcn.fmed3.f32(float %add1, float %add1, float 1.0) |
| %med2 = call float @llvm.amdgcn.fmed3.f32(float %add2, float %add2, float 1.0) |
| |
| %sum01 = fadd float %med0, %med1 |
| %sum = fadd float %sum01, %med2 |
| store float %sum, ptr addrspace(1) %output, align 4 |
| ret void |
| } |
| |
| define amdgpu_kernel void @kernel_fmed3_1(ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @kernel_fmed3_1( |
| ; GCN-SAME: ptr addrspace(1) [[A:%.*]], ptr addrspace(1) [[B:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[A0:%.*]] = load float, ptr addrspace(1) [[A]], align 4 |
| ; GCN-NEXT: [[APTR1:%.*]] = getelementptr float, ptr addrspace(1) [[A]], i64 1 |
| ; GCN-NEXT: [[A1:%.*]] = load float, ptr addrspace(1) [[APTR1]], align 4 |
| ; GCN-NEXT: [[APTR2:%.*]] = getelementptr float, ptr addrspace(1) [[A]], i64 2 |
| ; GCN-NEXT: [[A2:%.*]] = load float, ptr addrspace(1) [[APTR2]], align 4 |
| ; GCN-NEXT: [[APTR3:%.*]] = getelementptr float, ptr addrspace(1) [[A]], i64 3 |
| ; GCN-NEXT: [[A3:%.*]] = load float, ptr addrspace(1) [[APTR3]], align 4 |
| ; GCN-NEXT: [[B0:%.*]] = load float, ptr addrspace(1) [[B]], align 4 |
| ; GCN-NEXT: [[BPTR1:%.*]] = getelementptr float, ptr addrspace(1) [[B]], i64 1 |
| ; GCN-NEXT: [[B1:%.*]] = load float, ptr addrspace(1) [[BPTR1]], align 4 |
| ; GCN-NEXT: [[BPTR2:%.*]] = getelementptr float, ptr addrspace(1) [[B]], i64 2 |
| ; GCN-NEXT: [[B2:%.*]] = load float, ptr addrspace(1) [[BPTR2]], align 4 |
| ; GCN-NEXT: [[BPTR3:%.*]] = getelementptr float, ptr addrspace(1) [[B]], i64 3 |
| ; GCN-NEXT: [[B3:%.*]] = load float, ptr addrspace(1) [[BPTR3]], align 4 |
| ; GCN-NEXT: [[ADD0:%.*]] = fadd float 5.000000e+00, [[B0]] |
| ; GCN-NEXT: [[ADD1:%.*]] = fadd float 5.000000e+00, [[B1]] |
| ; GCN-NEXT: [[ADD2:%.*]] = fadd float 5.000000e+00, [[B2]] |
| ; GCN-NEXT: [[ADD3:%.*]] = fadd float 5.000000e+00, [[B3]] |
| ; GCN-NEXT: [[SUB0:%.*]] = fadd float 1.000000e+00, [[B0]] |
| ; GCN-NEXT: [[SUB1:%.*]] = fadd float 1.000000e+00, [[B1]] |
| ; GCN-NEXT: [[SUB2:%.*]] = fadd float 1.000000e+00, [[B2]] |
| ; GCN-NEXT: [[SUB3:%.*]] = fadd float 1.000000e+00, [[B3]] |
| ; GCN-NEXT: [[MED0:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ADD0]], float [[SUB0]], float 1.000000e+00) |
| ; GCN-NEXT: [[MED1:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ADD1]], float [[SUB1]], float 1.000000e+00) |
| ; GCN-NEXT: [[MED2:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ADD2]], float [[SUB2]], float 1.000000e+00) |
| ; GCN-NEXT: [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ADD3]], float [[SUB3]], float 1.000000e+00) |
| ; GCN-NEXT: [[SUM01:%.*]] = fadd float [[MED0]], [[MED1]] |
| ; GCN-NEXT: [[SUM02:%.*]] = fadd float [[MED2]], [[MED3]] |
| ; GCN-NEXT: [[SUM:%.*]] = fadd float [[SUM01]], [[SUM02]] |
| ; GCN-NEXT: store float [[SUM]], ptr addrspace(1) [[OUTPUT]], align 4 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| %a0 = load float, ptr addrspace(1) %a, align 4 |
| %aptr1 = getelementptr float, ptr addrspace(1) %a, i64 1 |
| %a1 = load float, ptr addrspace(1) %aptr1, align 4 |
| %aptr2 = getelementptr float, ptr addrspace(1) %a, i64 2 |
| %a2 = load float, ptr addrspace(1) %aptr2, align 4 |
| %aptr3 = getelementptr float, ptr addrspace(1) %a, i64 3 |
| %a3 = load float, ptr addrspace(1) %aptr3, align 4 |
| |
| %b0 = load float, ptr addrspace(1) %b, align 4 |
| %bptr1 = getelementptr float, ptr addrspace(1) %b, i64 1 |
| %b1 = load float, ptr addrspace(1) %bptr1, align 4 |
| %bptr2 = getelementptr float, ptr addrspace(1) %b, i64 2 |
| %b2 = load float, ptr addrspace(1) %bptr2, align 4 |
| %bptr3 = getelementptr float, ptr addrspace(1) %b, i64 3 |
| %b3 = load float, ptr addrspace(1) %bptr3, align 4 |
| |
| %add0 = fadd float 5.0, %b0 |
| %add1 = fadd float 5.0, %b1 |
| %add2 = fadd float 5.0, %b2 |
| %add3 = fadd float 5.0, %b3 |
| |
| %sub0 = fadd float 1.0, %b0 |
| %sub1 = fadd float 1.0, %b1 |
| %sub2 = fadd float 1.0, %b2 |
| %sub3 = fadd float 1.0, %b3 |
| |
| %med0 = call float @llvm.amdgcn.fmed3.f32(float %add0, float %sub0, float 1.0) |
| %med1 = call float @llvm.amdgcn.fmed3.f32(float %add1, float %sub1, float 1.0) |
| %med2 = call float @llvm.amdgcn.fmed3.f32(float %add2, float %sub2, float 1.0) |
| %med3 = call float @llvm.amdgcn.fmed3.f32(float %add3, float %sub3, float 1.0) |
| |
| %sum01 = fadd float %med0, %med1 |
| %sum02 = fadd float %med2, %med3 |
| %sum = fadd float %sum01, %sum02 |
| store float %sum, ptr addrspace(1) %output, align 4 |
| ret void |
| } |
| |
| define amdgpu_kernel void @test_single_exp_hreduction( |
| ; GCN-LABEL: define amdgpu_kernel void @test_single_exp_hreduction( |
| ; GCN-SAME: ptr addrspace(1) [[INPUT:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[P0:%.*]] = getelementptr float, ptr addrspace(1) [[INPUT]], i64 0 |
| ; GCN-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr addrspace(1) [[P0]], align 4 |
| ; GCN-NEXT: [[TMP1:%.*]] = call fast float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[TMP0]]) |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[TMP1]]) |
| ; GCN-NEXT: store float [[EXP0]], ptr addrspace(1) [[OUTPUT]], align 4 |
| ; GCN-NEXT: ret void |
| ; |
| ptr addrspace(1) %input, ptr addrspace(1) %output) { |
| entry: |
| %p0 = getelementptr float, ptr addrspace(1) %input, i64 0 |
| %p1 = getelementptr float, ptr addrspace(1) %input, i64 1 |
| %p2 = getelementptr float, ptr addrspace(1) %input, i64 2 |
| %p3 = getelementptr float, ptr addrspace(1) %input, i64 3 |
| |
| %a0 = load float, ptr addrspace(1) %p0, align 4 |
| %a1 = load float, ptr addrspace(1) %p1, align 4 |
| %a2 = load float, ptr addrspace(1) %p2, align 4 |
| %a3 = load float, ptr addrspace(1) %p3, align 4 |
| |
| %add01 = fadd fast float %a0, %a1 |
| %add23 = fadd fast float %a2, %a3 |
| %sum = fadd fast float %add01, %add23 |
| |
| %exp0 = tail call float @llvm.amdgcn.exp2.f32(float %sum) |
| store float %exp0, ptr addrspace(1) %output, align 4 |
| ret void |
| } |
| |
| define amdgpu_kernel void @test_hreduction_into_exp( |
| ; GCN-LABEL: define amdgpu_kernel void @test_hreduction_into_exp( |
| ; GCN-SAME: ptr addrspace(1) [[INPUT:%.*]], ptr addrspace(1) [[OUTPUT:%.*]], <16 x i32> [[A:%.*]], <16 x i32> [[B:%.*]], i32 [[SCALE_IDX:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[P0:%.*]] = getelementptr float, ptr addrspace(1) [[INPUT]], i64 0 |
| ; GCN-NEXT: [[P4:%.*]] = getelementptr float, ptr addrspace(1) [[INPUT]], i64 4 |
| ; GCN-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr addrspace(1) [[P0]], align 4 |
| ; GCN-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr addrspace(1) [[P4]], align 4 |
| ; GCN-NEXT: [[TMP2:%.*]] = call fast float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[TMP0]]) |
| ; GCN-NEXT: [[TMP3:%.*]] = call fast float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[TMP1]]) |
| ; GCN-NEXT: [[EXP0:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[TMP2]]) |
| ; GCN-NEXT: [[EXP1:%.*]] = tail call float @llvm.amdgcn.exp2.f32(float [[TMP3]]) |
| ; GCN-NEXT: [[VEC0:%.*]] = insertelement <2 x float> poison, float [[EXP0]], i64 0 |
| ; GCN-NEXT: [[VEC1:%.*]] = insertelement <2 x float> [[VEC0]], float [[EXP1]], i64 1 |
| ; GCN-NEXT: [[VEC_I32:%.*]] = bitcast <2 x float> [[VEC1]] to <2 x i32> |
| ; GCN-NEXT: [[SCALE0:%.*]] = extractelement <2 x i32> [[VEC_I32]], i64 0 |
| ; GCN-NEXT: [[SCALE1:%.*]] = extractelement <2 x i32> [[VEC_I32]], i64 1 |
| ; GCN-NEXT: [[WMMA0:%.*]] = tail call <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32(i32 0, <16 x i32> [[A]], i32 0, <16 x i32> [[B]], i16 0, <8 x float> zeroinitializer, i32 0, i32 0, i32 [[SCALE0]], i32 0, i32 0, i32 [[SCALE_IDX]], i1 false, i1 false) |
| ; GCN-NEXT: [[WMMA1:%.*]] = tail call <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32(i32 0, <16 x i32> [[A]], i32 0, <16 x i32> [[B]], i16 0, <8 x float> [[WMMA0]], i32 0, i32 0, i32 [[SCALE1]], i32 0, i32 0, i32 [[SCALE_IDX]], i1 false, i1 false) |
| ; GCN-NEXT: store <8 x float> [[WMMA1]], ptr addrspace(1) [[OUTPUT]], align 32 |
| ; GCN-NEXT: ret void |
| ; |
| ptr addrspace(1) %input, ptr addrspace(1) %output, |
| <16 x i32> %A, <16 x i32> %B, i32 %scale_idx) { |
| entry: |
| %p0 = getelementptr float, ptr addrspace(1) %input, i64 0 |
| %p1 = getelementptr float, ptr addrspace(1) %input, i64 1 |
| %p2 = getelementptr float, ptr addrspace(1) %input, i64 2 |
| %p3 = getelementptr float, ptr addrspace(1) %input, i64 3 |
| %p4 = getelementptr float, ptr addrspace(1) %input, i64 4 |
| %p5 = getelementptr float, ptr addrspace(1) %input, i64 5 |
| %p6 = getelementptr float, ptr addrspace(1) %input, i64 6 |
| %p7 = getelementptr float, ptr addrspace(1) %input, i64 7 |
| |
| %a0 = load float, ptr addrspace(1) %p0, align 4 |
| %a1 = load float, ptr addrspace(1) %p1, align 4 |
| %a2 = load float, ptr addrspace(1) %p2, align 4 |
| %a3 = load float, ptr addrspace(1) %p3, align 4 |
| %b0 = load float, ptr addrspace(1) %p4, align 4 |
| %b1 = load float, ptr addrspace(1) %p5, align 4 |
| %b2 = load float, ptr addrspace(1) %p6, align 4 |
| %b3 = load float, ptr addrspace(1) %p7, align 4 |
| |
| %add_a01 = fadd fast float %a0, %a1 |
| %add_a23 = fadd fast float %a2, %a3 |
| %sum0 = fadd fast float %add_a01, %add_a23 |
| |
| %add_b01 = fadd fast float %b0, %b1 |
| %add_b23 = fadd fast float %b2, %b3 |
| %sum1 = fadd fast float %add_b01, %add_b23 |
| |
| |
| %exp0 = tail call float @llvm.amdgcn.exp2.f32(float %sum0) |
| %exp1 = tail call float @llvm.amdgcn.exp2.f32(float %sum1) |
| |
| %vec0 = insertelement <2 x float> poison, float %exp0, i64 0 |
| %vec1 = insertelement <2 x float> %vec0, float %exp1, i64 1 |
| %vec_i32 = bitcast <2 x float> %vec1 to <2 x i32> |
| %scale0 = extractelement <2 x i32> %vec_i32, i64 0 |
| %scale1 = extractelement <2 x i32> %vec_i32, i64 1 |
| |
| %wmma0 = tail call <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32( |
| i32 0, <16 x i32> %A, i32 0, <16 x i32> %B, i16 0, <8 x float> zeroinitializer, |
| i32 0, i32 0, i32 %scale0, i32 0, i32 0, i32 %scale_idx, i1 false, i1 false) |
| |
| %wmma1 = tail call <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32( |
| i32 0, <16 x i32> %A, i32 0, <16 x i32> %B, i16 0, <8 x float> %wmma0, |
| i32 0, i32 0, i32 %scale1, i32 0, i32 0, i32 %scale_idx, i1 false, i1 false) |
| |
| store <8 x float> %wmma1, ptr addrspace(1) %output, align 32 |
| ret void |
| } |
| |
| define amdgpu_kernel void @kernel_alternate(ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %output) { |
| ; GCN-LABEL: define amdgpu_kernel void @kernel_alternate( |
| ; GCN-SAME: ptr addrspace(1) [[A:%.*]], ptr addrspace(1) [[B:%.*]], ptr addrspace(1) [[OUTPUT:%.*]]) { |
| ; GCN-NEXT: [[ENTRY:.*:]] |
| ; GCN-NEXT: [[A0:%.*]] = load float, ptr addrspace(1) [[A]], align 4 |
| ; GCN-NEXT: [[APTR1:%.*]] = getelementptr float, ptr addrspace(1) [[A]], i64 1 |
| ; GCN-NEXT: [[A1:%.*]] = load float, ptr addrspace(1) [[APTR1]], align 4 |
| ; GCN-NEXT: [[APTR2:%.*]] = getelementptr float, ptr addrspace(1) [[A]], i64 2 |
| ; GCN-NEXT: [[A2:%.*]] = load float, ptr addrspace(1) [[APTR2]], align 4 |
| ; GCN-NEXT: [[B0:%.*]] = load float, ptr addrspace(1) [[B]], align 4 |
| ; GCN-NEXT: [[BPTR1:%.*]] = getelementptr float, ptr addrspace(1) [[B]], i64 1 |
| ; GCN-NEXT: [[B1:%.*]] = load float, ptr addrspace(1) [[BPTR1]], align 4 |
| ; GCN-NEXT: [[BPTR2:%.*]] = getelementptr float, ptr addrspace(1) [[B]], i64 2 |
| ; GCN-NEXT: [[B2:%.*]] = load float, ptr addrspace(1) [[BPTR2]], align 4 |
| ; GCN-NEXT: [[ADD0:%.*]] = fadd float [[A0]], [[B0]] |
| ; GCN-NEXT: [[SUB0:%.*]] = fsub float [[A0]], [[B0]] |
| ; GCN-NEXT: [[ADD1:%.*]] = fadd float [[A1]], [[B1]] |
| ; GCN-NEXT: [[SUB1:%.*]] = fsub float [[A1]], [[B1]] |
| ; GCN-NEXT: [[ADD2:%.*]] = fadd float [[A2]], [[B2]] |
| ; GCN-NEXT: [[SUB2:%.*]] = fsub float [[A2]], [[B2]] |
| ; GCN-NEXT: [[E0:%.*]] = call float @llvm.amdgcn.exp2.f32(float [[ADD0]]) |
| ; GCN-NEXT: [[E1:%.*]] = call float @llvm.amdgcn.exp2.f32(float [[SUB0]]) |
| ; GCN-NEXT: [[E2:%.*]] = call float @llvm.amdgcn.log.f32(float [[ADD1]]) |
| ; GCN-NEXT: [[E3:%.*]] = call float @llvm.amdgcn.log.f32(float [[SUB1]]) |
| ; GCN-NEXT: [[E4:%.*]] = call float @llvm.amdgcn.exp2.f32(float [[ADD2]]) |
| ; GCN-NEXT: [[E5:%.*]] = call float @llvm.amdgcn.exp2.f32(float [[SUB2]]) |
| ; GCN-NEXT: [[OPTR0:%.*]] = getelementptr float, ptr addrspace(1) [[OUTPUT]], i64 0 |
| ; GCN-NEXT: [[OPTR1:%.*]] = getelementptr float, ptr addrspace(1) [[OUTPUT]], i64 1 |
| ; GCN-NEXT: [[OPTR2:%.*]] = getelementptr float, ptr addrspace(1) [[OUTPUT]], i64 2 |
| ; GCN-NEXT: [[OPTR3:%.*]] = getelementptr float, ptr addrspace(1) [[OUTPUT]], i64 3 |
| ; GCN-NEXT: [[OPTR4:%.*]] = getelementptr float, ptr addrspace(1) [[OUTPUT]], i64 4 |
| ; GCN-NEXT: [[OPTR5:%.*]] = getelementptr float, ptr addrspace(1) [[OUTPUT]], i64 5 |
| ; GCN-NEXT: store float [[E0]], ptr addrspace(1) [[OPTR0]], align 4 |
| ; GCN-NEXT: store float [[E1]], ptr addrspace(1) [[OPTR1]], align 4 |
| ; GCN-NEXT: store float [[E2]], ptr addrspace(1) [[OPTR2]], align 4 |
| ; GCN-NEXT: store float [[E3]], ptr addrspace(1) [[OPTR3]], align 4 |
| ; GCN-NEXT: store float [[E4]], ptr addrspace(1) [[OPTR4]], align 4 |
| ; GCN-NEXT: store float [[E5]], ptr addrspace(1) [[OPTR5]], align 4 |
| ; GCN-NEXT: ret void |
| ; |
| entry: |
| %a0 = load float, ptr addrspace(1) %a, align 4 |
| %aptr1 = getelementptr float, ptr addrspace(1) %a, i64 1 |
| %a1 = load float, ptr addrspace(1) %aptr1, align 4 |
| %aptr2 = getelementptr float, ptr addrspace(1) %a, i64 2 |
| %a2 = load float, ptr addrspace(1) %aptr2, align 4 |
| |
| %b0 = load float, ptr addrspace(1) %b, align 4 |
| %bptr1 = getelementptr float, ptr addrspace(1) %b, i64 1 |
| %b1 = load float, ptr addrspace(1) %bptr1, align 4 |
| %bptr2 = getelementptr float, ptr addrspace(1) %b, i64 2 |
| %b2 = load float, ptr addrspace(1) %bptr2, align 4 |
| |
| %add0 = fadd float %a0, %b0 |
| %sub0 = fsub float %a0, %b0 |
| %add1 = fadd float %a1, %b1 |
| %sub1 = fsub float %a1, %b1 |
| %add2 = fadd float %a2, %b2 |
| %sub2 = fsub float %a2, %b2 |
| |
| %e0 = call float @llvm.amdgcn.exp2.f32(float %add0) |
| %e1 = call float @llvm.amdgcn.exp2.f32(float %sub0) |
| %e2 = call float @llvm.amdgcn.log.f32(float %add1) |
| %e3 = call float @llvm.amdgcn.log.f32(float %sub1) |
| %e4 = call float @llvm.amdgcn.exp2.f32(float %add2) |
| %e5 = call float @llvm.amdgcn.exp2.f32(float %sub2) |
| |
| %optr0 = getelementptr float, ptr addrspace(1) %output, i64 0 |
| %optr1 = getelementptr float, ptr addrspace(1) %output, i64 1 |
| %optr2 = getelementptr float, ptr addrspace(1) %output, i64 2 |
| %optr3 = getelementptr float, ptr addrspace(1) %output, i64 3 |
| %optr4 = getelementptr float, ptr addrspace(1) %output, i64 4 |
| %optr5 = getelementptr float, ptr addrspace(1) %output, i64 5 |
| |
| store float %e0, ptr addrspace(1) %optr0, align 4 |
| store float %e1, ptr addrspace(1) %optr1, align 4 |
| store float %e2, ptr addrspace(1) %optr2, align 4 |
| store float %e3, ptr addrspace(1) %optr3, align 4 |
| store float %e4, ptr addrspace(1) %optr4, align 4 |
| store float %e5, ptr addrspace(1) %optr5, align 4 |
| ret void |
| } |
| |
| declare float @llvm.amdgcn.fmed3.f32(float, float, float) |
| declare { float, i1 } @llvm.amdgcn.div.scale.f32(float, float, i1) |
| declare half @llvm.amdgcn.exp2.f16(half) |
| declare float @llvm.amdgcn.exp2.f32(float) |
| declare <8 x float> @llvm.amdgcn.wmma.scale.f32.16x16x128.f8f6f4.v8f32.v16i32.v16i32(i32 immarg, <16 x i32>, i32 immarg, <16 x i32>, i16 immarg, <8 x float>, i32 immarg, i32 immarg, i32, i32 immarg, i32 immarg, i32, i1 immarg, i1 immarg) |