-; RUN: opt -S -mtriple=amdgcn-- -amdgpu-codegenprepare %s | FileCheck %s
-; RUN: opt -S -amdgpu-codegenprepare %s | FileCheck -check-prefix=NOOP %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -S -mtriple=amdgcn-- -mcpu=hawaii -passes=amdgpu-codegenprepare -denormal-fp-math-f32=ieee %s | FileCheck -check-prefixes=CHECK,IEEE,IEEE-GOODFREXP %s
+; RUN: opt -S -mtriple=amdgcn-- -mcpu=tahiti -passes=amdgpu-codegenprepare -denormal-fp-math-f32=ieee %s | FileCheck -check-prefixes=CHECK,IEEE,IEEE-BADFREXP %s
+; RUN: opt -S -mtriple=amdgcn-- -mcpu=hawaii -passes=amdgpu-codegenprepare -denormal-fp-math-f32=dynamic %s | FileCheck -check-prefixes=CHECK,IEEE %s
+; RUN: opt -S -mtriple=amdgcn-- -mcpu=hawaii -passes=amdgpu-codegenprepare -denormal-fp-math-f32=preserve-sign %s | FileCheck -check-prefixes=CHECK,DAZ %s
+
; Make sure this doesn't crash with no triple
+; TODO: Delete when old PM deleted
+; RUN: opt -amdgpu-codegenprepare -disable-output %s
+
-; NOOP-LABEL: @noop_fdiv_fpmath(
-; NOOP: %md.25ulp = fdiv float %a, %b, !fpmath !0
-define amdgpu_kernel void @noop_fdiv_fpmath(ptr addrspace(1) %out, float %a, float %b) {
+define amdgpu_kernel void @noop_fdiv_fpmath(ptr addrspace(1) %out, float %a, float %b) #0 {
+; CHECK-LABEL: define amdgpu_kernel void @noop_fdiv_fpmath
+; CHECK-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[MD_25ULP:%.*]] = fdiv float [[A]], [[B]], !fpmath [[META0:![0-9]+]]
+; CHECK-NEXT: store volatile float [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT: ret void
+;
%md.25ulp = fdiv float %a, %b, !fpmath !0
- store volatile float %md.25ulp, ptr addrspace(1) %out
+ store volatile float %md.25ulp, ptr addrspace(1) %out, align 4
ret void
}
-; CHECK-LABEL: @fdiv_fpmath(
-; CHECK: %no.md = fdiv float %a, %b{{$}}
-; CHECK: %md.half.ulp = fdiv float %a, %b
-; CHECK: %md.1ulp = fdiv float %a, %b
-; CHECK: %md.25ulp = call float @llvm.amdgcn.fdiv.fast(float %a, float %b)
-; CHECK: %md.3ulp = call float @llvm.amdgcn.fdiv.fast(float %a, float %b)
-; CHECK: %[[FAST_RCP:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %b)
-; CHECK: %fast.md.25ulp = fmul fast float %a, %[[FAST_RCP]]
-; CHECK: %[[AFN_RCP:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %b)
-; CHECK: afn.md.25ulp = fmul afn float %a, %[[AFN_RCP]]
-define amdgpu_kernel void @fdiv_fpmath(ptr addrspace(1) %out, float %a, float %b) #1 {
+define amdgpu_kernel void @fdiv_fpmath_f32(ptr addrspace(1) %out, float %a, float %b) {
+; IEEE-LABEL: define amdgpu_kernel void @fdiv_fpmath_f32
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR1:[0-9]+]] {
+; IEEE-NEXT: [[NO_MD:%.*]] = fdiv float [[A]], [[B]]
+; IEEE-NEXT: store volatile float [[NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_HALF_ULP:%.*]] = fdiv float [[A]], [[B]], !fpmath [[META1:![0-9]+]]
+; IEEE-NEXT: store volatile float [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP:%.*]] = fdiv float [[A]], [[B]], !fpmath [[META2:![0-9]+]]
+; IEEE-NEXT: store volatile float [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_25ULP:%.*]] = fdiv float [[A]], [[B]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_3ULP:%.*]] = fdiv float [[A]], [[B]], !fpmath [[META3:![0-9]+]]
+; IEEE-NEXT: store volatile float [[MD_3ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[TMP1:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[B]])
+; IEEE-NEXT: [[FAST_MD_25ULP:%.*]] = fmul fast float [[A]], [[TMP1]]
+; IEEE-NEXT: store volatile float [[FAST_MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[TMP2:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[B]])
+; IEEE-NEXT: [[AFN_MD_25ULP:%.*]] = fmul afn float [[A]], [[TMP2]]
+; IEEE-NEXT: store volatile float [[AFN_MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @fdiv_fpmath_f32
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR1:[0-9]+]] {
+; DAZ-NEXT: [[NO_MD:%.*]] = fdiv float [[A]], [[B]]
+; DAZ-NEXT: store volatile float [[NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_HALF_ULP:%.*]] = fdiv float [[A]], [[B]], !fpmath [[META1:![0-9]+]]
+; DAZ-NEXT: store volatile float [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP:%.*]] = fdiv float [[A]], [[B]], !fpmath [[META2:![0-9]+]]
+; DAZ-NEXT: store volatile float [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_25ULP:%.*]] = call float @llvm.amdgcn.fdiv.fast(float [[A]], float [[B]])
+; DAZ-NEXT: store volatile float [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_3ULP:%.*]] = call float @llvm.amdgcn.fdiv.fast(float [[A]], float [[B]])
+; DAZ-NEXT: store volatile float [[MD_3ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP1:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[B]])
+; DAZ-NEXT: [[FAST_MD_25ULP:%.*]] = fmul fast float [[A]], [[TMP1]]
+; DAZ-NEXT: store volatile float [[FAST_MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP2:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[B]])
+; DAZ-NEXT: [[AFN_MD_25ULP:%.*]] = fmul afn float [[A]], [[TMP2]]
+; DAZ-NEXT: store volatile float [[AFN_MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
%no.md = fdiv float %a, %b
- store volatile float %no.md, ptr addrspace(1) %out
-
+ store volatile float %no.md, ptr addrspace(1) %out, align 4
%md.half.ulp = fdiv float %a, %b, !fpmath !1
- store volatile float %md.half.ulp, ptr addrspace(1) %out
-
+ store volatile float %md.half.ulp, ptr addrspace(1) %out, align 4
%md.1ulp = fdiv float %a, %b, !fpmath !2
- store volatile float %md.1ulp, ptr addrspace(1) %out
-
+ store volatile float %md.1ulp, ptr addrspace(1) %out, align 4
%md.25ulp = fdiv float %a, %b, !fpmath !0
- store volatile float %md.25ulp, ptr addrspace(1) %out
-
+ store volatile float %md.25ulp, ptr addrspace(1) %out, align 4
%md.3ulp = fdiv float %a, %b, !fpmath !3
- store volatile float %md.3ulp, ptr addrspace(1) %out
-
+ store volatile float %md.3ulp, ptr addrspace(1) %out, align 4
%fast.md.25ulp = fdiv fast float %a, %b, !fpmath !0
- store volatile float %fast.md.25ulp, ptr addrspace(1) %out
-
+ store volatile float %fast.md.25ulp, ptr addrspace(1) %out, align 4
%afn.md.25ulp = fdiv afn float %a, %b, !fpmath !0
- store volatile float %afn.md.25ulp, ptr addrspace(1) %out
-
- ret void
-}
-
-; CHECK-LABEL: @rcp_fdiv_fpmath(
-; CHECK: %no.md = fdiv float 1.000000e+00, %x{{$}}
-; CHECK: %md.25ulp = call float @llvm.amdgcn.rcp.f32(float %x)
-; CHECK: %md.half.ulp = fdiv float 1.000000e+00, %x
-; CHECK: %afn.no.md = call afn float @llvm.amdgcn.rcp.f32(float %x)
-; CHECK: %afn.25ulp = call afn float @llvm.amdgcn.rcp.f32(float %x)
-; CHECK: %fast.no.md = call fast float @llvm.amdgcn.rcp.f32(float %x)
-; CHECK: %fast.25ulp = call fast float @llvm.amdgcn.rcp.f32(float %x)
-define amdgpu_kernel void @rcp_fdiv_fpmath(ptr addrspace(1) %out, float %x) #1 {
- %no.md = fdiv float 1.0, %x
- store volatile float %no.md, ptr addrspace(1) %out
-
- %md.25ulp = fdiv float 1.0, %x, !fpmath !0
- store volatile float %md.25ulp, ptr addrspace(1) %out
-
- %md.half.ulp = fdiv float 1.0, %x, !fpmath !1
- store volatile float %md.half.ulp, ptr addrspace(1) %out
-
- %afn.no.md = fdiv afn float 1.0, %x
- store volatile float %afn.no.md, ptr addrspace(1) %out
-
- %afn.25ulp = fdiv afn float 1.0, %x, !fpmath !0
- store volatile float %afn.25ulp, ptr addrspace(1) %out
-
- %fast.no.md = fdiv fast float 1.0, %x
- store volatile float %fast.no.md, ptr addrspace(1) %out
-
- %fast.25ulp = fdiv fast float 1.0, %x, !fpmath !0
- store volatile float %fast.25ulp, ptr addrspace(1) %out
-
- ret void
-}
-
-; CHECK-LABEL: @fdiv_fpmath_vector(
-; CHECK: %[[NO_A0:[0-9]+]] = extractelement <2 x float> %a, i64 0
-; CHECK: %[[NO_B0:[0-9]+]] = extractelement <2 x float> %b, i64 0
-; CHECK: %[[NO_FDIV0:[0-9]+]] = fdiv float %[[NO_A0]], %[[NO_B0]]
-; CHECK: %[[NO_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[NO_FDIV0]], i64 0
-; CHECK: %[[NO_A1:[0-9]+]] = extractelement <2 x float> %a, i64 1
-; CHECK: %[[NO_B1:[0-9]+]] = extractelement <2 x float> %b, i64 1
-; CHECK: %[[NO_FDIV1:[0-9]+]] = fdiv float %[[NO_A1]], %[[NO_B1]]
-; CHECK: %no.md = insertelement <2 x float> %[[NO_INS0]], float %[[NO_FDIV1]], i64 1
-; CHECK: store volatile <2 x float> %no.md, ptr addrspace(1) %out
-
-; CHECK: %[[HALF_A0:[0-9]+]] = extractelement <2 x float> %a, i64 0
-; CHECK: %[[HALF_B0:[0-9]+]] = extractelement <2 x float> %b, i64 0
-; CHECK: %[[HALF_FDIV0:[0-9]+]] = fdiv float %[[HALF_A0]], %[[HALF_B0]]
-; CHECK: %[[HALF_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[HALF_FDIV0]], i64 0
-; CHECK: %[[HALF_A1:[0-9]+]] = extractelement <2 x float> %a, i64 1
-; CHECK: %[[HALF_B1:[0-9]+]] = extractelement <2 x float> %b, i64 1
-; CHECK: %[[HALF_FDIV1:[0-9]+]] = fdiv float %[[HALF_A1]], %[[HALF_B1]]
-; CHECK: %md.half.ulp = insertelement <2 x float> %[[HALF_INS0]], float %[[HALF_FDIV1]], i64 1
-; CHECK: store volatile <2 x float> %md.half.ulp, ptr addrspace(1) %out
-
-; CHECK: %[[ONE_A0:[0-9]+]] = extractelement <2 x float> %a, i64 0
-; CHECK: %[[ONE_B0:[0-9]+]] = extractelement <2 x float> %b, i64 0
-; CHECK: %[[ONE_FDIV0:[0-9]+]] = fdiv float %[[ONE_A0]], %[[ONE_B0]]
-; CHECK: %[[ONE_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[ONE_FDIV0]], i64 0
-; CHECK: %[[ONE_A1:[0-9]+]] = extractelement <2 x float> %a, i64 1
-; CHECK: %[[ONE_B1:[0-9]+]] = extractelement <2 x float> %b, i64 1
-; CHECK: %[[ONE_FDIV1:[0-9]+]] = fdiv float %[[ONE_A1]], %[[ONE_B1]]
-; CHECK: %md.1ulp = insertelement <2 x float> %[[ONE_INS0]], float %[[ONE_FDIV1]], i64 1
-; CHECK: store volatile <2 x float> %md.1ulp, ptr addrspace(1) %out
-
-; CHECK: %[[A0:[0-9]+]] = extractelement <2 x float> %a, i64 0
-; CHECK: %[[B0:[0-9]+]] = extractelement <2 x float> %b, i64 0
-; CHECK: %[[FDIV0:[0-9]+]] = call float @llvm.amdgcn.fdiv.fast(float %[[A0]], float %[[B0]])
-; CHECK: %[[INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[FDIV0]], i64 0
-; CHECK: %[[A1:[0-9]+]] = extractelement <2 x float> %a, i64 1
-; CHECK: %[[B1:[0-9]+]] = extractelement <2 x float> %b, i64 1
-; CHECK: %[[FDIV1:[0-9]+]] = call float @llvm.amdgcn.fdiv.fast(float %[[A1]], float %[[B1]])
-; CHECK: %md.25ulp = insertelement <2 x float> %[[INS0]], float %[[FDIV1]], i64 1
-define amdgpu_kernel void @fdiv_fpmath_vector(ptr addrspace(1) %out, <2 x float> %a, <2 x float> %b) #1 {
- %no.md = fdiv <2 x float> %a, %b
- store volatile <2 x float> %no.md, ptr addrspace(1) %out
+ store volatile float %afn.md.25ulp, ptr addrspace(1) %out, align 4
+ ret void
+}
- %md.half.ulp = fdiv <2 x float> %a, %b, !fpmath !1
- store volatile <2 x float> %md.half.ulp, ptr addrspace(1) %out
+define amdgpu_kernel void @fdiv_fpmath_f32_flags(ptr addrspace(1) %out, float %a, float %b) {
+; IEEE-LABEL: define amdgpu_kernel void @fdiv_fpmath_f32_flags
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[MD_1ULP_NINF_NNAN:%.*]] = fdiv nnan ninf float [[A]], [[B]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_25ULP_NINF_NNAN:%.*]] = fdiv nnan ninf float [[A]], [[B]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[MD_25ULP_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NINF:%.*]] = fdiv ninf float [[A]], [[B]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NINF]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_25ULP_NINF:%.*]] = fdiv ninf float [[A]], [[B]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[MD_25ULP_NINF]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NNAN:%.*]] = fdiv nnan float [[A]], [[B]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_25ULP_NNAN:%.*]] = fdiv nnan float [[A]], [[B]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[MD_25ULP_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @fdiv_fpmath_f32_flags
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[MD_1ULP_NINF_NNAN:%.*]] = fdiv nnan ninf float [[A]], [[B]], !fpmath [[META2]]
+; DAZ-NEXT: store volatile float [[MD_1ULP_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_25ULP_NINF_NNAN:%.*]] = call nnan ninf float @llvm.amdgcn.fdiv.fast(float [[A]], float [[B]])
+; DAZ-NEXT: store volatile float [[MD_25ULP_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NINF:%.*]] = fdiv ninf float [[A]], [[B]], !fpmath [[META2]]
+; DAZ-NEXT: store volatile float [[MD_1ULP_NINF]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_25ULP_NINF:%.*]] = call ninf float @llvm.amdgcn.fdiv.fast(float [[A]], float [[B]])
+; DAZ-NEXT: store volatile float [[MD_25ULP_NINF]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NNAN:%.*]] = fdiv nnan float [[A]], [[B]], !fpmath [[META2]]
+; DAZ-NEXT: store volatile float [[MD_1ULP_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_25ULP_NNAN:%.*]] = call nnan float @llvm.amdgcn.fdiv.fast(float [[A]], float [[B]])
+; DAZ-NEXT: store volatile float [[MD_25ULP_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %md.1ulp.ninf.nnan = fdiv ninf nnan float %a, %b, !fpmath !2
+ store volatile float %md.1ulp.ninf.nnan, ptr addrspace(1) %out, align 4
+
+ %md.25ulp.ninf.nnan = fdiv ninf nnan float %a, %b, !fpmath !0
+ store volatile float %md.25ulp.ninf.nnan, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.ninf = fdiv ninf float %a, %b, !fpmath !2
+ store volatile float %md.1ulp.ninf, ptr addrspace(1) %out, align 4
+
+ %md.25ulp.ninf = fdiv ninf float %a, %b, !fpmath !0
+ store volatile float %md.25ulp.ninf, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.nnan = fdiv nnan float %a, %b, !fpmath !2
+ store volatile float %md.1ulp.nnan, ptr addrspace(1) %out, align 4
+
+ %md.25ulp.nnan = fdiv nnan float %a, %b, !fpmath !0
+ store volatile float %md.25ulp.nnan, ptr addrspace(1) %out, align 4
- %md.1ulp = fdiv <2 x float> %a, %b, !fpmath !2
- store volatile <2 x float> %md.1ulp, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @rcp_fdiv_f32_fpmath(ptr addrspace(1) %out, float %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_fpmath
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[NO_MD:%.*]] = fdiv float 1.000000e+00, [[X]]
+; IEEE-NEXT: store volatile float [[NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP:%.*]] = fdiv float 1.000000e+00, [[X]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_25ULP:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[X]])
+; IEEE-NEXT: store volatile float [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_HALF_ULP:%.*]] = fdiv float 1.000000e+00, [[X]], !fpmath [[META1]]
+; IEEE-NEXT: store volatile float [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[AFN_NO_MD:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[X]])
+; IEEE-NEXT: store volatile float [[AFN_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[AFN_25ULP:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[X]])
+; IEEE-NEXT: store volatile float [[AFN_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[FAST_NO_MD:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[X]])
+; IEEE-NEXT: store volatile float [[FAST_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[FAST_25ULP:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[X]])
+; IEEE-NEXT: store volatile float [[FAST_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[NEG_MD_1ULP:%.*]] = fdiv float -1.000000e+00, [[X]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[NEG_MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[NEG_MD_25ULP:%.*]] = call float @llvm.amdgcn.fdiv.fast(float -1.000000e+00, float [[X]])
+; IEEE-NEXT: store volatile float [[NEG_MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[TMP1:%.*]] = fneg afn float [[X]]
+; IEEE-NEXT: [[NEG_AFN_NO_MD:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP1]])
+; IEEE-NEXT: store volatile float [[NEG_AFN_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[TMP2:%.*]] = fneg afn float [[X]]
+; IEEE-NEXT: [[NEG_AFN_25ULP:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP2]])
+; IEEE-NEXT: store volatile float [[NEG_AFN_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[TMP3:%.*]] = fneg fast float [[X]]
+; IEEE-NEXT: [[NEG_FAST_NO_MD:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP3]])
+; IEEE-NEXT: store volatile float [[NEG_FAST_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_fpmath
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[NO_MD:%.*]] = fdiv float 1.000000e+00, [[X]]
+; DAZ-NEXT: store volatile float [[NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_25ULP:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_HALF_ULP:%.*]] = fdiv float 1.000000e+00, [[X]], !fpmath [[META1]]
+; DAZ-NEXT: store volatile float [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[AFN_NO_MD:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[AFN_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[AFN_25ULP:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[AFN_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[FAST_NO_MD:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[FAST_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[FAST_25ULP:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[FAST_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP1:%.*]] = fneg float [[X]]
+; DAZ-NEXT: [[NEG_MD_1ULP:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[TMP1]])
+; DAZ-NEXT: store volatile float [[NEG_MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP2:%.*]] = fneg float [[X]]
+; DAZ-NEXT: [[NEG_MD_25ULP:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[TMP2]])
+; DAZ-NEXT: store volatile float [[NEG_MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP3:%.*]] = fneg afn float [[X]]
+; DAZ-NEXT: [[NEG_AFN_NO_MD:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP3]])
+; DAZ-NEXT: store volatile float [[NEG_AFN_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP4:%.*]] = fneg afn float [[X]]
+; DAZ-NEXT: [[NEG_AFN_25ULP:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP4]])
+; DAZ-NEXT: store volatile float [[NEG_AFN_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP5:%.*]] = fneg fast float [[X]]
+; DAZ-NEXT: [[NEG_FAST_NO_MD:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP5]])
+; DAZ-NEXT: store volatile float [[NEG_FAST_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %no.md = fdiv float 1.000000e+00, %x
+ store volatile float %no.md, ptr addrspace(1) %out, align 4
+ %md.1ulp = fdiv float 1.000000e+00, %x, !fpmath !2
+ store volatile float %md.1ulp, ptr addrspace(1) %out, align 4
+ %md.25ulp = fdiv float 1.000000e+00, %x, !fpmath !0
+ store volatile float %md.25ulp, ptr addrspace(1) %out, align 4
+ %md.half.ulp = fdiv float 1.000000e+00, %x, !fpmath !1
+ store volatile float %md.half.ulp, ptr addrspace(1) %out, align 4
+ %afn.no.md = fdiv afn float 1.000000e+00, %x
+ store volatile float %afn.no.md, ptr addrspace(1) %out, align 4
+ %afn.25ulp = fdiv afn float 1.000000e+00, %x, !fpmath !0
+ store volatile float %afn.25ulp, ptr addrspace(1) %out, align 4
+ %fast.no.md = fdiv fast float 1.000000e+00, %x
+ store volatile float %fast.no.md, ptr addrspace(1) %out, align 4
+ %fast.25ulp = fdiv fast float 1.000000e+00, %x, !fpmath !0
+ store volatile float %fast.25ulp, ptr addrspace(1) %out, align 4
+ %neg.md.1ulp = fdiv float -1.000000e+00, %x, !fpmath !2
+ store volatile float %neg.md.1ulp, ptr addrspace(1) %out, align 4
+ %neg.md.25ulp = fdiv float -1.000000e+00, %x, !fpmath !0
+ store volatile float %neg.md.25ulp, ptr addrspace(1) %out, align 4
+ %neg.afn.no.md = fdiv afn float -1.000000e+00, %x
+ store volatile float %neg.afn.no.md, ptr addrspace(1) %out, align 4
+ %neg.afn.25ulp = fdiv afn float -1.000000e+00, %x, !fpmath !0
+ store volatile float %neg.afn.25ulp, ptr addrspace(1) %out, align 4
+ %neg.fast.no.md = fdiv fast float -1.000000e+00, %x
+ store volatile float %neg.fast.no.md, ptr addrspace(1) %out, align 4
+ ret void
+}
+define amdgpu_kernel void @rcp_fdiv_f32_fpmath_flags(ptr addrspace(1) %out, float %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_fpmath_flags
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[MD_1ULP_NINF_NNAN:%.*]] = fdiv nnan ninf float 1.000000e+00, [[X]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NINF:%.*]] = fdiv ninf float 1.000000e+00, [[X]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NINF]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NNAN:%.*]] = fdiv nnan float 1.000000e+00, [[X]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NSZ:%.*]] = fdiv nsz float 1.000000e+00, [[X]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NSZ]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_fpmath_flags
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[MD_1ULP_NINF_NNAN:%.*]] = call nnan ninf float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NINF:%.*]] = call ninf float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NINF]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NNAN:%.*]] = call nnan float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NSZ:%.*]] = call nsz float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NSZ]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %md.1ulp.ninf.nnan = fdiv ninf nnan float 1.000000e+00, %x, !fpmath !2
+ store volatile float %md.1ulp.ninf.nnan, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.ninf = fdiv ninf float 1.000000e+00, %x, !fpmath !2
+ store volatile float %md.1ulp.ninf, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.nnan = fdiv nnan float 1.000000e+00, %x, !fpmath !2
+ store volatile float %md.1ulp.nnan, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.nsz = fdiv nsz float 1.000000e+00, %x, !fpmath !2
+ store volatile float %md.1ulp.nsz, ptr addrspace(1) %out, align 4
+
+ ret void
+}
+
+define amdgpu_kernel void @rcp_fdiv_f32_knownfinite(ptr addrspace(1) %out,
+; IEEE-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_knownfinite
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(nan) [[NO_NAN:%.*]], float nofpclass(nan) [[NO_INF:%.*]], float nofpclass(nan inf) [[NO_INF_NAN:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[MD_1ULP_NO_NAN:%.*]] = fdiv float 1.000000e+00, [[NO_NAN]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_NAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NO_INF:%.*]] = fdiv float 1.000000e+00, [[NO_INF]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_INF]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NO_INF_NAN:%.*]] = fdiv float 1.000000e+00, [[NO_INF_NAN]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_INF_NAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_knownfinite
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(nan) [[NO_NAN:%.*]], float nofpclass(nan) [[NO_INF:%.*]], float nofpclass(nan inf) [[NO_INF_NAN:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[MD_1ULP_NO_NAN:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[NO_NAN]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_NAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NO_INF:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[NO_INF]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_INF]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NO_INF_NAN:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[NO_INF_NAN]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_INF_NAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ float nofpclass(nan) %no.nan,
+ float nofpclass(nan) %no.inf,
+ float nofpclass(inf nan) %no.inf.nan) {
+ %md.1ulp.no.nan = fdiv float 1.000000e+00, %no.nan, !fpmath !2
+ store volatile float %md.1ulp.no.nan, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.no.inf = fdiv float 1.000000e+00, %no.inf, !fpmath !2
+ store volatile float %md.1ulp.no.inf, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.no.inf.nan = fdiv float 1.000000e+00, %no.inf.nan, !fpmath !2
+ store volatile float %md.1ulp.no.inf.nan, ptr addrspace(1) %out, align 4
+
+ ret void
+}
+
+define amdgpu_kernel void @rcp_fdiv_f32_nozero(ptr addrspace(1) %out,
+; IEEE-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_nozero
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(zero) [[NO_ZERO:%.*]], float nofpclass(zero sub) [[NO_ZERO_SUB:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[MD_1ULP_NO_ZERO:%.*]] = fdiv float 1.000000e+00, [[NO_ZERO]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_ZERO]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NO_ZERO_SUB:%.*]] = fdiv float 1.000000e+00, [[NO_ZERO_SUB]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_ZERO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_nozero
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(zero) [[NO_ZERO:%.*]], float nofpclass(zero sub) [[NO_ZERO_SUB:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[MD_1ULP_NO_ZERO:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[NO_ZERO]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_ZERO]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NO_ZERO_SUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[NO_ZERO_SUB]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_ZERO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ float nofpclass(zero) %no.zero,
+ float nofpclass(zero sub) %no.zero.sub) {
+ %md.1ulp.no.zero = fdiv float 1.000000e+00, %no.zero, !fpmath !2
+ store volatile float %md.1ulp.no.zero, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.no.zero.sub = fdiv float 1.000000e+00, %no.zero.sub, !fpmath !2
+ store volatile float %md.1ulp.no.zero.sub, ptr addrspace(1) %out, align 4
+ ret void
+}
+
+define amdgpu_kernel void @rcp_fdiv_f32_nosub(ptr addrspace(1) %out,
+; IEEE-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_nosub
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(sub) [[NO_SUB:%.*]], float nofpclass(nsub) [[NO_NSUB:%.*]], float nofpclass(psub) [[NO_PSUB:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[MD_1ULP_NO_SUB:%.*]] = fdiv float 1.000000e+00, [[NO_SUB]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NO_NSUB:%.*]] = fdiv float 1.000000e+00, [[NO_NSUB]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_NSUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_NO_PSUB:%.*]] = fdiv float 1.000000e+00, [[NO_PSUB]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_PSUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_nosub
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(sub) [[NO_SUB:%.*]], float nofpclass(nsub) [[NO_NSUB:%.*]], float nofpclass(psub) [[NO_PSUB:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[MD_1ULP_NO_SUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[NO_SUB]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NO_NSUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[NO_NSUB]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_NSUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_NO_PSUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[NO_PSUB]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_PSUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ float nofpclass(sub) %no.sub,
+ float nofpclass(nsub) %no.nsub,
+ float nofpclass(psub) %no.psub) {
+ %md.1ulp.no.sub = fdiv float 1.000000e+00, %no.sub, !fpmath !2
+ store volatile float %md.1ulp.no.sub, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.no.nsub = fdiv float 1.000000e+00, %no.nsub, !fpmath !2
+ store volatile float %md.1ulp.no.nsub, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.no.psub = fdiv float 1.000000e+00, %no.psub, !fpmath !2
+ store volatile float %md.1ulp.no.psub, ptr addrspace(1) %out, align 4
+
+ ret void
+}
+
+define amdgpu_kernel void @rcp_fdiv_f32_assume_nosub(ptr addrspace(1) %out, float %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_assume_nosub
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]])
+; IEEE-NEXT: [[IS_NOT_SUBNORMAL:%.*]] = fcmp oge float [[FABS_X]], 0x3810000000000000
+; IEEE-NEXT: call void @llvm.assume(i1 [[IS_NOT_SUBNORMAL]])
+; IEEE-NEXT: [[MD_1ULP_NO_SUB:%.*]] = fdiv float 1.000000e+00, [[X]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_assume_nosub
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]])
+; DAZ-NEXT: [[IS_NOT_SUBNORMAL:%.*]] = fcmp oge float [[FABS_X]], 0x3810000000000000
+; DAZ-NEXT: call void @llvm.assume(i1 [[IS_NOT_SUBNORMAL]])
+; DAZ-NEXT: [[MD_1ULP_NO_SUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %fabs.x = call float @llvm.fabs.f32(float %x)
+ %is.not.subnormal = fcmp oge float %fabs.x, 0x3810000000000000
+ call void @llvm.assume(i1 %is.not.subnormal)
+ %md.1ulp.no.sub = fdiv float 1.000000e+00, %x, !fpmath !2
+ store volatile float %md.1ulp.no.sub, ptr addrspace(1) %out, align 4
+ ret void
+}
+
+; Test if we have an assumption on the output that it's not denormal.
+define amdgpu_kernel void @rcp_fdiv_f32_assume_nosub_assume_result_nosub(ptr addrspace(1) %out, float %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_assume_nosub_assume_result_nosub
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]])
+; IEEE-NEXT: [[IS_NOT_SUBNORMAL:%.*]] = fcmp oge float [[FABS_X]], 0x3810000000000000
+; IEEE-NEXT: call void @llvm.assume(i1 [[IS_NOT_SUBNORMAL]])
+; IEEE-NEXT: [[MD_1ULP_NO_SUB:%.*]] = fdiv float 1.000000e+00, [[X]], !fpmath [[META2]]
+; IEEE-NEXT: [[FABS_RESULT:%.*]] = call float @llvm.fabs.f32(float [[MD_1ULP_NO_SUB]])
+; IEEE-NEXT: [[RESULT_IS_NOT_SUBNORMAL:%.*]] = fcmp oge float [[FABS_RESULT]], 0x3810000000000000
+; IEEE-NEXT: call void @llvm.assume(i1 [[RESULT_IS_NOT_SUBNORMAL]])
+; IEEE-NEXT: store volatile float [[MD_1ULP_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_assume_nosub_assume_result_nosub
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]])
+; DAZ-NEXT: [[IS_NOT_SUBNORMAL:%.*]] = fcmp oge float [[FABS_X]], 0x3810000000000000
+; DAZ-NEXT: call void @llvm.assume(i1 [[IS_NOT_SUBNORMAL]])
+; DAZ-NEXT: [[MD_1ULP_NO_SUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[X]])
+; DAZ-NEXT: [[FABS_RESULT:%.*]] = call float @llvm.fabs.f32(float [[MD_1ULP_NO_SUB]])
+; DAZ-NEXT: [[RESULT_IS_NOT_SUBNORMAL:%.*]] = fcmp oge float [[FABS_RESULT]], 0x3810000000000000
+; DAZ-NEXT: call void @llvm.assume(i1 [[RESULT_IS_NOT_SUBNORMAL]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %fabs.x = call float @llvm.fabs.f32(float %x)
+ %is.not.subnormal = fcmp oge float %fabs.x, 0x3810000000000000
+ call void @llvm.assume(i1 %is.not.subnormal)
+ %md.1ulp.no.sub = fdiv float 1.000000e+00, %x, !fpmath !2
+
+ %fabs.result = call float @llvm.fabs.f32(float %md.1ulp.no.sub)
+ %result.is.not.subnormal = fcmp oge float %fabs.result, 0x3810000000000000
+ call void @llvm.assume(i1 %result.is.not.subnormal)
+ store volatile float %md.1ulp.no.sub, ptr addrspace(1) %out, align 4
+ ret void
+}
+
+define amdgpu_kernel void @rcp_fdiv_f32_vector_fpmath_flags(ptr addrspace(1) %out, <2 x float> %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_vector_fpmath_flags
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[X]], i64 0
+; IEEE-NEXT: [[TMP2:%.*]] = fdiv nnan ninf float 1.000000e+00, [[TMP1]]
+; IEEE-NEXT: [[TMP3:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; IEEE-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[X]], i64 1
+; IEEE-NEXT: [[TMP5:%.*]] = fdiv nnan ninf float 1.000000e+00, [[TMP4]]
+; IEEE-NEXT: [[MD_1ULP_NINF_NNAN:%.*]] = insertelement <2 x float> [[TMP3]], float [[TMP5]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_1ULP_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[X]], i64 0
+; IEEE-NEXT: [[TMP7:%.*]] = fdiv ninf float 1.000000e+00, [[TMP6]]
+; IEEE-NEXT: [[TMP8:%.*]] = insertelement <2 x float> poison, float [[TMP7]], i64 0
+; IEEE-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[X]], i64 1
+; IEEE-NEXT: [[TMP10:%.*]] = fdiv ninf float 1.000000e+00, [[TMP9]]
+; IEEE-NEXT: [[MD_1ULP_NINF:%.*]] = insertelement <2 x float> [[TMP8]], float [[TMP10]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_1ULP_NINF]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[TMP11:%.*]] = extractelement <2 x float> [[X]], i64 0
+; IEEE-NEXT: [[TMP12:%.*]] = fdiv nnan float 1.000000e+00, [[TMP11]]
+; IEEE-NEXT: [[TMP13:%.*]] = insertelement <2 x float> poison, float [[TMP12]], i64 0
+; IEEE-NEXT: [[TMP14:%.*]] = extractelement <2 x float> [[X]], i64 1
+; IEEE-NEXT: [[TMP15:%.*]] = fdiv nnan float 1.000000e+00, [[TMP14]]
+; IEEE-NEXT: [[MD_1ULP_NNAN:%.*]] = insertelement <2 x float> [[TMP13]], float [[TMP15]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_1ULP_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[TMP16:%.*]] = extractelement <2 x float> [[X]], i64 0
+; IEEE-NEXT: [[TMP17:%.*]] = fdiv nsz float 1.000000e+00, [[TMP16]]
+; IEEE-NEXT: [[TMP18:%.*]] = insertelement <2 x float> poison, float [[TMP17]], i64 0
+; IEEE-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[X]], i64 1
+; IEEE-NEXT: [[TMP20:%.*]] = fdiv nsz float 1.000000e+00, [[TMP19]]
+; IEEE-NEXT: [[MD_1ULP_NSZ:%.*]] = insertelement <2 x float> [[TMP18]], float [[TMP20]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_1ULP_NSZ]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_vector_fpmath_flags
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[X]], i64 0
+; DAZ-NEXT: [[TMP2:%.*]] = call nnan ninf float @llvm.amdgcn.rcp.f32(float [[TMP1]])
+; DAZ-NEXT: [[TMP3:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; DAZ-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[X]], i64 1
+; DAZ-NEXT: [[TMP5:%.*]] = call nnan ninf float @llvm.amdgcn.rcp.f32(float [[TMP4]])
+; DAZ-NEXT: [[MD_1ULP_NINF_NNAN:%.*]] = insertelement <2 x float> [[TMP3]], float [[TMP5]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_1ULP_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[X]], i64 0
+; DAZ-NEXT: [[TMP7:%.*]] = call ninf float @llvm.amdgcn.rcp.f32(float [[TMP6]])
+; DAZ-NEXT: [[TMP8:%.*]] = insertelement <2 x float> poison, float [[TMP7]], i64 0
+; DAZ-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[X]], i64 1
+; DAZ-NEXT: [[TMP10:%.*]] = call ninf float @llvm.amdgcn.rcp.f32(float [[TMP9]])
+; DAZ-NEXT: [[MD_1ULP_NINF:%.*]] = insertelement <2 x float> [[TMP8]], float [[TMP10]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_1ULP_NINF]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP11:%.*]] = extractelement <2 x float> [[X]], i64 0
+; DAZ-NEXT: [[TMP12:%.*]] = call nnan float @llvm.amdgcn.rcp.f32(float [[TMP11]])
+; DAZ-NEXT: [[TMP13:%.*]] = insertelement <2 x float> poison, float [[TMP12]], i64 0
+; DAZ-NEXT: [[TMP14:%.*]] = extractelement <2 x float> [[X]], i64 1
+; DAZ-NEXT: [[TMP15:%.*]] = call nnan float @llvm.amdgcn.rcp.f32(float [[TMP14]])
+; DAZ-NEXT: [[MD_1ULP_NNAN:%.*]] = insertelement <2 x float> [[TMP13]], float [[TMP15]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_1ULP_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[TMP16:%.*]] = extractelement <2 x float> [[X]], i64 0
+; DAZ-NEXT: [[TMP17:%.*]] = call nsz float @llvm.amdgcn.rcp.f32(float [[TMP16]])
+; DAZ-NEXT: [[TMP18:%.*]] = insertelement <2 x float> poison, float [[TMP17]], i64 0
+; DAZ-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[X]], i64 1
+; DAZ-NEXT: [[TMP20:%.*]] = call nsz float @llvm.amdgcn.rcp.f32(float [[TMP19]])
+; DAZ-NEXT: [[MD_1ULP_NSZ:%.*]] = insertelement <2 x float> [[TMP18]], float [[TMP20]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_1ULP_NSZ]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %md.1ulp.ninf.nnan = fdiv ninf nnan <2 x float> <float 1.0, float 1.0>, %x, !fpmath !2
+ store volatile <2 x float> %md.1ulp.ninf.nnan, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.ninf = fdiv ninf <2 x float> <float 1.0, float 1.0>, %x, !fpmath !2
+ store volatile <2 x float> %md.1ulp.ninf, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.nnan = fdiv nnan <2 x float> <float 1.0, float 1.0>, %x, !fpmath !2
+ store volatile <2 x float> %md.1ulp.nnan, ptr addrspace(1) %out, align 4
+
+ %md.1ulp.nsz = fdiv nsz <2 x float> <float 1.0, float 1.0>, %x, !fpmath !2
+ store volatile <2 x float> %md.1ulp.nsz, ptr addrspace(1) %out, align 4
+
+ ret void
+}
+
+define amdgpu_kernel void @fdiv_fpmath_f32_vector(ptr addrspace(1) %out, <2 x float> %a, <2 x float> %b) {
+; IEEE-LABEL: define amdgpu_kernel void @fdiv_fpmath_f32_vector
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[A]], i64 0
+; IEEE-NEXT: [[TMP2:%.*]] = extractelement <2 x float> [[B]], i64 0
+; IEEE-NEXT: [[TMP3:%.*]] = fdiv float [[TMP1]], [[TMP2]]
+; IEEE-NEXT: [[TMP4:%.*]] = insertelement <2 x float> poison, float [[TMP3]], i64 0
+; IEEE-NEXT: [[TMP5:%.*]] = extractelement <2 x float> [[A]], i64 1
+; IEEE-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[B]], i64 1
+; IEEE-NEXT: [[TMP7:%.*]] = fdiv float [[TMP5]], [[TMP6]]
+; IEEE-NEXT: [[NO_MD:%.*]] = insertelement <2 x float> [[TMP4]], float [[TMP7]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[NO_MD]], ptr addrspace(1) [[OUT]], align 8
+; IEEE-NEXT: [[TMP8:%.*]] = extractelement <2 x float> [[A]], i64 0
+; IEEE-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[B]], i64 0
+; IEEE-NEXT: [[TMP10:%.*]] = fdiv float [[TMP8]], [[TMP9]]
+; IEEE-NEXT: [[TMP11:%.*]] = insertelement <2 x float> poison, float [[TMP10]], i64 0
+; IEEE-NEXT: [[TMP12:%.*]] = extractelement <2 x float> [[A]], i64 1
+; IEEE-NEXT: [[TMP13:%.*]] = extractelement <2 x float> [[B]], i64 1
+; IEEE-NEXT: [[TMP14:%.*]] = fdiv float [[TMP12]], [[TMP13]]
+; IEEE-NEXT: [[MD_HALF_ULP:%.*]] = insertelement <2 x float> [[TMP11]], float [[TMP14]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 8
+; IEEE-NEXT: [[TMP15:%.*]] = extractelement <2 x float> [[A]], i64 0
+; IEEE-NEXT: [[TMP16:%.*]] = extractelement <2 x float> [[B]], i64 0
+; IEEE-NEXT: [[TMP17:%.*]] = fdiv float [[TMP15]], [[TMP16]]
+; IEEE-NEXT: [[TMP18:%.*]] = insertelement <2 x float> poison, float [[TMP17]], i64 0
+; IEEE-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[A]], i64 1
+; IEEE-NEXT: [[TMP20:%.*]] = extractelement <2 x float> [[B]], i64 1
+; IEEE-NEXT: [[TMP21:%.*]] = fdiv float [[TMP19]], [[TMP20]]
+; IEEE-NEXT: [[MD_1ULP:%.*]] = insertelement <2 x float> [[TMP18]], float [[TMP21]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 8
+; IEEE-NEXT: [[TMP22:%.*]] = extractelement <2 x float> [[A]], i64 0
+; IEEE-NEXT: [[TMP23:%.*]] = extractelement <2 x float> [[B]], i64 0
+; IEEE-NEXT: [[TMP24:%.*]] = fdiv float [[TMP22]], [[TMP23]]
+; IEEE-NEXT: [[TMP25:%.*]] = insertelement <2 x float> poison, float [[TMP24]], i64 0
+; IEEE-NEXT: [[TMP26:%.*]] = extractelement <2 x float> [[A]], i64 1
+; IEEE-NEXT: [[TMP27:%.*]] = extractelement <2 x float> [[B]], i64 1
+; IEEE-NEXT: [[TMP28:%.*]] = fdiv float [[TMP26]], [[TMP27]]
+; IEEE-NEXT: [[MD_25ULP:%.*]] = insertelement <2 x float> [[TMP25]], float [[TMP28]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 8
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @fdiv_fpmath_f32_vector
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[A]], i64 0
+; DAZ-NEXT: [[TMP2:%.*]] = extractelement <2 x float> [[B]], i64 0
+; DAZ-NEXT: [[TMP3:%.*]] = fdiv float [[TMP1]], [[TMP2]]
+; DAZ-NEXT: [[TMP4:%.*]] = insertelement <2 x float> poison, float [[TMP3]], i64 0
+; DAZ-NEXT: [[TMP5:%.*]] = extractelement <2 x float> [[A]], i64 1
+; DAZ-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[B]], i64 1
+; DAZ-NEXT: [[TMP7:%.*]] = fdiv float [[TMP5]], [[TMP6]]
+; DAZ-NEXT: [[NO_MD:%.*]] = insertelement <2 x float> [[TMP4]], float [[TMP7]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[NO_MD]], ptr addrspace(1) [[OUT]], align 8
+; DAZ-NEXT: [[TMP8:%.*]] = extractelement <2 x float> [[A]], i64 0
+; DAZ-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[B]], i64 0
+; DAZ-NEXT: [[TMP10:%.*]] = fdiv float [[TMP8]], [[TMP9]]
+; DAZ-NEXT: [[TMP11:%.*]] = insertelement <2 x float> poison, float [[TMP10]], i64 0
+; DAZ-NEXT: [[TMP12:%.*]] = extractelement <2 x float> [[A]], i64 1
+; DAZ-NEXT: [[TMP13:%.*]] = extractelement <2 x float> [[B]], i64 1
+; DAZ-NEXT: [[TMP14:%.*]] = fdiv float [[TMP12]], [[TMP13]]
+; DAZ-NEXT: [[MD_HALF_ULP:%.*]] = insertelement <2 x float> [[TMP11]], float [[TMP14]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 8
+; DAZ-NEXT: [[TMP15:%.*]] = extractelement <2 x float> [[A]], i64 0
+; DAZ-NEXT: [[TMP16:%.*]] = extractelement <2 x float> [[B]], i64 0
+; DAZ-NEXT: [[TMP17:%.*]] = fdiv float [[TMP15]], [[TMP16]]
+; DAZ-NEXT: [[TMP18:%.*]] = insertelement <2 x float> poison, float [[TMP17]], i64 0
+; DAZ-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[A]], i64 1
+; DAZ-NEXT: [[TMP20:%.*]] = extractelement <2 x float> [[B]], i64 1
+; DAZ-NEXT: [[TMP21:%.*]] = fdiv float [[TMP19]], [[TMP20]]
+; DAZ-NEXT: [[MD_1ULP:%.*]] = insertelement <2 x float> [[TMP18]], float [[TMP21]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 8
+; DAZ-NEXT: [[TMP22:%.*]] = extractelement <2 x float> [[A]], i64 0
+; DAZ-NEXT: [[TMP23:%.*]] = extractelement <2 x float> [[B]], i64 0
+; DAZ-NEXT: [[TMP24:%.*]] = call float @llvm.amdgcn.fdiv.fast(float [[TMP22]], float [[TMP23]])
+; DAZ-NEXT: [[TMP25:%.*]] = insertelement <2 x float> poison, float [[TMP24]], i64 0
+; DAZ-NEXT: [[TMP26:%.*]] = extractelement <2 x float> [[A]], i64 1
+; DAZ-NEXT: [[TMP27:%.*]] = extractelement <2 x float> [[B]], i64 1
+; DAZ-NEXT: [[TMP28:%.*]] = call float @llvm.amdgcn.fdiv.fast(float [[TMP26]], float [[TMP27]])
+; DAZ-NEXT: [[MD_25ULP:%.*]] = insertelement <2 x float> [[TMP25]], float [[TMP28]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 8
+; DAZ-NEXT: ret void
+;
+ %no.md = fdiv <2 x float> %a, %b
+ store volatile <2 x float> %no.md, ptr addrspace(1) %out, align 8
+ %md.half.ulp = fdiv <2 x float> %a, %b, !fpmath !1
+ store volatile <2 x float> %md.half.ulp, ptr addrspace(1) %out, align 8
+ %md.1ulp = fdiv <2 x float> %a, %b, !fpmath !2
+ store volatile <2 x float> %md.1ulp, ptr addrspace(1) %out, align 8
%md.25ulp = fdiv <2 x float> %a, %b, !fpmath !0
- store volatile <2 x float> %md.25ulp, ptr addrspace(1) %out
-
- ret void
-}
-
-; CHECK-LABEL: @rcp_fdiv_fpmath_vector(
-; CHECK: %[[NO0:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[NO_FDIV0:[0-9]+]] = fdiv float 1.000000e+00, %[[NO0]]
-; CHECK: %[[NO_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[NO_FDIV0]], i64 0
-; CHECK: %[[NO1:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[NO_FDIV1:[0-9]+]] = fdiv float 1.000000e+00, %[[NO1]]
-; CHECK: %no.md = insertelement <2 x float> %[[NO_INS0]], float %[[NO_FDIV1]], i64 1
-; CHECK: store volatile <2 x float> %no.md, ptr addrspace(1) %out
-
-; CHECK: %[[HALF0:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[HALF_FDIV0:[0-9]+]] = fdiv float 1.000000e+00, %[[HALF0]]
-; CHECK: %[[HALF_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[HALF_FDIV0]], i64 0
-; CHECK: %[[HALF1:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[HALF_FDIV1:[0-9]+]] = fdiv float 1.000000e+00, %[[HALF1]]
-; CHECK: %md.half.ulp = insertelement <2 x float> %[[HALF_INS0]], float %[[HALF_FDIV1]], i64 1
-; CHECK: store volatile <2 x float> %md.half.ulp, ptr addrspace(1) %out
-
-; CHECK: %[[AFN_NO0:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[AFN_NO_FDIV0:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_NO0]])
-; CHECK: %[[AFN_NO_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[AFN_NO_FDIV0]], i64 0
-; CHECK: %[[AFN_NO1:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[AFN_NO_FDIV1:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_NO1]])
-; CHECK: %afn.no.md = insertelement <2 x float> %[[AFN_NO_INS0]], float %[[AFN_NO_FDIV1]], i64 1
-; CHECK: store volatile <2 x float> %afn.no.md, ptr addrspace(1) %out
-
-; CHECK: %[[FAST_NO0:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[FAST_NO_RCP0:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_NO0]])
-; CHECK: %[[FAST_NO_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[FAST_NO_RCP0]], i64 0
-; CHECK: %[[FAST_NO1:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[FAST_NO_RCP1:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_NO1]])
-; CHECK: %fast.no.md = insertelement <2 x float> %[[FAST_NO_INS0]], float %[[FAST_NO_RCP1]], i64 1
-; CHECK: store volatile <2 x float> %fast.no.md, ptr addrspace(1) %out
-
-; CHECK: %[[AFN_250:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[AFN_25_RCP0:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_250]])
-; CHECK: %[[AFN_25_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[AFN_25_RCP0]], i64 0
-; CHECK: %[[AFN_251:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[AFN_25_RCP1:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_251]])
-; CHECK: %afn.25ulp = insertelement <2 x float> %[[AFN_25_INS0]], float %[[AFN_25_RCP1]], i64 1
-; CHECK: store volatile <2 x float> %afn.25ulp, ptr addrspace(1) %out
-
-; CHECK: %[[FAST_250:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[FAST_25_RCP0:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_250]])
-; CHECK: %[[FAST_25_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[FAST_25_RCP0]], i64 0
-; CHECK: %[[FAST_251:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[FAST_25_RCP1:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_251]])
-; CHECK: %fast.25ulp = insertelement <2 x float> %[[FAST_25_INS0]], float %[[FAST_25_RCP1]], i64 1
-; CHECK: store volatile <2 x float> %fast.25ulp, ptr addrspace(1) %out
-define amdgpu_kernel void @rcp_fdiv_fpmath_vector(ptr addrspace(1) %out, <2 x float> %x) #1 {
- %no.md = fdiv <2 x float> <float 1.0, float 1.0>, %x
- store volatile <2 x float> %no.md, ptr addrspace(1) %out
-
- %md.half.ulp = fdiv <2 x float> <float 1.0, float 1.0>, %x, !fpmath !1
- store volatile <2 x float> %md.half.ulp, ptr addrspace(1) %out
-
- %afn.no.md = fdiv afn <2 x float> <float 1.0, float 1.0>, %x
- store volatile <2 x float> %afn.no.md, ptr addrspace(1) %out
-
- %fast.no.md = fdiv fast <2 x float> <float 1.0, float 1.0>, %x
- store volatile <2 x float> %fast.no.md, ptr addrspace(1) %out
-
- %afn.25ulp = fdiv afn <2 x float> <float 1.0, float 1.0>, %x, !fpmath !0
- store volatile <2 x float> %afn.25ulp, ptr addrspace(1) %out
-
- %fast.25ulp = fdiv fast <2 x float> <float 1.0, float 1.0>, %x, !fpmath !0
- store volatile <2 x float> %fast.25ulp, ptr addrspace(1) %out
-
- ret void
-}
-
-; CHECK-LABEL: @rcp_fdiv_fpmath_vector_nonsplat(
-; CHECK: %[[NO0:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[NO_FDIV0:[0-9]+]] = fdiv float 1.000000e+00, %[[NO0]]
-; CHECK: %[[NO_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[NO_FDIV0]], i64 0
-; CHECK: %[[NO1:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[NO_FDIV1:[0-9]+]] = fdiv float 2.000000e+00, %[[NO1]]
-; CHECK: %no.md = insertelement <2 x float> %[[NO_INS0]], float %[[NO_FDIV1]], i64 1
-; CHECK: store volatile <2 x float> %no.md, ptr addrspace(1) %out
-
-; CHECK: %[[AFN_NO0:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[AFN_NO_FDIV0:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_NO0]])
-; CHECK: %[[AFN_NO_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[AFN_NO_FDIV0]], i64 0
-; CHECK: %[[AFN_NO1:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[AFN_NO_FDIV1:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_NO1]])
-; CHECK: %[[AFN_NO_MUL1:[0-9]+]] = fmul afn float 2.000000e+00, %[[AFN_NO_FDIV1]]
-; CHECK: %afn.no.md = insertelement <2 x float> %[[AFN_NO_INS0]], float %[[AFN_NO_MUL1]], i64 1
-; CHECK: store volatile <2 x float> %afn.no.md, ptr addrspace(1) %out
-
-; CHECK: %[[FAST_NO0:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[FAST_NO_RCP0:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_NO0]])
-; CHECK: %[[FAST_NO_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[FAST_NO_RCP0]], i64 0
-; CHECK: %[[FAST_NO1:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[FAST_NO_RCP1:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_NO1]])
-; CHECK: %[[FAST_NO_MUL1:[0-9]+]] = fmul fast float 2.000000e+00, %[[FAST_NO_RCP1]]
-; CHECK: %fast.no.md = insertelement <2 x float> %[[FAST_NO_INS0]], float %[[FAST_NO_MUL1]], i64 1
-; CHECK: store volatile <2 x float> %fast.no.md, ptr addrspace(1) %out
-
-; CHECK: %[[AFN_250:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[AFN_25_RCP0:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_250]])
-; CHECK: %[[AFN_25_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[AFN_25_RCP0]], i64 0
-; CHECK: %[[AFN_251:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[AFN_25_RCP1:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_251]])
-; CHECK: %[[AFN_25_MUL1:[0-9]+]] = fmul afn float 2.000000e+00, %[[AFN_25_RCP1]]
-; CHECK: %afn.25ulp = insertelement <2 x float> %[[AFN_25_INS0]], float %[[AFN_25_MUL1]], i64 1
-; CHECK: store volatile <2 x float> %afn.25ulp, ptr addrspace(1) %out
-
-; CHECK: %[[FAST_250:[0-9]+]] = extractelement <2 x float> %x, i64 0
-; CHECK: %[[FAST_25_RCP0:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_250]])
-; CHECK: %[[FAST_25_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[FAST_25_RCP0]], i64 0
-; CHECK: %[[FAST_251:[0-9]+]] = extractelement <2 x float> %x, i64 1
-; CHECK: %[[FAST_25_RCP1:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_251]])
-; CHECK: %[[FAST_25_MUL1:[0-9]+]] = fmul fast float 2.000000e+00, %[[FAST_25_RCP1]]
-; CHECK: %fast.25ulp = insertelement <2 x float> %[[FAST_25_INS0]], float %[[FAST_25_MUL1]], i64 1
-; CHECK: store volatile <2 x float> %fast.25ulp, ptr addrspace(1) %out
-define amdgpu_kernel void @rcp_fdiv_fpmath_vector_nonsplat(ptr addrspace(1) %out, <2 x float> %x) #1 {
- %no.md = fdiv <2 x float> <float 1.0, float 2.0>, %x
- store volatile <2 x float> %no.md, ptr addrspace(1) %out
-
- %afn.no.md = fdiv afn <2 x float> <float 1.0, float 2.0>, %x
- store volatile <2 x float> %afn.no.md, ptr addrspace(1) %out
-
- %fast.no.md = fdiv fast <2 x float> <float 1.0, float 2.0>, %x
- store volatile <2 x float> %fast.no.md, ptr addrspace(1) %out
-
- %afn.25ulp = fdiv afn <2 x float> <float 1.0, float 2.0>, %x, !fpmath !0
- store volatile <2 x float> %afn.25ulp, ptr addrspace(1) %out
-
- %fast.25ulp = fdiv fast <2 x float> <float 1.0, float 2.0>, %x, !fpmath !0
- store volatile <2 x float> %fast.25ulp, ptr addrspace(1) %out
-
- ret void
-}
-
-; CHECK-LABEL: @rcp_fdiv_fpmath_vector_partial_constant(
-; CHECK: %[[AFN_A0:[0-9]+]] = extractelement <2 x float> %x.insert, i64 0
-; CHECK: %[[AFN_B0:[0-9]+]] = extractelement <2 x float> %y, i64 0
-; CHECK: %[[AFN_RCP0:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_B0]])
-; CHECK: %[[AFN_MUL0:[0-9]+]] = fmul afn float %[[AFN_A0]], %[[AFN_RCP0]]
-; CHECK: %[[AFN_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[AFN_MUL0]], i64 0
-; CHECK: %[[AFN_A1:[0-9]+]] = extractelement <2 x float> %x.insert, i64 1
-; CHECK: %[[AFN_B1:[0-9]+]] = extractelement <2 x float> %y, i64 1
-; CHECK: %[[AFN_RCP1:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %[[AFN_B1]])
-; CHECK: %[[AFN_MUL1:[0-9]+]] = fmul afn float %[[AFN_A1]], %[[AFN_RCP1]]
-; CHECK: %afn.25ulp = insertelement <2 x float> %[[AFN_INS0]], float %[[AFN_MUL1]], i64 1
-; CHECK: store volatile <2 x float> %afn.25ulp
-
-; CHECK: %[[FAST_A0:[0-9]+]] = extractelement <2 x float> %x.insert, i64 0
-; CHECK: %[[FAST_B0:[0-9]+]] = extractelement <2 x float> %y, i64 0
-; CHECK: %[[FAST_RCP0:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_B0]])
-; CHECK: %[[FAST_MUL0:[0-9]+]] = fmul fast float %[[FAST_A0]], %[[FAST_RCP0]]
-; CHECK: %[[FAST_INS0:[0-9]+]] = insertelement <2 x float> poison, float %[[FAST_MUL0]], i64 0
-; CHECK: %[[FAST_A1:[0-9]+]] = extractelement <2 x float> %x.insert, i64 1
-; CHECK: %[[FAST_B1:[0-9]+]] = extractelement <2 x float> %y, i64 1
-; CHECK: %[[FAST_RCP1:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %[[FAST_B1]])
-; CHECK: %[[FAST_MUL1:[0-9]+]] = fmul fast float %[[FAST_A1]], %[[FAST_RCP1]]
-; CHECK: %fast.25ulp = insertelement <2 x float> %[[FAST_INS0]], float %[[FAST_MUL1]], i64 1
-; CHECK: store volatile <2 x float> %fast.25ulp
-define amdgpu_kernel void @rcp_fdiv_fpmath_vector_partial_constant(ptr addrspace(1) %out, <2 x float> %x, <2 x float> %y) #1 {
- %x.insert = insertelement <2 x float> %x, float 1.0, i32 0
+ store volatile <2 x float> %md.25ulp, ptr addrspace(1) %out, align 8
+ ret void
+}
- %afn.25ulp = fdiv afn <2 x float> %x.insert, %y, !fpmath !0
- store volatile <2 x float> %afn.25ulp, ptr addrspace(1) %out
+define amdgpu_kernel void @rcp_fdiv_f32_vector_fpmath(ptr addrspace(1) %out, <2 x float> %x) {
+; CHECK-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_vector_fpmath
+; CHECK-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP2:%.*]] = fdiv float 1.000000e+00, [[TMP1]]
+; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP5:%.*]] = fdiv float 1.000000e+00, [[TMP4]]
+; CHECK-NEXT: [[NO_MD:%.*]] = insertelement <2 x float> [[TMP3]], float [[TMP5]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[NO_MD]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP7:%.*]] = fdiv float 1.000000e+00, [[TMP6]]
+; CHECK-NEXT: [[TMP8:%.*]] = insertelement <2 x float> poison, float [[TMP7]], i64 0
+; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP10:%.*]] = fdiv float 1.000000e+00, [[TMP9]]
+; CHECK-NEXT: [[MD_HALF_ULP:%.*]] = insertelement <2 x float> [[TMP8]], float [[TMP10]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP12:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP11]])
+; CHECK-NEXT: [[TMP13:%.*]] = insertelement <2 x float> poison, float [[TMP12]], i64 0
+; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP15:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP14]])
+; CHECK-NEXT: [[AFN_NO_MD:%.*]] = insertelement <2 x float> [[TMP13]], float [[TMP15]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[AFN_NO_MD]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP17:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP16]])
+; CHECK-NEXT: [[TMP18:%.*]] = insertelement <2 x float> poison, float [[TMP17]], i64 0
+; CHECK-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP20:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP19]])
+; CHECK-NEXT: [[FAST_NO_MD:%.*]] = insertelement <2 x float> [[TMP18]], float [[TMP20]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[FAST_NO_MD]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP21:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP22:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP21]])
+; CHECK-NEXT: [[TMP23:%.*]] = insertelement <2 x float> poison, float [[TMP22]], i64 0
+; CHECK-NEXT: [[TMP24:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP25:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP24]])
+; CHECK-NEXT: [[AFN_25ULP:%.*]] = insertelement <2 x float> [[TMP23]], float [[TMP25]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[AFN_25ULP]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP26:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP27:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP26]])
+; CHECK-NEXT: [[TMP28:%.*]] = insertelement <2 x float> poison, float [[TMP27]], i64 0
+; CHECK-NEXT: [[TMP29:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP30:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP29]])
+; CHECK-NEXT: [[FAST_25ULP:%.*]] = insertelement <2 x float> [[TMP28]], float [[TMP30]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[FAST_25ULP]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: ret void
+;
+ %no.md = fdiv <2 x float> <float 1.000000e+00, float 1.000000e+00>, %x
+ store volatile <2 x float> %no.md, ptr addrspace(1) %out, align 8
+ %md.half.ulp = fdiv <2 x float> <float 1.000000e+00, float 1.000000e+00>, %x, !fpmath !1
+ store volatile <2 x float> %md.half.ulp, ptr addrspace(1) %out, align 8
+ %afn.no.md = fdiv afn <2 x float> <float 1.000000e+00, float 1.000000e+00>, %x
+ store volatile <2 x float> %afn.no.md, ptr addrspace(1) %out, align 8
+ %fast.no.md = fdiv fast <2 x float> <float 1.000000e+00, float 1.000000e+00>, %x
+ store volatile <2 x float> %fast.no.md, ptr addrspace(1) %out, align 8
+ %afn.25ulp = fdiv afn <2 x float> <float 1.000000e+00, float 1.000000e+00>, %x, !fpmath !0
+ store volatile <2 x float> %afn.25ulp, ptr addrspace(1) %out, align 8
+ %fast.25ulp = fdiv fast <2 x float> <float 1.000000e+00, float 1.000000e+00>, %x, !fpmath !0
+ store volatile <2 x float> %fast.25ulp, ptr addrspace(1) %out, align 8
+ ret void
+}
+define amdgpu_kernel void @rcp_fdiv_f32_fpmath_vector_nonsplat(ptr addrspace(1) %out, <2 x float> %x) {
+; CHECK-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_fpmath_vector_nonsplat
+; CHECK-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP2:%.*]] = fdiv float 1.000000e+00, [[TMP1]]
+; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP5:%.*]] = fdiv float 2.000000e+00, [[TMP4]]
+; CHECK-NEXT: [[NO_MD:%.*]] = insertelement <2 x float> [[TMP3]], float [[TMP5]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[NO_MD]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP7:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP6]])
+; CHECK-NEXT: [[TMP8:%.*]] = insertelement <2 x float> poison, float [[TMP7]], i64 0
+; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP10:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP9]])
+; CHECK-NEXT: [[TMP11:%.*]] = fmul afn float 2.000000e+00, [[TMP10]]
+; CHECK-NEXT: [[AFN_NO_MD:%.*]] = insertelement <2 x float> [[TMP8]], float [[TMP11]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[AFN_NO_MD]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP13:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP12]])
+; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x float> poison, float [[TMP13]], i64 0
+; CHECK-NEXT: [[TMP15:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP16:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP15]])
+; CHECK-NEXT: [[TMP17:%.*]] = fmul fast float 2.000000e+00, [[TMP16]]
+; CHECK-NEXT: [[FAST_NO_MD:%.*]] = insertelement <2 x float> [[TMP14]], float [[TMP17]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[FAST_NO_MD]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP18:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP19:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP18]])
+; CHECK-NEXT: [[TMP20:%.*]] = insertelement <2 x float> poison, float [[TMP19]], i64 0
+; CHECK-NEXT: [[TMP21:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP22:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP21]])
+; CHECK-NEXT: [[TMP23:%.*]] = fmul afn float 2.000000e+00, [[TMP22]]
+; CHECK-NEXT: [[AFN_25ULP:%.*]] = insertelement <2 x float> [[TMP20]], float [[TMP23]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[AFN_25ULP]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP24:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP25:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP24]])
+; CHECK-NEXT: [[TMP26:%.*]] = insertelement <2 x float> poison, float [[TMP25]], i64 0
+; CHECK-NEXT: [[TMP27:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP28:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP27]])
+; CHECK-NEXT: [[TMP29:%.*]] = fmul fast float 2.000000e+00, [[TMP28]]
+; CHECK-NEXT: [[FAST_25ULP:%.*]] = insertelement <2 x float> [[TMP26]], float [[TMP29]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[FAST_25ULP]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: ret void
+;
+ %no.md = fdiv <2 x float> <float 1.000000e+00, float 2.000000e+00>, %x
+ store volatile <2 x float> %no.md, ptr addrspace(1) %out, align 8
+ %afn.no.md = fdiv afn <2 x float> <float 1.000000e+00, float 2.000000e+00>, %x
+ store volatile <2 x float> %afn.no.md, ptr addrspace(1) %out, align 8
+ %fast.no.md = fdiv fast <2 x float> <float 1.000000e+00, float 2.000000e+00>, %x
+ store volatile <2 x float> %fast.no.md, ptr addrspace(1) %out, align 8
+ %afn.25ulp = fdiv afn <2 x float> <float 1.000000e+00, float 2.000000e+00>, %x, !fpmath !0
+ store volatile <2 x float> %afn.25ulp, ptr addrspace(1) %out, align 8
+ %fast.25ulp = fdiv fast <2 x float> <float 1.000000e+00, float 2.000000e+00>, %x, !fpmath !0
+ store volatile <2 x float> %fast.25ulp, ptr addrspace(1) %out, align 8
+ ret void
+}
+
+define amdgpu_kernel void @rcp_fdiv_f32_vector_fpmath_partial_constant(ptr addrspace(1) %out, <2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: define amdgpu_kernel void @rcp_fdiv_f32_vector_fpmath_partial_constant
+; CHECK-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[X_INSERT:%.*]] = insertelement <2 x float> [[X]], float 1.000000e+00, i32 0
+; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[X_INSERT]], i64 0
+; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x float> [[Y]], i64 0
+; CHECK-NEXT: [[TMP3:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP2]])
+; CHECK-NEXT: [[TMP4:%.*]] = fmul afn float [[TMP1]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x float> poison, float [[TMP4]], i64 0
+; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[X_INSERT]], i64 1
+; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x float> [[Y]], i64 1
+; CHECK-NEXT: [[TMP8:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[TMP7]])
+; CHECK-NEXT: [[TMP9:%.*]] = fmul afn float [[TMP6]], [[TMP8]]
+; CHECK-NEXT: [[AFN_25ULP:%.*]] = insertelement <2 x float> [[TMP5]], float [[TMP9]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[AFN_25ULP]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x float> [[X_INSERT]], i64 0
+; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x float> [[Y]], i64 0
+; CHECK-NEXT: [[TMP12:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP11]])
+; CHECK-NEXT: [[TMP13:%.*]] = fmul fast float [[TMP10]], [[TMP12]]
+; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x float> poison, float [[TMP13]], i64 0
+; CHECK-NEXT: [[TMP15:%.*]] = extractelement <2 x float> [[X_INSERT]], i64 1
+; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x float> [[Y]], i64 1
+; CHECK-NEXT: [[TMP17:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[TMP16]])
+; CHECK-NEXT: [[TMP18:%.*]] = fmul fast float [[TMP15]], [[TMP17]]
+; CHECK-NEXT: [[FAST_25ULP:%.*]] = insertelement <2 x float> [[TMP14]], float [[TMP18]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[FAST_25ULP]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: ret void
+;
+ %x.insert = insertelement <2 x float> %x, float 1.000000e+00, i32 0
+ %afn.25ulp = fdiv afn <2 x float> %x.insert, %y, !fpmath !0
+ store volatile <2 x float> %afn.25ulp, ptr addrspace(1) %out, align 8
%fast.25ulp = fdiv fast <2 x float> %x.insert, %y, !fpmath !0
- store volatile <2 x float> %fast.25ulp, ptr addrspace(1) %out
+ store volatile <2 x float> %fast.25ulp, ptr addrspace(1) %out, align 8
+ ret void
+}
+
+define amdgpu_kernel void @rsq_f32_fpmath(ptr addrspace(1) %out, float %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rsq_f32_fpmath
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[SQRT_X_NO_MD:%.*]] = call float @llvm.sqrt.f32(float [[X]])
+; IEEE-NEXT: [[NO_MD:%.*]] = fdiv float 1.000000e+00, [[SQRT_X_NO_MD]]
+; IEEE-NEXT: store volatile float [[NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_MD_1ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META2]]
+; IEEE-NEXT: [[MD_1ULP:%.*]] = fdiv float 1.000000e+00, [[SQRT_MD_1ULP]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_MD_1ULP_MULTI_USE:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[SQRT_MD_1ULP_MULTI_USE]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[MD_1ULP_MULTI_USE:%.*]] = fdiv float 1.000000e+00, [[SQRT_MD_1ULP_MULTI_USE]], !fpmath [[META2]]
+; IEEE-NEXT: store volatile float [[MD_1ULP_MULTI_USE]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_MD_25ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0]]
+; IEEE-NEXT: [[MD_25ULP:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_MD_25ULP]])
+; IEEE-NEXT: store volatile float [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_MD_HALF_ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META1]]
+; IEEE-NEXT: [[MD_HALF_ULP:%.*]] = fdiv float 1.000000e+00, [[SQRT_MD_HALF_ULP]], !fpmath [[META1]]
+; IEEE-NEXT: store volatile float [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_AFN_NO_MD:%.*]] = call afn float @llvm.sqrt.f32(float [[X]])
+; IEEE-NEXT: [[AFN_NO_MD:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[SQRT_X_AFN_NO_MD]])
+; IEEE-NEXT: store volatile float [[AFN_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_AFN_25ULP:%.*]] = call afn float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0]]
+; IEEE-NEXT: [[AFN_25ULP:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[SQRT_X_AFN_25ULP]])
+; IEEE-NEXT: store volatile float [[AFN_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_FAST_NO_MD:%.*]] = call fast float @llvm.sqrt.f32(float [[X]])
+; IEEE-NEXT: [[FAST_NO_MD:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[SQRT_X_FAST_NO_MD]])
+; IEEE-NEXT: store volatile float [[FAST_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_FAST_25ULP:%.*]] = call fast float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0]]
+; IEEE-NEXT: [[FAST_25ULP:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[SQRT_X_FAST_25ULP]])
+; IEEE-NEXT: store volatile float [[FAST_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[NEG_SQRT_X_3ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[NEG_FDIV_OPENCL:%.*]] = call float @llvm.amdgcn.fdiv.fast(float -1.000000e+00, float [[NEG_SQRT_X_3ULP]])
+; IEEE-NEXT: store volatile float [[NEG_FDIV_OPENCL]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_HALF_ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META1]]
+; IEEE-NEXT: [[FDIV_SQRT_MISMATCH_MD0:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_HALF_ULP]])
+; IEEE-NEXT: store volatile float [[FDIV_SQRT_MISMATCH_MD0]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_MISMATCH_MD1:%.*]] = call afn float @llvm.sqrt.f32(float [[X]])
+; IEEE-NEXT: [[FDIV_SQRT_MISMATCH_MD1:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_MISMATCH_MD1]])
+; IEEE-NEXT: store volatile float [[FDIV_SQRT_MISMATCH_MD1]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_MISMATCH_MD2:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_SQRT_MISMATCH_MD2:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[SQRT_MISMATCH_MD2]])
+; IEEE-NEXT: store volatile float [[FDIV_SQRT_MISMATCH_MD2]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rsq_f32_fpmath
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[SQRT_X_NO_MD:%.*]] = call float @llvm.sqrt.f32(float [[X]])
+; DAZ-NEXT: [[NO_MD:%.*]] = fdiv float 1.000000e+00, [[SQRT_X_NO_MD]]
+; DAZ-NEXT: store volatile float [[NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_MD_1ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META2]]
+; DAZ-NEXT: [[MD_1ULP:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_MD_1ULP]])
+; DAZ-NEXT: store volatile float [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_MD_1ULP_MULTI_USE:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META2]]
+; DAZ-NEXT: store volatile float [[SQRT_MD_1ULP_MULTI_USE]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[MD_1ULP_MULTI_USE:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_MD_1ULP_MULTI_USE]])
+; DAZ-NEXT: store volatile float [[MD_1ULP_MULTI_USE]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_MD_25ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0]]
+; DAZ-NEXT: [[MD_25ULP:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_MD_25ULP]])
+; DAZ-NEXT: store volatile float [[MD_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_MD_HALF_ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META1]]
+; DAZ-NEXT: [[MD_HALF_ULP:%.*]] = fdiv float 1.000000e+00, [[SQRT_MD_HALF_ULP]], !fpmath [[META1]]
+; DAZ-NEXT: store volatile float [[MD_HALF_ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_AFN_NO_MD:%.*]] = call afn float @llvm.sqrt.f32(float [[X]])
+; DAZ-NEXT: [[AFN_NO_MD:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[SQRT_X_AFN_NO_MD]])
+; DAZ-NEXT: store volatile float [[AFN_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_AFN_25ULP:%.*]] = call afn float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0]]
+; DAZ-NEXT: [[AFN_25ULP:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[SQRT_X_AFN_25ULP]])
+; DAZ-NEXT: store volatile float [[AFN_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_FAST_NO_MD:%.*]] = call fast float @llvm.sqrt.f32(float [[X]])
+; DAZ-NEXT: [[FAST_NO_MD:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[SQRT_X_FAST_NO_MD]])
+; DAZ-NEXT: store volatile float [[FAST_NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_FAST_25ULP:%.*]] = call fast float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0]]
+; DAZ-NEXT: [[FAST_25ULP:%.*]] = call fast float @llvm.amdgcn.rcp.f32(float [[SQRT_X_FAST_25ULP]])
+; DAZ-NEXT: store volatile float [[FAST_25ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3:![0-9]+]]
+; DAZ-NEXT: [[FDIV_OPENCL:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[NEG_SQRT_X_3ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[TMP1:%.*]] = fneg float [[NEG_SQRT_X_3ULP]]
+; DAZ-NEXT: [[NEG_FDIV_OPENCL:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[TMP1]])
+; DAZ-NEXT: store volatile float [[NEG_FDIV_OPENCL]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_HALF_ULP:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META1]]
+; DAZ-NEXT: [[FDIV_SQRT_MISMATCH_MD0:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_HALF_ULP]])
+; DAZ-NEXT: store volatile float [[FDIV_SQRT_MISMATCH_MD0]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_MISMATCH_MD1:%.*]] = call afn float @llvm.sqrt.f32(float [[X]])
+; DAZ-NEXT: [[FDIV_SQRT_MISMATCH_MD1:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_MISMATCH_MD1]])
+; DAZ-NEXT: store volatile float [[FDIV_SQRT_MISMATCH_MD1]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_MISMATCH_MD2:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_SQRT_MISMATCH_MD2:%.*]] = call afn float @llvm.amdgcn.rcp.f32(float [[SQRT_MISMATCH_MD2]])
+; DAZ-NEXT: store volatile float [[FDIV_SQRT_MISMATCH_MD2]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %sqrt.x.no.md = call float @llvm.sqrt.f32(float %x)
+ %no.md = fdiv float 1.000000e+00, %sqrt.x.no.md
+ store volatile float %no.md, ptr addrspace(1) %out, align 4
+
+ ; Matches the rsq instruction accuracy
+ %sqrt.md.1ulp = call float @llvm.sqrt.f32(float %x), !fpmath !2
+ %md.1ulp = fdiv float 1.000000e+00, %sqrt.md.1ulp, !fpmath !2
+ store volatile float %md.1ulp, ptr addrspace(1) %out, align 4
+
+ %sqrt.md.1ulp.multi.use = call float @llvm.sqrt.f32(float %x), !fpmath !2
+ store volatile float %sqrt.md.1ulp.multi.use, ptr addrspace(1) %out, align 4
+ %md.1ulp.multi.use = fdiv float 1.000000e+00, %sqrt.md.1ulp.multi.use, !fpmath !2
+ store volatile float %md.1ulp.multi.use, ptr addrspace(1) %out, align 4
+
+ %sqrt.md.25ulp = call float @llvm.sqrt.f32(float %x), !fpmath !0
+ %md.25ulp = fdiv float 1.000000e+00, %sqrt.md.25ulp, !fpmath !0
+ store volatile float %md.25ulp, ptr addrspace(1) %out, align 4
+
+ %sqrt.md.half.ulp = call float @llvm.sqrt.f32(float %x), !fpmath !1
+ %md.half.ulp = fdiv float 1.000000e+00, %sqrt.md.half.ulp, !fpmath !1
+ store volatile float %md.half.ulp, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.afn.no.md = call afn float @llvm.sqrt.f32(float %x)
+ %afn.no.md = fdiv afn float 1.000000e+00, %sqrt.x.afn.no.md
+ store volatile float %afn.no.md, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.afn.25ulp = call afn float @llvm.sqrt.f32(float %x), !fpmath !0
+ %afn.25ulp = fdiv afn float 1.000000e+00, %sqrt.x.afn.25ulp, !fpmath !0
+ store volatile float %afn.25ulp, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.fast.no.md = call fast float @llvm.sqrt.f32(float %x)
+ %fast.no.md = fdiv fast float 1.000000e+00, %sqrt.x.fast.no.md
+ store volatile float %fast.no.md, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.fast.25ulp = call fast float @llvm.sqrt.f32(float %x), !fpmath !0
+ %fast.25ulp = fdiv fast float 1.000000e+00, %sqrt.x.fast.25ulp, !fpmath !0
+ store volatile float %fast.25ulp, ptr addrspace(1) %out, align 4
+
+
+ ; Test mismatched metadata/flags between the sqrt and fdiv
+
+ ; Test the expected opencl default pattern
+ %sqrt.x.3ulp = call float @llvm.sqrt.f32(float %x), !fpmath !3 ; OpenCL default requires 3 for sqrt and 2.5 for fdiv
+ %fdiv.opencl = fdiv float 1.0, %sqrt.x.3ulp, !fpmath !0
+ store volatile float %fdiv.opencl, ptr addrspace(1) %out, align 4
+
+ %neg.sqrt.x.3ulp = call float @llvm.sqrt.f32(float %x), !fpmath !3 ; OpenCL default requires 3 for sqrt and 2.5 for fdiv
+ %neg.fdiv.opencl = fdiv float -1.0, %neg.sqrt.x.3ulp, !fpmath !0
+ store volatile float %neg.fdiv.opencl, ptr addrspace(1) %out, align 4
+
+ ; sqrt demands higher precision than fdiv
+ %sqrt.x.half.ulp = call float @llvm.sqrt.f32(float %x), !fpmath !1
+ %fdiv.sqrt.mismatch.md0 = fdiv float 1.0, %sqrt.x.half.ulp, !fpmath !0
+ store volatile float %fdiv.sqrt.mismatch.md0, ptr addrspace(1) %out, align 4
+
+ ; sqrt demands full precision but has afn
+ %sqrt.mismatch.md1 = call afn float @llvm.sqrt.f32(float %x)
+ %fdiv.sqrt.mismatch.md1 = fdiv float 1.0, %sqrt.mismatch.md1, !fpmath !0
+ store volatile float %fdiv.sqrt.mismatch.md1, ptr addrspace(1) %out, align 4
+
+ ; sqrt has relaxed precision fdiv has afn only
+ %sqrt.mismatch.md2 = call float @llvm.sqrt.f32(float %x), !fpmath !3
+ %fdiv.sqrt.mismatch.md2 = fdiv afn float 1.0, %sqrt.mismatch.md2
+ store volatile float %fdiv.sqrt.mismatch.md2, ptr addrspace(1) %out, align 4
ret void
}
-; CHECK-LABEL: @fdiv_fpmath_f32_denormals(
-; CHECK: %no.md = fdiv float %a, %b{{$}}
-; CHECK: %md.half.ulp = fdiv float %a, %b
-; CHECK: %md.1ulp = fdiv float %a, %b
-; CHECK: %md.25ulp = fdiv float %a, %b
-; CHECK: %md.3ulp = fdiv float %a, %b
-; CHECK: %[[RCP_FAST:[0-9]+]] = call fast float @llvm.amdgcn.rcp.f32(float %b)
-; CHECK: %fast.md.25ulp = fmul fast float %a, %[[RCP_FAST]]
-; CHECK: %[[RCP_AFN:[0-9]+]] = call afn float @llvm.amdgcn.rcp.f32(float %b)
-; CHECK: %afn.md.25ulp = fmul afn float %a, %[[RCP_AFN]]
-define amdgpu_kernel void @fdiv_fpmath_f32_denormals(ptr addrspace(1) %out, float %a, float %b) #2 {
- %no.md = fdiv float %a, %b
- store volatile float %no.md, ptr addrspace(1) %out
+define amdgpu_kernel void @rsq_f32_fpmath_flags(ptr addrspace(1) %out, float %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rsq_f32_fpmath_flags
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[SQRT_X_3ULP_NINF_NNAN:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NINF_NNAN:%.*]] = call nnan ninf float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NINF_NNAN]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NINF:%.*]] = call ninf float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NINF:%.*]] = call ninf float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NINF]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NINF]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NNAN:%.*]] = call nnan float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NNAN]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NSZ:%.*]] = call nsz float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NSZ:%.*]] = call nsz float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NSZ]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NSZ]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NINF_MIX0:%.*]] = call ninf float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NNAN_MIX0:%.*]] = call nnan float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NINF_MIX0]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NNAN_MIX0]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NINF_MIX1:%.*]] = call ninf float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NNAN_MIX1:%.*]] = call nnan float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NINF_MIX1]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NNAN_MIX1]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rsq_f32_fpmath_flags
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[SQRT_X_3ULP_NINF_NNAN:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NINF_NNAN:%.*]] = call nnan ninf float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NINF_NNAN]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NINF_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NINF:%.*]] = call ninf float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NINF:%.*]] = call ninf float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NINF]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NINF]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NNAN:%.*]] = call nnan float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NNAN]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NNAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NSZ:%.*]] = call nsz float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NSZ:%.*]] = call nsz float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NSZ]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NSZ]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NINF_MIX0:%.*]] = call ninf float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NNAN_MIX0:%.*]] = call nnan float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NINF_MIX0]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NNAN_MIX0]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NINF_MIX1:%.*]] = call ninf float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NNAN_MIX1:%.*]] = call nnan float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NINF_MIX1]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NNAN_MIX1]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %sqrt.x.3ulp.ninf.nnan = call ninf nnan float @llvm.sqrt.f32(float %x), !fpmath !3 ; OpenCL default requires 3 for sqrt and 2.5 for fdiv
+ %fdiv.opencl.ninf.nnan = fdiv ninf nnan float 1.0, %sqrt.x.3ulp.ninf.nnan, !fpmath !0
+ store volatile float %fdiv.opencl.ninf.nnan, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.ninf = call ninf float @llvm.sqrt.f32(float %x), !fpmath !3 ; OpenCL default requires 3 for sqrt and 2.5 for fdiv
+ %fdiv.opencl.ninf = fdiv ninf float 1.0, %sqrt.x.3ulp.ninf, !fpmath !0
+ store volatile float %fdiv.opencl.ninf, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.nnan = call nnan float @llvm.sqrt.f32(float %x), !fpmath !3 ; OpenCL default requires 3 for sqrt and 2.5 for fdiv
+ %fdiv.opencl.nnan = fdiv nnan float 1.0, %sqrt.x.3ulp.nnan, !fpmath !0
+ store volatile float %fdiv.opencl.nnan, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.nsz = call nsz float @llvm.sqrt.f32(float %x), !fpmath !3 ; OpenCL default requires 3 for sqrt and 2.5 for fdiv
+ %fdiv.opencl.nsz = fdiv nsz float 1.0, %sqrt.x.3ulp.nsz, !fpmath !0
+ store volatile float %fdiv.opencl.nsz, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.ninf.mix0 = call ninf float @llvm.sqrt.f32(float %x), !fpmath !3
+ %fdiv.opencl.nnan.mix0 = fdiv nnan float 1.0, %sqrt.x.3ulp.ninf.mix0, !fpmath !0
+ store volatile float %fdiv.opencl.nnan.mix0, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.ninf.mix1 = call ninf float @llvm.sqrt.f32(float %x), !fpmath !3
+ %fdiv.opencl.nnan.mix1 = fdiv nnan float 1.0, %sqrt.x.3ulp.ninf.mix1, !fpmath !0
+ store volatile float %fdiv.opencl.nnan.mix1, ptr addrspace(1) %out, align 4
- %md.half.ulp = fdiv float %a, %b, !fpmath !1
- store volatile float %md.half.ulp, ptr addrspace(1) %out
+ ret void
+}
- %md.1ulp = fdiv float %a, %b, !fpmath !2
- store volatile float %md.1ulp, ptr addrspace(1) %out
+define amdgpu_kernel void @rsq_f32_knownfinite(ptr addrspace(1) %out, float nofpclass(nan) %no.nan,
+; IEEE-LABEL: define amdgpu_kernel void @rsq_f32_knownfinite
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(nan) [[NO_NAN:%.*]], float nofpclass(nan) [[NO_INF:%.*]], float nofpclass(nan inf) [[NO_INF_NAN:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_NAN:%.*]] = call float @llvm.sqrt.f32(float [[NO_NAN]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_NAN:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_NAN]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_NAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_INF:%.*]] = call float @llvm.sqrt.f32(float [[NO_INF]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_INF:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_INF]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_INF]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_INF_NAN:%.*]] = call float @llvm.sqrt.f32(float [[NO_INF_NAN]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_INF_NAN:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_INF_NAN]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_INF_NAN]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rsq_f32_knownfinite
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(nan) [[NO_NAN:%.*]], float nofpclass(nan) [[NO_INF:%.*]], float nofpclass(nan inf) [[NO_INF_NAN:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_NAN:%.*]] = call float @llvm.sqrt.f32(float [[NO_NAN]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_NAN:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_NAN]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_NAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_INF:%.*]] = call float @llvm.sqrt.f32(float [[NO_INF]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_INF:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_INF]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_INF]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_INF_NAN:%.*]] = call float @llvm.sqrt.f32(float [[NO_INF_NAN]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_INF_NAN:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_INF_NAN]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_INF_NAN]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ float nofpclass(nan) %no.inf,
+ float nofpclass(inf nan) %no.inf.nan) {
+ %sqrt.x.3ulp.no.nan = call float @llvm.sqrt.f32(float %no.nan), !fpmath !3
+ %fdiv.opencl.no.nan = fdiv float 1.0, %sqrt.x.3ulp.no.nan, !fpmath !0
+ store volatile float %fdiv.opencl.no.nan, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.no.inf = call float @llvm.sqrt.f32(float %no.inf), !fpmath !3
+ %fdiv.opencl.no.inf = fdiv float 1.0, %sqrt.x.3ulp.no.inf, !fpmath !0
+ store volatile float %fdiv.opencl.no.inf, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.no.inf.nan = call float @llvm.sqrt.f32(float %no.inf.nan), !fpmath !3
+ %fdiv.opencl.no.inf.nan = fdiv float 1.0, %sqrt.x.3ulp.no.inf.nan, !fpmath !0
+ store volatile float %fdiv.opencl.no.inf.nan, ptr addrspace(1) %out, align 4
- %md.25ulp = fdiv float %a, %b, !fpmath !0
- store volatile float %md.25ulp, ptr addrspace(1) %out
+ ret void
+}
- %md.3ulp = fdiv float %a, %b, !fpmath !3
- store volatile float %md.3ulp, ptr addrspace(1) %out
+define amdgpu_kernel void @rsq_f32_known_nozero(ptr addrspace(1) %out, float nofpclass(zero) %no.zero, float nofpclass(zero sub) %no.zero.sub) {
+; IEEE-LABEL: define amdgpu_kernel void @rsq_f32_known_nozero
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(zero) [[NO_ZERO:%.*]], float nofpclass(zero sub) [[NO_ZERO_SUB:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_ZERO:%.*]] = call float @llvm.sqrt.f32(float [[NO_ZERO]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_ZERO:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_ZERO]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_ZERO]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_ZERO_SUB:%.*]] = call float @llvm.sqrt.f32(float [[NO_ZERO_SUB]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_ZERO_SUB:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_ZERO_SUB]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_ZERO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rsq_f32_known_nozero
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(zero) [[NO_ZERO:%.*]], float nofpclass(zero sub) [[NO_ZERO_SUB:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_ZERO:%.*]] = call float @llvm.sqrt.f32(float [[NO_ZERO]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_ZERO:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_ZERO]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_ZERO]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_ZERO_SUB:%.*]] = call float @llvm.sqrt.f32(float [[NO_ZERO_SUB]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_ZERO_SUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_ZERO_SUB]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_ZERO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %sqrt.x.3ulp.no.zero = call float @llvm.sqrt.f32(float %no.zero), !fpmath !3
+ %fdiv.opencl.no.zero = fdiv float 1.0, %sqrt.x.3ulp.no.zero, !fpmath !0
+ store volatile float %fdiv.opencl.no.zero, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.no.zero.sub = call float @llvm.sqrt.f32(float %no.zero.sub), !fpmath !3
+ %fdiv.opencl.no.zero.sub = fdiv float 1.0, %sqrt.x.3ulp.no.zero.sub, !fpmath !0
+ store volatile float %fdiv.opencl.no.zero.sub, ptr addrspace(1) %out, align 4
- %fast.md.25ulp = fdiv fast float %a, %b, !fpmath !0
- store volatile float %fast.md.25ulp, ptr addrspace(1) %out
+ ret void
+}
- %afn.md.25ulp = fdiv afn float %a, %b, !fpmath !0
- store volatile float %afn.md.25ulp, ptr addrspace(1) %out
+define amdgpu_kernel void @rsq_f32_known_nosub(ptr addrspace(1) %out, float nofpclass(sub) %no.sub, float nofpclass(psub) %no.psub, float nofpclass(nsub) %no.nsub) {
+; IEEE-LABEL: define amdgpu_kernel void @rsq_f32_known_nosub
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(sub) [[NO_SUB:%.*]], float nofpclass(psub) [[NO_PSUB:%.*]], float nofpclass(nsub) [[NO_NSUB:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_SUB:%.*]] = call float @llvm.sqrt.f32(float [[NO_SUB]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_SUB:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_SUB]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_PSUB:%.*]] = call float @llvm.sqrt.f32(float [[NO_PSUB]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_PSUB:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_PSUB]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_PSUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_NSUB:%.*]] = call float @llvm.sqrt.f32(float [[NO_NSUB]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_NSUB:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_NSUB]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_NSUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rsq_f32_known_nosub
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float nofpclass(sub) [[NO_SUB:%.*]], float nofpclass(psub) [[NO_PSUB:%.*]], float nofpclass(nsub) [[NO_NSUB:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_SUB:%.*]] = call float @llvm.sqrt.f32(float [[NO_SUB]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_SUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_SUB]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_PSUB:%.*]] = call float @llvm.sqrt.f32(float [[NO_PSUB]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_PSUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_PSUB]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_PSUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_NSUB:%.*]] = call float @llvm.sqrt.f32(float [[NO_NSUB]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_NSUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_NSUB]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_NSUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %sqrt.x.3ulp.no.sub = call float @llvm.sqrt.f32(float %no.sub), !fpmath !3
+ %fdiv.opencl.no.sub = fdiv float 1.0, %sqrt.x.3ulp.no.sub, !fpmath !0
+ store volatile float %fdiv.opencl.no.sub, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.no.psub = call float @llvm.sqrt.f32(float %no.psub), !fpmath !3
+ %fdiv.opencl.no.psub = fdiv float 1.0, %sqrt.x.3ulp.no.psub, !fpmath !0
+ store volatile float %fdiv.opencl.no.psub, ptr addrspace(1) %out, align 4
+
+ %sqrt.x.3ulp.no.nsub = call float @llvm.sqrt.f32(float %no.nsub), !fpmath !3
+ %fdiv.opencl.no.nsub = fdiv float 1.0, %sqrt.x.3ulp.no.nsub, !fpmath !0
+ store volatile float %fdiv.opencl.no.nsub, ptr addrspace(1) %out, align 4
+
+ ret void
+}
+
+define amdgpu_kernel void @rsq_f32_assume_nosub(ptr addrspace(1) %out, float %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rsq_f32_assume_nosub
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]])
+; IEEE-NEXT: [[IS_NOT_SUBNORMAL:%.*]] = fcmp oge float [[FABS_X]], 0x3810000000000000
+; IEEE-NEXT: call void @llvm.assume(i1 [[IS_NOT_SUBNORMAL]])
+; IEEE-NEXT: [[SQRT_X_3ULP_NO_SUB:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[FDIV_OPENCL_NO_SUB:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[SQRT_X_3ULP_NO_SUB]])
+; IEEE-NEXT: store volatile float [[FDIV_OPENCL_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rsq_f32_assume_nosub
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]])
+; DAZ-NEXT: [[IS_NOT_SUBNORMAL:%.*]] = fcmp oge float [[FABS_X]], 0x3810000000000000
+; DAZ-NEXT: call void @llvm.assume(i1 [[IS_NOT_SUBNORMAL]])
+; DAZ-NEXT: [[SQRT_X_3ULP_NO_SUB:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[FDIV_OPENCL_NO_SUB:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT_X_3ULP_NO_SUB]])
+; DAZ-NEXT: store volatile float [[FDIV_OPENCL_NO_SUB]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %fabs.x = call float @llvm.fabs.f32(float %x)
+ %is.not.subnormal = fcmp oge float %fabs.x, 0x3810000000000000
+ call void @llvm.assume(i1 %is.not.subnormal)
+ %sqrt.x.3ulp.no.sub = call float @llvm.sqrt.f32(float %x), !fpmath !3
+ %fdiv.opencl.no.sub = fdiv float 1.0, %sqrt.x.3ulp.no.sub, !fpmath !0
+ store volatile float %fdiv.opencl.no.sub, ptr addrspace(1) %out, align 4
+ ret void
+}
+
+define amdgpu_kernel void @rsq_f32_vector_fpmath(ptr addrspace(1) %out, <2 x float> %x) {
+; IEEE-LABEL: define amdgpu_kernel void @rsq_f32_vector_fpmath
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[SQRT_X_NO_MD:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]])
+; IEEE-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[SQRT_X_NO_MD]], i64 0
+; IEEE-NEXT: [[TMP2:%.*]] = fdiv float 1.000000e+00, [[TMP1]]
+; IEEE-NEXT: [[TMP3:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; IEEE-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[SQRT_X_NO_MD]], i64 1
+; IEEE-NEXT: [[TMP5:%.*]] = fdiv float 1.000000e+00, [[TMP4]]
+; IEEE-NEXT: [[NO_MD:%.*]] = insertelement <2 x float> [[TMP3]], float [[TMP5]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_MD_1ULP:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]), !fpmath [[META2]]
+; IEEE-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[SQRT_MD_1ULP]], i64 0
+; IEEE-NEXT: [[TMP7:%.*]] = fdiv float 1.000000e+00, [[TMP6]]
+; IEEE-NEXT: [[TMP8:%.*]] = insertelement <2 x float> poison, float [[TMP7]], i64 0
+; IEEE-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[SQRT_MD_1ULP]], i64 1
+; IEEE-NEXT: [[TMP10:%.*]] = fdiv float 1.000000e+00, [[TMP9]]
+; IEEE-NEXT: [[MD_1ULP:%.*]] = insertelement <2 x float> [[TMP8]], float [[TMP10]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_MD_1ULP_UNDEF:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]), !fpmath [[META2]]
+; IEEE-NEXT: [[TMP11:%.*]] = extractelement <2 x float> [[SQRT_MD_1ULP_UNDEF]], i64 0
+; IEEE-NEXT: [[TMP12:%.*]] = fdiv float 1.000000e+00, [[TMP11]]
+; IEEE-NEXT: [[TMP13:%.*]] = insertelement <2 x float> poison, float [[TMP12]], i64 0
+; IEEE-NEXT: [[TMP14:%.*]] = extractelement <2 x float> [[SQRT_MD_1ULP_UNDEF]], i64 1
+; IEEE-NEXT: [[TMP15:%.*]] = fdiv float undef, [[TMP14]]
+; IEEE-NEXT: [[MD_1ULP_UNDEF:%.*]] = insertelement <2 x float> [[TMP13]], float [[TMP15]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[MD_1ULP_UNDEF]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: [[SQRT_X_3ULP:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]), !fpmath [[META3]]
+; IEEE-NEXT: [[TMP16:%.*]] = extractelement <2 x float> [[SQRT_X_3ULP]], i64 0
+; IEEE-NEXT: [[TMP17:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[TMP16]])
+; IEEE-NEXT: [[TMP18:%.*]] = insertelement <2 x float> poison, float [[TMP17]], i64 0
+; IEEE-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[SQRT_X_3ULP]], i64 1
+; IEEE-NEXT: [[TMP20:%.*]] = call float @llvm.amdgcn.fdiv.fast(float 1.000000e+00, float [[TMP19]])
+; IEEE-NEXT: [[FDIV_OPENCL:%.*]] = insertelement <2 x float> [[TMP18]], float [[TMP20]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[FDIV_OPENCL]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @rsq_f32_vector_fpmath
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[SQRT_X_NO_MD:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]])
+; DAZ-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[SQRT_X_NO_MD]], i64 0
+; DAZ-NEXT: [[TMP2:%.*]] = fdiv float 1.000000e+00, [[TMP1]]
+; DAZ-NEXT: [[TMP3:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0
+; DAZ-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[SQRT_X_NO_MD]], i64 1
+; DAZ-NEXT: [[TMP5:%.*]] = fdiv float 1.000000e+00, [[TMP4]]
+; DAZ-NEXT: [[NO_MD:%.*]] = insertelement <2 x float> [[TMP3]], float [[TMP5]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[NO_MD]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_MD_1ULP:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]), !fpmath [[META2]]
+; DAZ-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[SQRT_MD_1ULP]], i64 0
+; DAZ-NEXT: [[TMP7:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[TMP6]])
+; DAZ-NEXT: [[TMP8:%.*]] = insertelement <2 x float> poison, float [[TMP7]], i64 0
+; DAZ-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[SQRT_MD_1ULP]], i64 1
+; DAZ-NEXT: [[TMP10:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[TMP9]])
+; DAZ-NEXT: [[MD_1ULP:%.*]] = insertelement <2 x float> [[TMP8]], float [[TMP10]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_1ULP]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_MD_1ULP_UNDEF:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]), !fpmath [[META2]]
+; DAZ-NEXT: [[TMP11:%.*]] = extractelement <2 x float> [[SQRT_MD_1ULP_UNDEF]], i64 0
+; DAZ-NEXT: [[TMP12:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[TMP11]])
+; DAZ-NEXT: [[TMP13:%.*]] = insertelement <2 x float> poison, float [[TMP12]], i64 0
+; DAZ-NEXT: [[TMP14:%.*]] = extractelement <2 x float> [[SQRT_MD_1ULP_UNDEF]], i64 1
+; DAZ-NEXT: [[TMP15:%.*]] = fdiv float undef, [[TMP14]]
+; DAZ-NEXT: [[MD_1ULP_UNDEF:%.*]] = insertelement <2 x float> [[TMP13]], float [[TMP15]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[MD_1ULP_UNDEF]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: [[SQRT_X_3ULP:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]), !fpmath [[META3]]
+; DAZ-NEXT: [[TMP16:%.*]] = extractelement <2 x float> [[SQRT_X_3ULP]], i64 0
+; DAZ-NEXT: [[TMP17:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[TMP16]])
+; DAZ-NEXT: [[TMP18:%.*]] = insertelement <2 x float> poison, float [[TMP17]], i64 0
+; DAZ-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[SQRT_X_3ULP]], i64 1
+; DAZ-NEXT: [[TMP20:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[TMP19]])
+; DAZ-NEXT: [[FDIV_OPENCL:%.*]] = insertelement <2 x float> [[TMP18]], float [[TMP20]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[FDIV_OPENCL]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %sqrt.x.no.md = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x)
+ %no.md = fdiv <2 x float> <float 1.0, float 1.0>, %sqrt.x.no.md
+ store volatile <2 x float> %no.md, ptr addrspace(1) %out, align 4
+
+ ; Matches the rsq instruction accuracy
+ %sqrt.md.1ulp = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x), !fpmath !2
+ %md.1ulp = fdiv <2 x float> <float 1.0, float 1.0>, %sqrt.md.1ulp, !fpmath !2
+ store volatile <2 x float> %md.1ulp, ptr addrspace(1) %out, align 4
+
+ ; Matches the rsq instruction accuracy
+ %sqrt.md.1ulp.undef = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x), !fpmath !2
+ %md.1ulp.undef = fdiv <2 x float> <float 1.0, float undef>, %sqrt.md.1ulp.undef, !fpmath !2
+ store volatile <2 x float> %md.1ulp.undef, ptr addrspace(1) %out, align 4
+
+ ; Test mismatched metadata/flags between the sqrt and fdiv
+
+ ; Test the expected opencl default pattern
+ %sqrt.x.3ulp = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x), !fpmath !3 ; OpenCL default requires 3 for sqrt and 2.5 for fdiv
+ %fdiv.opencl = fdiv <2 x float> <float 1.0, float 1.0>, %sqrt.x.3ulp, !fpmath !0
+ store volatile <2 x float> %fdiv.opencl, ptr addrspace(1) %out, align 4
+
+ ret void
+}
+
+define amdgpu_kernel void @multiple_arcp_fdiv_denom_nomd(ptr addrspace(1) %out, float %x, float %y, float %denom) {
+; CHECK-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_nomd
+; CHECK-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]]
+; CHECK-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]]
+; CHECK-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT: ret void
+;
+ %arcp0 = fdiv arcp float %x, %denom
+ %arcp1 = fdiv arcp float %y, %denom
+ store volatile float %arcp0, ptr addrspace(1) %out
+ store volatile float %arcp1, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp(ptr addrspace(1) %out, float %x, float %y, float %denom) {
+; IEEE-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[ARCP0:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[X]], float [[DENOM]])
+; DAZ-NEXT: [[ARCP1:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[Y]], float [[DENOM]])
+; DAZ-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %arcp0 = fdiv arcp float %x, %denom, !fpmath !0
+ %arcp1 = fdiv arcp float %y, %denom, !fpmath !0
+ store volatile float %arcp0, ptr addrspace(1) %out
+ store volatile float %arcp1, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp_x3(ptr addrspace(1) %out, float %x, float %y, float %z, float %denom) {
+; IEEE-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp_x3
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: [[ARCP2:%.*]] = fdiv arcp float [[Z]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: store volatile float [[ARCP2]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp_x3
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[ARCP0:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[X]], float [[DENOM]])
+; DAZ-NEXT: [[ARCP1:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[Y]], float [[DENOM]])
+; DAZ-NEXT: [[ARCP2:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[Z]], float [[DENOM]])
+; DAZ-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: store volatile float [[ARCP2]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %arcp0 = fdiv arcp float %x, %denom, !fpmath !0
+ %arcp1 = fdiv arcp float %y, %denom, !fpmath !0
+ %arcp2 = fdiv arcp float %z, %denom, !fpmath !0
+ store volatile float %arcp0, ptr addrspace(1) %out
+ store volatile float %arcp1, ptr addrspace(1) %out
+ store volatile float %arcp2, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp_nomd(ptr addrspace(1) %out, float %x, float %y, float %denom) {
+; IEEE-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp_nomd
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]]
+; IEEE-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_25ulp_nomd
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[ARCP0:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[X]], float [[DENOM]])
+; DAZ-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]]
+; DAZ-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %arcp0 = fdiv arcp float %x, %denom, !fpmath !0
+ %arcp1 = fdiv arcp float %y, %denom
+ store volatile float %arcp0, ptr addrspace(1) %out
+ store volatile float %arcp1, ptr addrspace(1) %out
+ ret void
+}
+define amdgpu_kernel void @multiple_arcp_fdiv_denom_nomd_25ulp(ptr addrspace(1) %out, float %x, float %y, float %denom) {
+; IEEE-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_nomd_25ulp
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]]
+; IEEE-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_nomd_25ulp
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]]
+; DAZ-NEXT: [[ARCP1:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[Y]], float [[DENOM]])
+; DAZ-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %arcp0 = fdiv arcp float %x, %denom
+ %arcp1 = fdiv arcp float %y, %denom, !fpmath !0
+ store volatile float %arcp0, ptr addrspace(1) %out
+ store volatile float %arcp1, ptr addrspace(1) %out
ret void
}
-; CHECK-LABEL: @rcp_fpmath_dynamic_denorm(
-; CHECK: %md.25ulp = fdiv float 1.000000e+00, %x, !fpmath !2
-define float @rcp_fpmath_dynamic_denorm(float %x) #3 {
- %md.25ulp = fdiv float 1.0, %x, !fpmath !2
- ret float %md.25ulp
+define amdgpu_kernel void @multiple_arcp_fdiv_denom_1ulp(ptr addrspace(1) %out, float %x, float %y, float %denom) {
+; CHECK-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_1ulp
+; CHECK-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[DENOM:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]], !fpmath [[META2:![0-9]+]]
+; CHECK-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]], !fpmath [[META2]]
+; CHECK-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT: ret void
+;
+ %arcp0 = fdiv arcp float %x, %denom, !fpmath !2
+ %arcp1 = fdiv arcp float %y, %denom, !fpmath !2
+ store volatile float %arcp0, ptr addrspace(1) %out
+ store volatile float %arcp1, ptr addrspace(1) %out
+ ret void
}
-; CHECK-LABEL: @rcp_dynamic_denorm(
-; CHECK: %md.25ulp = fdiv float 1.000000e+00, %x
-define float @rcp_dynamic_denorm(float %x) #3 {
- %md.25ulp = fdiv float 1.0, %x
- ret float %md.25ulp
+define amdgpu_kernel void @multiple_arcp_fdiv_denom_1ulp_vector(ptr addrspace(1) %out, <2 x float> %x, <2 x float> %y, <2 x float> %denom) {
+; CHECK-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_denom_1ulp_vector
+; CHECK-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[DENOM:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[X]], i64 0
+; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x float> [[DENOM]], i64 0
+; CHECK-NEXT: [[TMP3:%.*]] = fdiv arcp float [[TMP1]], [[TMP2]]
+; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x float> poison, float [[TMP3]], i64 0
+; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x float> [[X]], i64 1
+; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[DENOM]], i64 1
+; CHECK-NEXT: [[TMP7:%.*]] = fdiv arcp float [[TMP5]], [[TMP6]]
+; CHECK-NEXT: [[ARCP0:%.*]] = insertelement <2 x float> [[TMP4]], float [[TMP7]], i64 1
+; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x float> [[Y]], i64 0
+; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[DENOM]], i64 0
+; CHECK-NEXT: [[TMP10:%.*]] = fdiv arcp float [[TMP8]], [[TMP9]]
+; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x float> poison, float [[TMP10]], i64 0
+; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x float> [[Y]], i64 1
+; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x float> [[DENOM]], i64 1
+; CHECK-NEXT: [[TMP14:%.*]] = fdiv arcp float [[TMP12]], [[TMP13]]
+; CHECK-NEXT: [[ARCP1:%.*]] = insertelement <2 x float> [[TMP11]], float [[TMP14]], i64 1
+; CHECK-NEXT: store volatile <2 x float> [[ARCP0]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: store volatile <2 x float> [[ARCP1]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: ret void
+;
+ %arcp0 = fdiv arcp <2 x float> %x, %denom, !fpmath !2
+ %arcp1 = fdiv arcp <2 x float> %y, %denom, !fpmath !2
+ store volatile <2 x float> %arcp0, ptr addrspace(1) %out
+ store volatile <2 x float> %arcp1, ptr addrspace(1) %out
+ ret void
}
-attributes #0 = { nounwind optnone noinline }
-attributes #1 = { nounwind "denormal-fp-math-f32"="preserve-sign,preserve-sign" }
-attributes #2 = { nounwind "denormal-fp-math-f32"="ieee,ieee" }
-attributes #3 = { nounwind "denormal-fp-math-f32"="dynamic,dynamic" }
+define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_25ulp(ptr addrspace(1) %out, float %x, float %y, float %sqr.denom) {
+; IEEE-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_25ulp
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[SQR_DENOM:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[DENOM:%.*]] = call float @llvm.sqrt.f32(float [[SQR_DENOM]]), !fpmath [[META3]]
+; IEEE-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_25ulp
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[SQR_DENOM:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[DENOM:%.*]] = call float @llvm.sqrt.f32(float [[SQR_DENOM]]), !fpmath [[META3]]
+; DAZ-NEXT: [[ARCP0:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[X]], float [[DENOM]])
+; DAZ-NEXT: [[ARCP1:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[Y]], float [[DENOM]])
+; DAZ-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %denom = call float @llvm.sqrt.f32(float %sqr.denom), !fpmath !3
+ %arcp0 = fdiv arcp float %x, %denom, !fpmath !0
+ %arcp1 = fdiv arcp float %y, %denom, !fpmath !0
+ store volatile float %arcp0, ptr addrspace(1) %out
+ store volatile float %arcp1, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_vector_25ulp(ptr addrspace(1) %out, <2 x float> %x, <2 x float> %y, <2 x float> %sqr.denom) {
+; IEEE-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_vector_25ulp
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[SQR_DENOM:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[DENOM:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[SQR_DENOM]]), !fpmath [[META3]]
+; IEEE-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[X]], i64 0
+; IEEE-NEXT: [[TMP2:%.*]] = extractelement <2 x float> [[DENOM]], i64 0
+; IEEE-NEXT: [[TMP3:%.*]] = fdiv arcp float [[TMP1]], [[TMP2]]
+; IEEE-NEXT: [[TMP4:%.*]] = insertelement <2 x float> poison, float [[TMP3]], i64 0
+; IEEE-NEXT: [[TMP5:%.*]] = extractelement <2 x float> [[X]], i64 1
+; IEEE-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[DENOM]], i64 1
+; IEEE-NEXT: [[TMP7:%.*]] = fdiv arcp float [[TMP5]], [[TMP6]]
+; IEEE-NEXT: [[ARCP0:%.*]] = insertelement <2 x float> [[TMP4]], float [[TMP7]], i64 1
+; IEEE-NEXT: [[TMP8:%.*]] = extractelement <2 x float> [[Y]], i64 0
+; IEEE-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[DENOM]], i64 0
+; IEEE-NEXT: [[TMP10:%.*]] = fdiv arcp float [[TMP8]], [[TMP9]]
+; IEEE-NEXT: [[TMP11:%.*]] = insertelement <2 x float> poison, float [[TMP10]], i64 0
+; IEEE-NEXT: [[TMP12:%.*]] = extractelement <2 x float> [[Y]], i64 1
+; IEEE-NEXT: [[TMP13:%.*]] = extractelement <2 x float> [[DENOM]], i64 1
+; IEEE-NEXT: [[TMP14:%.*]] = fdiv arcp float [[TMP12]], [[TMP13]]
+; IEEE-NEXT: [[ARCP1:%.*]] = insertelement <2 x float> [[TMP11]], float [[TMP14]], i64 1
+; IEEE-NEXT: store volatile <2 x float> [[ARCP0]], ptr addrspace(1) [[OUT]], align 8
+; IEEE-NEXT: store volatile <2 x float> [[ARCP1]], ptr addrspace(1) [[OUT]], align 8
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_vector_25ulp
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], <2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[SQR_DENOM:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[DENOM:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[SQR_DENOM]]), !fpmath [[META3]]
+; DAZ-NEXT: [[TMP1:%.*]] = extractelement <2 x float> [[X]], i64 0
+; DAZ-NEXT: [[TMP2:%.*]] = extractelement <2 x float> [[DENOM]], i64 0
+; DAZ-NEXT: [[TMP3:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[TMP1]], float [[TMP2]])
+; DAZ-NEXT: [[TMP4:%.*]] = insertelement <2 x float> poison, float [[TMP3]], i64 0
+; DAZ-NEXT: [[TMP5:%.*]] = extractelement <2 x float> [[X]], i64 1
+; DAZ-NEXT: [[TMP6:%.*]] = extractelement <2 x float> [[DENOM]], i64 1
+; DAZ-NEXT: [[TMP7:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[TMP5]], float [[TMP6]])
+; DAZ-NEXT: [[ARCP0:%.*]] = insertelement <2 x float> [[TMP4]], float [[TMP7]], i64 1
+; DAZ-NEXT: [[TMP8:%.*]] = extractelement <2 x float> [[Y]], i64 0
+; DAZ-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[DENOM]], i64 0
+; DAZ-NEXT: [[TMP10:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[TMP8]], float [[TMP9]])
+; DAZ-NEXT: [[TMP11:%.*]] = insertelement <2 x float> poison, float [[TMP10]], i64 0
+; DAZ-NEXT: [[TMP12:%.*]] = extractelement <2 x float> [[Y]], i64 1
+; DAZ-NEXT: [[TMP13:%.*]] = extractelement <2 x float> [[DENOM]], i64 1
+; DAZ-NEXT: [[TMP14:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[TMP12]], float [[TMP13]])
+; DAZ-NEXT: [[ARCP1:%.*]] = insertelement <2 x float> [[TMP11]], float [[TMP14]], i64 1
+; DAZ-NEXT: store volatile <2 x float> [[ARCP0]], ptr addrspace(1) [[OUT]], align 8
+; DAZ-NEXT: store volatile <2 x float> [[ARCP1]], ptr addrspace(1) [[OUT]], align 8
+; DAZ-NEXT: ret void
+;
+ %denom = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %sqr.denom), !fpmath !3
+ %arcp0 = fdiv arcp <2 x float> %x, %denom, !fpmath !0
+ %arcp1 = fdiv arcp <2 x float> %y, %denom, !fpmath !0
+ store volatile <2 x float> %arcp0, ptr addrspace(1) %out
+ store volatile <2 x float> %arcp1, ptr addrspace(1) %out
+ ret void
+}
+
+define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_25ulp_x3(ptr addrspace(1) %out, float %x, float %y, float %z, float %sqr.denom) {
+; IEEE-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_25ulp_x3
+; IEEE-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]], float [[SQR_DENOM:%.*]]) #[[ATTR1]] {
+; IEEE-NEXT: [[DENOM:%.*]] = call float @llvm.sqrt.f32(float [[SQR_DENOM]]), !fpmath [[META3]]
+; IEEE-NEXT: [[ARCP0:%.*]] = fdiv arcp float [[X]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: [[ARCP1:%.*]] = fdiv arcp float [[Y]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: [[ARCP2:%.*]] = fdiv arcp float [[Z]], [[DENOM]], !fpmath [[META0]]
+; IEEE-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: store volatile float [[ARCP2]], ptr addrspace(1) [[OUT]], align 4
+; IEEE-NEXT: ret void
+;
+; DAZ-LABEL: define amdgpu_kernel void @multiple_arcp_fdiv_sqrt_denom_25ulp_x3
+; DAZ-SAME: (ptr addrspace(1) [[OUT:%.*]], float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]], float [[SQR_DENOM:%.*]]) #[[ATTR1]] {
+; DAZ-NEXT: [[DENOM:%.*]] = call float @llvm.sqrt.f32(float [[SQR_DENOM]]), !fpmath [[META3]]
+; DAZ-NEXT: [[ARCP0:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[X]], float [[DENOM]])
+; DAZ-NEXT: [[ARCP1:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[Y]], float [[DENOM]])
+; DAZ-NEXT: [[ARCP2:%.*]] = call arcp float @llvm.amdgcn.fdiv.fast(float [[Z]], float [[DENOM]])
+; DAZ-NEXT: store volatile float [[ARCP0]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: store volatile float [[ARCP1]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: store volatile float [[ARCP2]], ptr addrspace(1) [[OUT]], align 4
+; DAZ-NEXT: ret void
+;
+ %denom = call float @llvm.sqrt.f32(float %sqr.denom), !fpmath !3
+ %arcp0 = fdiv arcp float %x, %denom, !fpmath !0
+ %arcp1 = fdiv arcp float %y, %denom, !fpmath !0
+ %arcp2 = fdiv arcp float %z, %denom, !fpmath !0
+ store volatile float %arcp0, ptr addrspace(1) %out
+ store volatile float %arcp1, ptr addrspace(1) %out
+ store volatile float %arcp2, ptr addrspace(1) %out
+ ret void
+}
+
+declare float @llvm.sqrt.f32(float)
+declare float @llvm.fabs.f32(float)
+declare <2 x float> @llvm.sqrt.v2f32(<2 x float>)
+declare void @llvm.assume(i1 noundef)
+
+attributes #0 = { optnone noinline }
!0 = !{float 2.500000e+00}
!1 = !{float 5.000000e-01}
!2 = !{float 1.000000e+00}
!3 = !{float 3.000000e+00}
+;.
+; CHECK: [[META0]] = !{float 2.500000e+00}
+; CHECK: [[META2]] = !{float 1.000000e+00}
+;.
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; IEEE-BADFREXP: {{.*}}
+; IEEE-GOODFREXP: {{.*}}