[llvm] cc54f8e - AMDGPU: Add baseline tests for fmed3 shrinking combine

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed May 10 00:03:37 PDT 2023


Author: Matt Arsenault
Date: 2023-05-10T08:02:11+01:00
New Revision: cc54f8eec733c6d40656e10ddccdf15ffb99bbaf

URL: https://github.com/llvm/llvm-project/commit/cc54f8eec733c6d40656e10ddccdf15ffb99bbaf
DIFF: https://github.com/llvm/llvm-project/commit/cc54f8eec733c6d40656e10ddccdf15ffb99bbaf.diff

LOG: AMDGPU: Add baseline tests for fmed3 shrinking combine

Added: 
    llvm/test/Transforms/InstCombine/AMDGPU/fmed3.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/InstCombine/AMDGPU/fmed3.ll b/llvm/test/Transforms/InstCombine/AMDGPU/fmed3.ll
new file mode 100644
index 0000000000000..2370eaf844dcc
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/fmed3.ll
@@ -0,0 +1,628 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; Unknown/default target
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=instcombine < %s | FileCheck -check-prefixes=NO-FMED3F16,UNKNOWN %s
+
+; Known target, no med3_f16
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -passes=instcombine < %s | FileCheck -check-prefixes=NO-FMED3F16,GFX8 %s
+
+; Has med3_f16
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=instcombine < %s | FileCheck -check-prefixes=GFX9 %s
+
+
+declare float @llvm.fabs.f32(float) #0
+declare half @llvm.fabs.f16(half) #0
+declare float @llvm.amdgcn.fmed3.f32(float, float, float) #0
+
+define float @fmed3_f32_fpext_f16(half %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1:[0-9]+]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1:[0-9]+]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_flags(half %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_flags
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call nsz float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_flags
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call nsz float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call nsz float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_k0(half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_k0
+; NO-FMED3F16-SAME: (half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG1_EXT]], float [[ARG2_EXT]], float 2.000000e+00)
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_k0
+; GFX9-SAME: (half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG1_EXT]], float [[ARG2_EXT]], float 2.000000e+00)
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float 2.0, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_k1(half %arg0, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_k1
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG2_EXT]], float 2.000000e+00)
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_k1
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG2_EXT]], float 2.000000e+00)
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float 2.0, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_k2(half %arg0, half %arg1) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_k2
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float 2.000000e+00)
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_k2
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float 2.000000e+00)
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float 2.0)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_k0_k1(half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_k0_k1
+; NO-FMED3F16-SAME: (half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG2_EXT]], float 0.000000e+00, float 1.600000e+01)
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_k0_k1
+; GFX9-SAME: (half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG2_EXT]], float 0.000000e+00, float 1.600000e+01)
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float 0.0, float 16.0, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_k0_k2(half %arg1) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_k0_k2
+; NO-FMED3F16-SAME: (half [[ARG1:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG1_EXT]], float 0.000000e+00, float 2.000000e+00)
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_k0_k2
+; GFX9-SAME: (half [[ARG1:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG1_EXT]], float 0.000000e+00, float 2.000000e+00)
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg1.ext = fpext half %arg1 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float 0.0, float %arg1.ext, float 2.0)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_fabs(half %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_fabs
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[FABS_ARG0:%.*]] = call half @llvm.fabs.f16(half [[ARG0]])
+; NO-FMED3F16-NEXT:    [[FABS_ARG1:%.*]] = call half @llvm.fabs.f16(half [[ARG1]])
+; NO-FMED3F16-NEXT:    [[FABS_ARG2:%.*]] = call half @llvm.fabs.f16(half [[ARG2]])
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[FABS_ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[FABS_ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[FABS_ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_fabs
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[FABS_ARG0:%.*]] = call half @llvm.fabs.f16(half [[ARG0]])
+; GFX9-NEXT:    [[FABS_ARG1:%.*]] = call half @llvm.fabs.f16(half [[ARG1]])
+; GFX9-NEXT:    [[FABS_ARG2:%.*]] = call half @llvm.fabs.f16(half [[ARG2]])
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[FABS_ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[FABS_ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[FABS_ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %fabs.arg0 = call half @llvm.fabs.f16(half %arg0)
+  %fabs.arg1 = call half @llvm.fabs.f16(half %arg1)
+  %fabs.arg2 = call half @llvm.fabs.f16(half %arg2)
+  %arg0.ext = fpext half %fabs.arg0 to float
+  %arg1.ext = fpext half %fabs.arg1 to float
+  %arg2.ext = fpext half %fabs.arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_fabs_f32_fpext_f16(half %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_fabs_f32_fpext_f16
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[ARG0]])
+; NO-FMED3F16-NEXT:    [[FABS_EXT_ARG0:%.*]] = fpext half [[TMP1]] to float
+; NO-FMED3F16-NEXT:    [[TMP2:%.*]] = call half @llvm.fabs.f16(half [[ARG1]])
+; NO-FMED3F16-NEXT:    [[FABS_EXT_ARG1:%.*]] = fpext half [[TMP2]] to float
+; NO-FMED3F16-NEXT:    [[TMP3:%.*]] = call half @llvm.fabs.f16(half [[ARG2]])
+; NO-FMED3F16-NEXT:    [[FABS_EXT_ARG2:%.*]] = fpext half [[TMP3]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[FABS_EXT_ARG0]], float [[FABS_EXT_ARG1]], float [[FABS_EXT_ARG2]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_fabs_f32_fpext_f16
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[ARG0]])
+; GFX9-NEXT:    [[FABS_EXT_ARG0:%.*]] = fpext half [[TMP1]] to float
+; GFX9-NEXT:    [[TMP2:%.*]] = call half @llvm.fabs.f16(half [[ARG1]])
+; GFX9-NEXT:    [[FABS_EXT_ARG1:%.*]] = fpext half [[TMP2]] to float
+; GFX9-NEXT:    [[TMP3:%.*]] = call half @llvm.fabs.f16(half [[ARG2]])
+; GFX9-NEXT:    [[FABS_EXT_ARG2:%.*]] = fpext half [[TMP3]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[FABS_EXT_ARG0]], float [[FABS_EXT_ARG1]], float [[FABS_EXT_ARG2]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %fabs.ext.arg0 = call float @llvm.fabs.f32(float %arg0.ext)
+  %fabs.ext.arg1 = call float @llvm.fabs.f32(float %arg1.ext)
+  %fabs.ext.arg2 = call float @llvm.fabs.f32(float %arg2.ext)
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %fabs.ext.arg0, float %fabs.ext.arg1, float %fabs.ext.arg2)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_fneg(half %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_fneg
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[FNEG_ARG0:%.*]] = fneg half [[ARG0]]
+; NO-FMED3F16-NEXT:    [[FNEG_ARG1:%.*]] = fneg half [[ARG1]]
+; NO-FMED3F16-NEXT:    [[FNEG_ARG2:%.*]] = fneg half [[ARG2]]
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[FNEG_ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[FNEG_ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[FNEG_ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_fneg
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[FNEG_ARG0:%.*]] = fneg half [[ARG0]]
+; GFX9-NEXT:    [[FNEG_ARG1:%.*]] = fneg half [[ARG1]]
+; GFX9-NEXT:    [[FNEG_ARG2:%.*]] = fneg half [[ARG2]]
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[FNEG_ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[FNEG_ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[FNEG_ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %fneg.arg0 = fneg half %arg0
+  %fneg.arg1 = fneg half %arg1
+  %fneg.arg2 = fneg half %arg2
+  %arg0.ext = fpext half %fneg.arg0 to float
+  %arg1.ext = fpext half %fneg.arg1 to float
+  %arg2.ext = fpext half %fneg.arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_fneg_f32_fpext_f16(half %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_fneg_f32_fpext_f16
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[FNEG_EXT_ARG0:%.*]] = fneg float [[ARG0_EXT]]
+; NO-FMED3F16-NEXT:    [[FNEG_EXT_ARG1:%.*]] = fneg float [[ARG1_EXT]]
+; NO-FMED3F16-NEXT:    [[FNEG_EXT_ARG2:%.*]] = fneg float [[ARG2_EXT]]
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[FNEG_EXT_ARG0]], float [[FNEG_EXT_ARG1]], float [[FNEG_EXT_ARG2]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_fneg_f32_fpext_f16
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[FNEG_EXT_ARG0:%.*]] = fneg float [[ARG0_EXT]]
+; GFX9-NEXT:    [[FNEG_EXT_ARG1:%.*]] = fneg float [[ARG1_EXT]]
+; GFX9-NEXT:    [[FNEG_EXT_ARG2:%.*]] = fneg float [[ARG2_EXT]]
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[FNEG_EXT_ARG0]], float [[FNEG_EXT_ARG1]], float [[FNEG_EXT_ARG2]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %fneg.ext.arg0 = fneg float %arg0.ext
+  %fneg.ext.arg1 = fneg float %arg1.ext
+  %fneg.ext.arg2 = fneg float %arg2.ext
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %fneg.ext.arg0, float %fneg.ext.arg1, float %fneg.ext.arg2)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_fneg_fabs(half %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_fneg_fabs
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[FABS_ARG0:%.*]] = call half @llvm.fabs.f16(half [[ARG0]])
+; NO-FMED3F16-NEXT:    [[FABS_ARG1:%.*]] = call half @llvm.fabs.f16(half [[ARG1]])
+; NO-FMED3F16-NEXT:    [[FABS_ARG2:%.*]] = call half @llvm.fabs.f16(half [[ARG2]])
+; NO-FMED3F16-NEXT:    [[FNEG_FABS_ARG0:%.*]] = fneg half [[FABS_ARG0]]
+; NO-FMED3F16-NEXT:    [[FNEG_FABS_ARG1:%.*]] = fneg half [[FABS_ARG1]]
+; NO-FMED3F16-NEXT:    [[FNEG_FABS_ARG2:%.*]] = fneg half [[FABS_ARG2]]
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[FNEG_FABS_ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[FNEG_FABS_ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[FNEG_FABS_ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_fneg_fabs
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[FABS_ARG0:%.*]] = call half @llvm.fabs.f16(half [[ARG0]])
+; GFX9-NEXT:    [[FABS_ARG1:%.*]] = call half @llvm.fabs.f16(half [[ARG1]])
+; GFX9-NEXT:    [[FABS_ARG2:%.*]] = call half @llvm.fabs.f16(half [[ARG2]])
+; GFX9-NEXT:    [[FNEG_FABS_ARG0:%.*]] = fneg half [[FABS_ARG0]]
+; GFX9-NEXT:    [[FNEG_FABS_ARG1:%.*]] = fneg half [[FABS_ARG1]]
+; GFX9-NEXT:    [[FNEG_FABS_ARG2:%.*]] = fneg half [[FABS_ARG2]]
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[FNEG_FABS_ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[FNEG_FABS_ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[FNEG_FABS_ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %fabs.arg0 = call half @llvm.fabs.f16(half %arg0)
+  %fabs.arg1 = call half @llvm.fabs.f16(half %arg1)
+  %fabs.arg2 = call half @llvm.fabs.f16(half %arg2)
+  %fneg.fabs.arg0 = fneg half %fabs.arg0
+  %fneg.fabs.arg1 = fneg half %fabs.arg1
+  %fneg.fabs.arg2 = fneg half %fabs.arg2
+  %arg0.ext = fpext half %fneg.fabs.arg0 to float
+  %arg1.ext = fpext half %fneg.fabs.arg1 to float
+  %arg2.ext = fpext half %fneg.fabs.arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_fneg_fabs_f32_fpext_f16(half %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_fneg_fabs_f32_fpext_f16
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[ARG0]])
+; NO-FMED3F16-NEXT:    [[FABS_EXT_ARG0:%.*]] = fpext half [[TMP1]] to float
+; NO-FMED3F16-NEXT:    [[TMP2:%.*]] = call half @llvm.fabs.f16(half [[ARG1]])
+; NO-FMED3F16-NEXT:    [[FABS_EXT_ARG1:%.*]] = fpext half [[TMP2]] to float
+; NO-FMED3F16-NEXT:    [[TMP3:%.*]] = call half @llvm.fabs.f16(half [[ARG2]])
+; NO-FMED3F16-NEXT:    [[FABS_EXT_ARG2:%.*]] = fpext half [[TMP3]] to float
+; NO-FMED3F16-NEXT:    [[FNEG_FABS_EXT_ARG0:%.*]] = fneg float [[FABS_EXT_ARG0]]
+; NO-FMED3F16-NEXT:    [[FNEG_FABS_EXT_ARG1:%.*]] = fneg float [[FABS_EXT_ARG1]]
+; NO-FMED3F16-NEXT:    [[FNEG_FABS_EXT_ARG2:%.*]] = fneg float [[FABS_EXT_ARG2]]
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[FNEG_FABS_EXT_ARG0]], float [[FNEG_FABS_EXT_ARG1]], float [[FNEG_FABS_EXT_ARG2]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_fneg_fabs_f32_fpext_f16
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[ARG0]])
+; GFX9-NEXT:    [[FABS_EXT_ARG0:%.*]] = fpext half [[TMP1]] to float
+; GFX9-NEXT:    [[TMP2:%.*]] = call half @llvm.fabs.f16(half [[ARG1]])
+; GFX9-NEXT:    [[FABS_EXT_ARG1:%.*]] = fpext half [[TMP2]] to float
+; GFX9-NEXT:    [[TMP3:%.*]] = call half @llvm.fabs.f16(half [[ARG2]])
+; GFX9-NEXT:    [[FABS_EXT_ARG2:%.*]] = fpext half [[TMP3]] to float
+; GFX9-NEXT:    [[FNEG_FABS_EXT_ARG0:%.*]] = fneg float [[FABS_EXT_ARG0]]
+; GFX9-NEXT:    [[FNEG_FABS_EXT_ARG1:%.*]] = fneg float [[FABS_EXT_ARG1]]
+; GFX9-NEXT:    [[FNEG_FABS_EXT_ARG2:%.*]] = fneg float [[FABS_EXT_ARG2]]
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[FNEG_FABS_EXT_ARG0]], float [[FNEG_FABS_EXT_ARG1]], float [[FNEG_FABS_EXT_ARG2]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %fabs.ext.arg0 = call float @llvm.fabs.f32(float %arg0.ext)
+  %fabs.ext.arg1 = call float @llvm.fabs.f32(float %arg1.ext)
+  %fabs.ext.arg2 = call float @llvm.fabs.f32(float %arg2.ext)
+  %fneg.fabs.ext.arg0 = fneg float %fabs.ext.arg0
+  %fneg.fabs.ext.arg1 = fneg float %fabs.ext.arg1
+  %fneg.fabs.ext.arg2 = fneg float %fabs.ext.arg2
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %fneg.fabs.ext.arg0, float %fneg.fabs.ext.arg1, float %fneg.fabs.ext.arg2)
+  ret float %med3
+}
+
+; --------------------------------------------------------------------------------
+; Negative tests
+; --------------------------------------------------------------------------------
+
+define float @fmed3_f32_fpext_f16_multi_use_0(half %arg0, half %arg1, half %arg2, ptr addrspace(1) %ptr) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_multi_use_0
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]], ptr addrspace(1) [[PTR:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    store float [[ARG0_EXT]], ptr addrspace(1) [[PTR]], align 4
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_multi_use_0
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]], ptr addrspace(1) [[PTR:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    store float [[ARG0_EXT]], ptr addrspace(1) [[PTR]], align 4
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  store float %arg0.ext, ptr addrspace(1) %ptr
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_multi_use_1(half %arg0, half %arg1, half %arg2, ptr addrspace(1) %ptr) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_multi_use_1
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]], ptr addrspace(1) [[PTR:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    store float [[ARG1_EXT]], ptr addrspace(1) [[PTR]], align 4
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_multi_use_1
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]], ptr addrspace(1) [[PTR:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    store float [[ARG1_EXT]], ptr addrspace(1) [[PTR]], align 4
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  store float %arg1.ext, ptr addrspace(1) %ptr
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_multi_use_2(half %arg0, half %arg1, half %arg2, ptr addrspace(1) %ptr) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_multi_use_2
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]], ptr addrspace(1) [[PTR:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    store float [[ARG2_EXT]], ptr addrspace(1) [[PTR]], align 4
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_multi_use_2
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]], ptr addrspace(1) [[PTR:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    store float [[ARG2_EXT]], ptr addrspace(1) [[PTR]], align 4
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  store float %arg2.ext, ptr addrspace(1) %ptr
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_bf16(bfloat %arg0, bfloat %arg1, bfloat %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_bf16
+; NO-FMED3F16-SAME: (bfloat [[ARG0:%.*]], bfloat [[ARG1:%.*]], bfloat [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext bfloat [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext bfloat [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext bfloat [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_bf16
+; GFX9-SAME: (bfloat [[ARG0:%.*]], bfloat [[ARG1:%.*]], bfloat [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext bfloat [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext bfloat [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext bfloat [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext bfloat %arg0 to float
+  %arg1.ext = fpext bfloat %arg1 to float
+  %arg2.ext = fpext bfloat %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_bf16_0(bfloat %arg0, half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_bf16_0
+; NO-FMED3F16-SAME: (bfloat [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext bfloat [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_bf16_0
+; GFX9-SAME: (bfloat [[ARG0:%.*]], half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext bfloat [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext bfloat %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_bf16_1(half %arg0, bfloat %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_bf16_1
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], bfloat [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext bfloat [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_bf16_1
+; GFX9-SAME: (half [[ARG0:%.*]], bfloat [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext bfloat [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext bfloat %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_bf16_2(half %arg0, half %arg1, bfloat %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_bf16_2
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], bfloat [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext bfloat [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_bf16_2
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]], bfloat [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext bfloat [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float [[ARG2_EXT]])
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext bfloat %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_unrepresentable_k0(half %arg1, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_unrepresentable_k0
+; NO-FMED3F16-SAME: (half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG1_EXT]], float [[ARG2_EXT]], float 0x41F0000000000000)
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_unrepresentable_k0
+; GFX9-SAME: (half [[ARG1:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG1_EXT]], float [[ARG2_EXT]], float 0x41F0000000000000)
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg1.ext = fpext half %arg1 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float 0x41f0000000000000, float %arg1.ext, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_unrepresentable_k1(half %arg0, half %arg2) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_unrepresentable_k1
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG2_EXT]], float 0x41F0000000000000)
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_unrepresentable_k1
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG2:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG2_EXT:%.*]] = fpext half [[ARG2]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG2_EXT]], float 0x41F0000000000000)
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg2.ext = fpext half %arg2 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float 0x41f0000000000000, float %arg2.ext)
+  ret float %med3
+}
+
+define float @fmed3_f32_fpext_f16_unrepresentable_k2(half %arg0, half %arg1) #1 {
+; NO-FMED3F16-LABEL: define float @fmed3_f32_fpext_f16_unrepresentable_k2
+; NO-FMED3F16-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]]) #[[ATTR1]] {
+; NO-FMED3F16-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; NO-FMED3F16-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; NO-FMED3F16-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float 0x41F0000000000000)
+; NO-FMED3F16-NEXT:    ret float [[MED3]]
+;
+; GFX9-LABEL: define float @fmed3_f32_fpext_f16_unrepresentable_k2
+; GFX9-SAME: (half [[ARG0:%.*]], half [[ARG1:%.*]]) #[[ATTR1]] {
+; GFX9-NEXT:    [[ARG0_EXT:%.*]] = fpext half [[ARG0]] to float
+; GFX9-NEXT:    [[ARG1_EXT:%.*]] = fpext half [[ARG1]] to float
+; GFX9-NEXT:    [[MED3:%.*]] = call float @llvm.amdgcn.fmed3.f32(float [[ARG0_EXT]], float [[ARG1_EXT]], float 0x41F0000000000000)
+; GFX9-NEXT:    ret float [[MED3]]
+;
+  %arg0.ext = fpext half %arg0 to float
+  %arg1.ext = fpext half %arg1 to float
+  %med3 = call float @llvm.amdgcn.fmed3.f32(float %arg0.ext, float %arg1.ext, float 0x41f0000000000000)
+  ret float %med3
+}
+
+
+attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn }
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; GFX8: {{.*}}
+; UNKNOWN: {{.*}}


        


More information about the llvm-commits mailing list