CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
753 lines
32 KiB
LLVM
753 lines
32 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: opt -S -p=instcombine < %s | FileCheck %s
|
|
|
|
; Test a special pattern wrapping llvm.canonicalize which has weaker
|
|
; requirements for nan behavior.
|
|
|
|
; Base pattern with no denormal flushing, should fold to direct use of
|
|
; %x
|
|
define float @canonicalize_ieee_0(float %x) #0 {
|
|
; CHECK-LABEL: define float @canonicalize_ieee_0(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Commuted pattern, should fold to direct use of %x
|
|
define float @canonicalize_ieee_1(float %x) #0 {
|
|
; CHECK-LABEL: define float @canonicalize_ieee_1(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%uno = fcmp uno float %x, 0.0
|
|
%x.canon = select i1 %uno, float %soft.canonical, float %hard.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Would be OK, but instcombine will delete the no-op fmul before
|
|
; reaching the select.
|
|
define float @canonicalize_ieee_0_fmul(float %x) #0 {
|
|
; CHECK-LABEL: define float @canonicalize_ieee_0_fmul(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fmul float %x, 1.0
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Commuted fdiv would be OK, but instcombine will delete the no-op
|
|
; fmul before reaching the select.
|
|
define float @canonicalize_ieee_0_fdiv_commute(float %x) #0 {
|
|
; CHECK-LABEL: define float @canonicalize_ieee_0_fdiv_commute(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float %x, 1.0
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Base pattern with denormal flushing, should fold to single
|
|
; canonicalize call.
|
|
define float @canonicalize_daz_0(float %x) #1 {
|
|
; CHECK-LABEL: define float @canonicalize_daz_0(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR1:[0-9]+]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[HARD_CANONICAL]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Commuted pattern with denormal flushing, should fold to single
|
|
; canonicalize call.
|
|
define float @canonicalize_daz_1(float %x) #1 {
|
|
; CHECK-LABEL: define float @canonicalize_daz_1(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: ret float [[HARD_CANONICAL]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%uno = fcmp uno float %x, 0.0
|
|
%x.canon = select i1 %uno, float %soft.canonical, float %hard.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Unknown denormal mode can fold to canonicalize call
|
|
define float @canonicalize_dynamic_0(float %x) #2 {
|
|
; CHECK-LABEL: define float @canonicalize_dynamic_0(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR2:[0-9]+]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Unknown denormal mode can fold to canonicalize call
|
|
define float @canonicalize_dynamic_1(float %x) #2 {
|
|
; CHECK-LABEL: define float @canonicalize_dynamic_1(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR2]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], float [[SOFT_CANONICAL]], float [[HARD_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%uno = fcmp uno float %x, 0.0
|
|
%x.canon = select i1 %uno, float %soft.canonical, float %hard.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
define <2 x float> @canonicalize_ieee_0_vec(<2 x float> %x) #0 {
|
|
; CHECK-LABEL: define <2 x float> @canonicalize_ieee_0_vec(
|
|
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret <2 x float> [[X]]
|
|
;
|
|
%hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
|
|
%soft.canonical = fdiv <2 x float> splat (float 1.0), %x
|
|
%ord = fcmp ord <2 x float> %x, zeroinitializer
|
|
%x.canon = select <2 x i1> %ord, <2 x float> %hard.canonical, <2 x float> %soft.canonical
|
|
ret <2 x float> %x.canon
|
|
}
|
|
|
|
define <2 x float> @canonicalize_ieee_1_vec(<2 x float> %x) #0 {
|
|
; CHECK-LABEL: define <2 x float> @canonicalize_ieee_1_vec(
|
|
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret <2 x float> [[X]]
|
|
;
|
|
%hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
|
|
%soft.canonical = fdiv <2 x float> splat (float 1.0), %x
|
|
%uno = fcmp uno <2 x float> %x, zeroinitializer
|
|
%x.canon = select <2 x i1> %uno, <2 x float> %soft.canonical, <2 x float> %hard.canonical
|
|
ret <2 x float> %x.canon
|
|
}
|
|
|
|
define <2 x float> @canonicalize_ieee_0_vec_poison_elt(<2 x float> %x) #0 {
|
|
; CHECK-LABEL: define <2 x float> @canonicalize_ieee_0_vec_poison_elt(
|
|
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv <2 x float> <float 1.000000e+00, float poison>, [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord <2 x float> [[X]], zeroinitializer
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select <2 x i1> [[ORD]], <2 x float> [[X]], <2 x float> [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret <2 x float> [[X_CANON]]
|
|
;
|
|
%hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
|
|
%soft.canonical = fdiv <2 x float> <float 1.0, float poison>, %x
|
|
%ord = fcmp ord <2 x float> %x, zeroinitializer
|
|
%x.canon = select <2 x i1> %ord, <2 x float> %hard.canonical, <2 x float> %soft.canonical
|
|
ret <2 x float> %x.canon
|
|
}
|
|
|
|
define <2 x float> @canonicalize_daz_0_vec(<2 x float> %x) #1 {
|
|
; CHECK-LABEL: define <2 x float> @canonicalize_daz_0_vec(
|
|
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[X]])
|
|
; CHECK-NEXT: ret <2 x float> [[HARD_CANONICAL]]
|
|
;
|
|
%hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
|
|
%soft.canonical = fdiv <2 x float> splat (float 1.0), %x
|
|
%ord = fcmp ord <2 x float> %x, zeroinitializer
|
|
%x.canon = select <2 x i1> %ord, <2 x float> %hard.canonical, <2 x float> %soft.canonical
|
|
ret <2 x float> %x.canon
|
|
}
|
|
|
|
define <2 x float> @canonicalize_daz_1_vec(<2 x float> %x) #1 {
|
|
; CHECK-LABEL: define <2 x float> @canonicalize_daz_1_vec(
|
|
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[X]])
|
|
; CHECK-NEXT: ret <2 x float> [[HARD_CANONICAL]]
|
|
;
|
|
%hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
|
|
%soft.canonical = fdiv <2 x float> splat (float 1.0), %x
|
|
%uno = fcmp uno <2 x float> %x, zeroinitializer
|
|
%x.canon = select <2 x i1> %uno, <2 x float> %soft.canonical, <2 x float> %hard.canonical
|
|
ret <2 x float> %x.canon
|
|
}
|
|
|
|
define bfloat @canonicalize_ieee_bf16(bfloat %x) #0 {
|
|
; CHECK-LABEL: define bfloat @canonicalize_ieee_bf16(
|
|
; CHECK-SAME: bfloat [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret bfloat [[X]]
|
|
;
|
|
%hard.canonical = call bfloat @llvm.canonicalize.bf16(bfloat %x)
|
|
%soft.canonical = fdiv bfloat 1.0, %x
|
|
%ord = fcmp ord bfloat %x, 0.0
|
|
%x.canon = select i1 %ord, bfloat %hard.canonical, bfloat %soft.canonical
|
|
ret bfloat %x.canon
|
|
}
|
|
|
|
define half @canonicalize_ieee_f16(half %x) #0 {
|
|
; CHECK-LABEL: define half @canonicalize_ieee_f16(
|
|
; CHECK-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret half [[X]]
|
|
;
|
|
%hard.canonical = call half @llvm.canonicalize.f16(half %x)
|
|
%soft.canonical = fdiv half 1.0, %x
|
|
%ord = fcmp ord half %x, 0.0
|
|
%x.canon = select i1 %ord, half %hard.canonical, half %soft.canonical
|
|
ret half %x.canon
|
|
}
|
|
|
|
define double @canonicalize_ieee_f64(double %x) #0 {
|
|
; CHECK-LABEL: define double @canonicalize_ieee_f64(
|
|
; CHECK-SAME: double [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret double [[X]]
|
|
;
|
|
%hard.canonical = call double @llvm.canonicalize.f64(double %x)
|
|
%soft.canonical = fdiv double 1.0, %x
|
|
%ord = fcmp ord double %x, 0.0
|
|
%x.canon = select i1 %ord, double %hard.canonical, double %soft.canonical
|
|
ret double %x.canon
|
|
}
|
|
|
|
define fp128 @canonicalize_ieee_f128(fp128 %x) #0 {
|
|
; CHECK-LABEL: define fp128 @canonicalize_ieee_f128(
|
|
; CHECK-SAME: fp128 [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret fp128 [[X]]
|
|
;
|
|
%hard.canonical = call fp128 @llvm.canonicalize.f128(fp128 %x)
|
|
%ord = fcmp ord fp128 %x, 0xL00000000000000000000000000000000
|
|
%x.canon = select i1 %ord, fp128 %hard.canonical, fp128 %x
|
|
ret fp128 %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @div_not_one(float %x) #0 {
|
|
; CHECK-LABEL: define float @div_not_one(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 2.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[X]], float [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 2.0, %x
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @not_fdiv(float %x) #0 {
|
|
; CHECK-LABEL: define float @not_fdiv(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fadd float [[X]], 1.000000e+00
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[X]], float [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fadd float %x, 1.0
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @fcmp_not_ord(float %x) #0 {
|
|
; CHECK-LABEL: define float @fcmp_not_ord(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp olt float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp olt float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
declare float @func(float)
|
|
|
|
; Negative test
|
|
define float @not_canonicalize(float %x) #0 {
|
|
; CHECK-LABEL: define float @not_canonicalize(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[X_FR:%.*]] = freeze float [[X]]
|
|
; CHECK-NEXT: [[NOT_CANONICAL:%.*]] = call noundef float @func(float [[X_FR]])
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X_FR]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[NOT_CANONICAL]], float [[X_FR]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%not.canonical = call noundef float @func(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %not.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @compared_value_different(float %x, float %y) #0 {
|
|
; CHECK-LABEL: define float @compared_value_different(
|
|
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[Y]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %y, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @fdiv_value_different_ieee(float %x, float %y) #0 {
|
|
; CHECK-LABEL: define float @fdiv_value_different_ieee(
|
|
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[Y]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[X]], float [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %y
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @fdiv_value_different_ieee_commute(float %x, float %y) #0 {
|
|
; CHECK-LABEL: define float @fdiv_value_different_ieee_commute(
|
|
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[Y]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp uno float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[SOFT_CANONICAL]], float [[X]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %y
|
|
%ord = fcmp uno float %x, 0.0
|
|
%x.canon = select i1 %ord, float %soft.canonical, float %hard.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @fdiv_value_different_daz(float %x, float %y) #1 {
|
|
; CHECK-LABEL: define float @fdiv_value_different_daz(
|
|
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[Y]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %y
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @fdiv_value_different_daz_commute(float %x, float %y) #1 {
|
|
; CHECK-LABEL: define float @fdiv_value_different_daz_commute(
|
|
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[Y]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp uno float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[SOFT_CANONICAL]], float [[HARD_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %y
|
|
%ord = fcmp uno float %x, 0.0
|
|
%x.canon = select i1 %ord, float %soft.canonical, float %hard.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @fcmp_ord_not_constant(float %x, float %y) #0 {
|
|
; CHECK-LABEL: define float @fcmp_ord_not_constant(
|
|
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], [[Y]]
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %x, %y
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test
|
|
define float @fcmp_ord_nan_constant(float %x) #0 {
|
|
; CHECK-LABEL: define float @fcmp_ord_nan_constant(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: ret float [[SOFT_CANONICAL]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %x, 0x7FF8000000000000
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
define x86_fp80 @ignore_x86_fp80(x86_fp80 %x) #0 {
|
|
; CHECK-LABEL: define x86_fp80 @ignore_x86_fp80(
|
|
; CHECK-SAME: x86_fp80 [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call x86_fp80 @llvm.canonicalize.f80(x86_fp80 [[X]])
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord x86_fp80 [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], x86_fp80 [[HARD_CANONICAL]], x86_fp80 [[X]]
|
|
; CHECK-NEXT: ret x86_fp80 [[X_CANON]]
|
|
;
|
|
%hard.canonical = call x86_fp80 @llvm.canonicalize.f80(x86_fp80 %x)
|
|
%ord = fcmp ord x86_fp80 %x, 0xK00000000000000000000
|
|
%x.canon = select i1 %ord, x86_fp80 %hard.canonical, x86_fp80 %x
|
|
ret x86_fp80 %x.canon
|
|
}
|
|
|
|
define ppc_fp128 @ignore_ppc_fp128(ppc_fp128 %x) #0 {
|
|
; CHECK-LABEL: define ppc_fp128 @ignore_ppc_fp128(
|
|
; CHECK-SAME: ppc_fp128 [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call ppc_fp128 @llvm.canonicalize.ppcf128(ppc_fp128 [[X]])
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord ppc_fp128 [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], ppc_fp128 [[HARD_CANONICAL]], ppc_fp128 [[X]]
|
|
; CHECK-NEXT: ret ppc_fp128 [[X_CANON]]
|
|
;
|
|
%hard.canonical = call ppc_fp128 @llvm.canonicalize.ppcf128(ppc_fp128 %x)
|
|
%ord = fcmp ord ppc_fp128 %x, 0xM00000000000000000000000000000000
|
|
%x.canon = select i1 %ord, ppc_fp128 %hard.canonical, ppc_fp128 %x
|
|
ret ppc_fp128 %x.canon
|
|
}
|
|
|
|
; In IEEE mode there are no non-canonical values, we can drop the canonicalize.
|
|
define float @canonicalize_ieee_0_missing_noop(float %x) #0 {
|
|
; CHECK-LABEL: define float @canonicalize_ieee_0_missing_noop(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %x
|
|
ret float %x.canon
|
|
}
|
|
|
|
; In IEEE mode there are no non-canonical values, we can drop the
|
|
; canonicalize.
|
|
define float @canonicalize_ieee_1_missing_noop(float %x) #0 {
|
|
; CHECK-LABEL: define float @canonicalize_ieee_1_missing_noop(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%uno = fcmp uno float %x, 0.0
|
|
%x.canon = select i1 %uno, float %x, float %hard.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test. This cannot fold to the canonicalize call, as it may
|
|
; change the payload and sign bit of %x in the nan case.
|
|
define float @canonicalize_da_0_missing_noop(float %x) #1 {
|
|
; CHECK-LABEL: define float @canonicalize_da_0_missing_noop(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[X]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %x
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Negative test. This cannot fold to the canonicalize call, as it may
|
|
; change the payload and sign bit of %x in the nan case.
|
|
define float @canonicalize_daz_1_missing_noop(float %x) #1 {
|
|
; CHECK-LABEL: define float @canonicalize_daz_1_missing_noop(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], float [[X]], float [[HARD_CANONICAL]]
|
|
; CHECK-NEXT: ret float [[X_CANON]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%uno = fcmp uno float %x, 0.0
|
|
%x.canon = select i1 %uno, float %x, float %hard.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Either input or output is sufficient to require canonicalize
|
|
define float @canonicalize_only_ftz(float %x) "denormal-fp-math"="preserve-sign,ieee" {
|
|
; CHECK-LABEL: define float @canonicalize_only_ftz(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR3:[0-9]+]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Either input or output is sufficient to require canonicalize
|
|
define float @canonicalize_only_daz(float %x) "denormal-fp-math"="ieee,preserve-sign" {
|
|
; CHECK-LABEL: define float @canonicalize_only_daz(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR4:[0-9]+]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%soft.canonical = fdiv float 1.0, %x
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %soft.canonical
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Both components must be IEEE to fully drop the canonicalize
|
|
define float @canonicalize_missing_noop_only_ftz(float %x) "denormal-fp-math"="preserve-sign,ieee" {
|
|
; CHECK-LABEL: define float @canonicalize_missing_noop_only_ftz(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %x
|
|
ret float %x.canon
|
|
}
|
|
|
|
; Both components must be IEEE to fully drop the canonicalize
|
|
define float @canonicalize_missing_noop_only_daz(float %x) "denormal-fp-math"="ieee,preserve-sign" {
|
|
; CHECK-LABEL: define float @canonicalize_missing_noop_only_daz(
|
|
; CHECK-SAME: float [[X:%.*]]) #[[ATTR4]] {
|
|
; CHECK-NEXT: ret float [[X]]
|
|
;
|
|
%hard.canonical = call float @llvm.canonicalize.f32(float %x)
|
|
%ord = fcmp ord float %x, 0.0
|
|
%x.canon = select i1 %ord, float %hard.canonical, float %x
|
|
ret float %x.canon
|
|
}
|
|
|
|
define half @independent_hands_canonicalize_ieee_0(half noundef %x, half %y) #0 {
|
|
; CHECK-LABEL: define half @independent_hands_canonicalize_ieee_0(
|
|
; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[X]], half [[Y]]
|
|
; CHECK-NEXT: ret half [[X_CANON]]
|
|
;
|
|
%hard.canonical = call half @llvm.canonicalize.f16(half %x)
|
|
%ord = fcmp ord half %x, 0.0
|
|
%x.canon = select i1 %ord, half %hard.canonical, half %y
|
|
ret half %x.canon
|
|
}
|
|
|
|
define half @independent_hands_canonicalize_ieee_1(half noundef %x, half %y) #0 {
|
|
; CHECK-LABEL: define half @independent_hands_canonicalize_ieee_1(
|
|
; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[X]]
|
|
; CHECK-NEXT: ret half [[X_CANON]]
|
|
;
|
|
%hard.canonical = call half @llvm.canonicalize.f16(half %x)
|
|
%uno = fcmp uno half %x, 0.0
|
|
%x.canon = select i1 %uno, half %y, half %hard.canonical
|
|
ret half %x.canon
|
|
}
|
|
|
|
define half @independent_hands_fdiv_ieee_0(half noundef %x, half %y) #0 {
|
|
; CHECK-LABEL: define half @independent_hands_fdiv_ieee_0(
|
|
; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[X]]
|
|
; CHECK-NEXT: ret half [[SEL]]
|
|
;
|
|
%rcp = fdiv half 1.0, %x
|
|
%ord = fcmp ord half %x, 0.0
|
|
%sel = select i1 %ord, half %y, half %rcp
|
|
ret half %sel
|
|
}
|
|
|
|
define half @independent_hands_fdiv_ieee_1(half noundef %x, half %y) #0 {
|
|
; CHECK-LABEL: define half @independent_hands_fdiv_ieee_1(
|
|
; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[X]], half [[Y]]
|
|
; CHECK-NEXT: ret half [[SEL]]
|
|
;
|
|
%rcp = fdiv half 1.0, %x
|
|
%uno = fcmp uno half %x, 0.0
|
|
%sel = select i1 %uno, half %rcp, half %y
|
|
ret half %sel
|
|
}
|
|
|
|
define half @independent_hands_canonicalize_daz_0(half noundef %x, half %y) #1 {
|
|
; CHECK-LABEL: define half @independent_hands_canonicalize_daz_0(
|
|
; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]])
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[HARD_CANONICAL]], half [[Y]]
|
|
; CHECK-NEXT: ret half [[X_CANON]]
|
|
;
|
|
%hard.canonical = call half @llvm.canonicalize.f16(half %x)
|
|
%ord = fcmp ord half %x, 0.0
|
|
%x.canon = select i1 %ord, half %hard.canonical, half %y
|
|
ret half %x.canon
|
|
}
|
|
|
|
define half @independent_hands_canonicalize_daz_1(half noundef %x, half %y) #1 {
|
|
; CHECK-LABEL: define half @independent_hands_canonicalize_daz_1(
|
|
; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]])
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[HARD_CANONICAL]]
|
|
; CHECK-NEXT: ret half [[X_CANON]]
|
|
;
|
|
%hard.canonical = call half @llvm.canonicalize.f16(half %x)
|
|
%uno = fcmp uno half %x, 0.0
|
|
%x.canon = select i1 %uno, half %y, half %hard.canonical
|
|
ret half %x.canon
|
|
}
|
|
|
|
define half @independent_hands_fdiv_daz_0(half noundef %x, half %y) #1 {
|
|
; CHECK-LABEL: define half @independent_hands_fdiv_daz_0(
|
|
; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[RCP:%.*]] = fdiv half 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[RCP]]
|
|
; CHECK-NEXT: ret half [[SEL]]
|
|
;
|
|
%rcp = fdiv half 1.0, %x
|
|
%ord = fcmp ord half %x, 0.0
|
|
%sel = select i1 %ord, half %y, half %rcp
|
|
ret half %sel
|
|
}
|
|
|
|
define half @independent_hands_fdiv_daz_1(half noundef %x, half %y) #1 {
|
|
; CHECK-LABEL: define half @independent_hands_fdiv_daz_1(
|
|
; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR1]] {
|
|
; CHECK-NEXT: [[RCP:%.*]] = fdiv half 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[RCP]], half [[Y]]
|
|
; CHECK-NEXT: ret half [[SEL]]
|
|
;
|
|
%rcp = fdiv half 1.0, %x
|
|
%uno = fcmp uno half %x, 0.0
|
|
%sel = select i1 %uno, half %rcp, half %y
|
|
ret half %sel
|
|
}
|
|
|
|
define x86_fp80 @independent_hands_canonicalize_ieee_0_x86_fp80(x86_fp80 noundef %x, x86_fp80 %y) #0 {
|
|
; CHECK-LABEL: define x86_fp80 @independent_hands_canonicalize_ieee_0_x86_fp80(
|
|
; CHECK-SAME: x86_fp80 noundef [[X:%.*]], x86_fp80 [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call x86_fp80 @llvm.canonicalize.f80(x86_fp80 [[X]])
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord x86_fp80 [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], x86_fp80 [[HARD_CANONICAL]], x86_fp80 [[Y]]
|
|
; CHECK-NEXT: ret x86_fp80 [[X_CANON]]
|
|
;
|
|
%hard.canonical = call x86_fp80 @llvm.canonicalize.f80(x86_fp80 %x)
|
|
%ord = fcmp ord x86_fp80 %x, 0xK00000000000000000000
|
|
%x.canon = select i1 %ord, x86_fp80 %hard.canonical, x86_fp80 %y
|
|
ret x86_fp80 %x.canon
|
|
}
|
|
|
|
define x86_fp80 @independent_hands_fdiv_ieee_0_x86_fp80(x86_fp80 noundef %x, x86_fp80 %y) #0 {
|
|
; CHECK-LABEL: define x86_fp80 @independent_hands_fdiv_ieee_0_x86_fp80(
|
|
; CHECK-SAME: x86_fp80 noundef [[X:%.*]], x86_fp80 [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[RCP:%.*]] = fdiv x86_fp80 1.000000e+00, [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord x86_fp80 [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], x86_fp80 [[Y]], x86_fp80 [[RCP]]
|
|
; CHECK-NEXT: ret x86_fp80 [[SEL]]
|
|
;
|
|
%rcp = fdiv x86_fp80 0xK3FFF8000000000000000, %x
|
|
%ord = fcmp ord x86_fp80 %x, 0xK00000000000000000000
|
|
%sel = select i1 %ord, x86_fp80 %y, x86_fp80 %rcp
|
|
ret x86_fp80 %sel
|
|
}
|
|
|
|
|
|
; Negative test, needs noundef
|
|
define half @independent_hands_canonicalize_ieee_0_maybe_undef(half %x, half %y) #0 {
|
|
; CHECK-LABEL: define half @independent_hands_canonicalize_ieee_0_maybe_undef(
|
|
; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[X]], half [[Y]]
|
|
; CHECK-NEXT: ret half [[X_CANON]]
|
|
;
|
|
%hard.canonical = call half @llvm.canonicalize.f16(half %x)
|
|
%ord = fcmp ord half %x, 0.0
|
|
%x.canon = select i1 %ord, half %hard.canonical, half %y
|
|
ret half %x.canon
|
|
}
|
|
|
|
; Negative test, needs noundef
|
|
define half @independent_hands_canonicalize_ieee_1_maybe_undef(half %x, half %y) #0 {
|
|
; CHECK-LABEL: define half @independent_hands_canonicalize_ieee_1_maybe_undef(
|
|
; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[X]]
|
|
; CHECK-NEXT: ret half [[X_CANON]]
|
|
;
|
|
%hard.canonical = call half @llvm.canonicalize.f16(half %x)
|
|
%uno = fcmp uno half %x, 0.0
|
|
%x.canon = select i1 %uno, half %y, half %hard.canonical
|
|
ret half %x.canon
|
|
}
|
|
|
|
; Negative test, needs noundef
|
|
define half @independent_hands_fdiv_ieee_0_maybe_undef(half %x, half %y) #0 {
|
|
; CHECK-LABEL: define half @independent_hands_fdiv_ieee_0_maybe_undef(
|
|
; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[X_FR:%.*]] = freeze half [[X]]
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X_FR]], 0.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[X_FR]]
|
|
; CHECK-NEXT: ret half [[SEL]]
|
|
;
|
|
%rcp = fdiv half 1.0, %x
|
|
%ord = fcmp ord half %x, 0.0
|
|
%sel = select i1 %ord, half %y, half %rcp
|
|
ret half %sel
|
|
}
|
|
|
|
; Negative test, needs noundef
|
|
define half @independent_hands_fdiv_ieee_1_maybe_undef(half %x, half %y) #0 {
|
|
; CHECK-LABEL: define half @independent_hands_fdiv_ieee_1_maybe_undef(
|
|
; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[X_FR:%.*]] = freeze half [[X]]
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X_FR]], 0.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[X_FR]], half [[Y]]
|
|
; CHECK-NEXT: ret half [[SEL]]
|
|
;
|
|
%rcp = fdiv half 1.0, %x
|
|
%uno = fcmp uno half %x, 0.0
|
|
%sel = select i1 %uno, half %rcp, half %y
|
|
ret half %sel
|
|
}
|
|
|
|
attributes #0 = { denormal_fpenv(ieee) }
|
|
attributes #1 = { denormal_fpenv(preservesign) }
|
|
attributes #2 = { denormal_fpenv(dynamic) }
|