[llvm-branch-commits] [llvm] InstCombine: Add baseline tests for exp SimplifyDemandedFPClass (PR #173431)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 29 05:46:48 PST 2025
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/173431
>From 373b0b5e1c76d283084eeb35f9fda91767cd79cd Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sat, 20 Dec 2025 21:30:35 +0100
Subject: [PATCH] InstCombine: Add baseline tests for exp
SimplifyDemandedFPClass
---
.../simplify-demanded-fpclass-exp.ll | 502 ++++++++++++++++++
1 file changed, 502 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-exp.ll
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-exp.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-exp.ll
new file mode 100644
index 0000000000000..7706d2de68f16
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-exp.ll
@@ -0,0 +1,502 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+define nofpclass(pinf) float @ret_nofpclass_pinf__exp2_select_maybe_inf_or_not_pinf(i1 %cond, float %maybe.inf, float nofpclass(pinf) %not.pinf) {
+; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__exp2_select_maybe_inf_or_not_pinf(
+; CHECK-SAME: i1 [[COND:%.*]], float [[MAYBE_INF:%.*]], float nofpclass(pinf) [[NOT_PINF:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MAYBE_INF]], float [[NOT_PINF]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %maybe.inf, float %not.pinf
+ %exp = call float @llvm.exp2.f32(float %select)
+ ret float %exp
+}
+
+define nofpclass(ninf) float @ret_nofpclass_ninf__exp2_select_maybe_inf_or_not_pinf(i1 %cond, float %maybe.inf, float nofpclass(pinf) %not.pinf) {
+; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__exp2_select_maybe_inf_or_not_pinf(
+; CHECK-SAME: i1 [[COND:%.*]], float [[MAYBE_INF:%.*]], float nofpclass(pinf) [[NOT_PINF:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MAYBE_INF]], float [[NOT_PINF]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %maybe.inf, float %not.pinf
+ %exp = call float @llvm.exp2.f32(float %select)
+ ret float %exp
+}
+
+define nofpclass(ninf) float @ret_nofpclass_ninf__exp2_select_maybe_inf_or_not_ninf(i1 %cond, float %maybe.inf, float nofpclass(ninf) %not.ninf) {
+; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__exp2_select_maybe_inf_or_not_ninf(
+; CHECK-SAME: i1 [[COND:%.*]], float [[MAYBE_INF:%.*]], float nofpclass(ninf) [[NOT_NINF:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MAYBE_INF]], float [[NOT_NINF]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %maybe.inf, float %not.ninf
+ %exp = call float @llvm.exp2.f32(float %select)
+ ret float %exp
+}
+
+; Negative test
+define nofpclass(nan) float @ret_nofpclass_nan__exp2_select_maybe_inf_or_not_nan(i1 %cond, float %maybe.nan, float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__exp2_select_maybe_inf_or_not_nan(
+; CHECK-SAME: i1 [[COND:%.*]], float [[MAYBE_NAN:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MAYBE_NAN]], float [[NOT_NAN]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %maybe.nan, float %not.nan
+ %exp = call float @llvm.exp2.f32(float %select)
+ ret float %exp
+}
+
+; Fold to only exp2
+define nofpclass(nan) float @ret_nofpclass_nan__exp2_select_maybe_inf_or_nan(i1 %cond, float %maybe.nan, float nofpclass(inf zero sub norm) %only.nan) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__exp2_select_maybe_inf_or_nan(
+; CHECK-SAME: i1 [[COND:%.*]], float [[MAYBE_NAN:%.*]], float nofpclass(inf zero sub norm) [[ONLY_NAN:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MAYBE_NAN]], float [[ONLY_NAN]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %maybe.nan, float %only.nan
+ %exp = call float @llvm.exp2.f32(float %select)
+ ret float %exp
+}
+
+; Only need to propagate nan inputs, so fold to ret %x
+define nofpclass(pinf zero psub pnorm) float @ret_nofpclass_no_positives__exp2(float %x) {
+; CHECK-LABEL: define nofpclass(pinf zero psub pnorm) float @ret_nofpclass_no_positives__exp2(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[X]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %x)
+ ret float %exp
+}
+
+; No positive results or nans, so fold to poison.
+define nofpclass(nan pinf zero psub pnorm) float @ret_nofpclass_no_positives_no_nan__exp2(float %x) {
+; CHECK-LABEL: define nofpclass(nan pinf zero psub pnorm) float @ret_nofpclass_no_positives_no_nan__exp2(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: ret float poison
+;
+ %exp = call float @llvm.exp2.f32(float %x)
+ ret float %exp
+}
+
+; Can fold this for nan propagation, don't need -0
+define nofpclass(pzero pinf psub pnorm) float @ret_nofpclass_no_positives_except_neg0__exp2(float %x) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives_except_neg0__exp2(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[X]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %x)
+ ret float %exp
+}
+
+; -0 isn't returnable, fold to poison
+define nofpclass(pzero pinf psub pnorm nan) float @ret_nofpclass_no_positives_except_neg0_no_nan__exp2(float %x) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_except_neg0_no_nan__exp2(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: ret float poison
+;
+ %exp = call float @llvm.exp2.f32(float %x)
+ ret float %exp
+}
+
+; Can't fold this, values near 0 return 1.
+define nofpclass(nzero pinf psub pnorm) float @ret_nofpclass_no_positives_except_pos0__exp2(float %x) {
+; CHECK-LABEL: define nofpclass(pinf nzero psub pnorm) float @ret_nofpclass_no_positives_except_pos0__exp2(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[X]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %x)
+ ret float %exp
+}
+
+; Can't fold this, values near 0 return 1.
+define nofpclass(pinf psub pnorm) float @ret_nofpclass_no_positives_except_0__exp2(float %x) {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @ret_nofpclass_no_positives_except_0__exp2(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[X]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %x)
+ ret float %exp
+}
+
+; check exp intrinsic is handled
+define nofpclass(nan) float @handle_exp(i1 %cond, float %maybe.nan, float nofpclass(inf zero sub norm) %only.nan) {
+; CHECK-LABEL: define nofpclass(nan) float @handle_exp(
+; CHECK-SAME: i1 [[COND:%.*]], float [[MAYBE_NAN:%.*]], float nofpclass(inf zero sub norm) [[ONLY_NAN:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MAYBE_NAN]], float [[ONLY_NAN]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %maybe.nan, float %only.nan
+ %exp = call float @llvm.exp.f32(float %select)
+ ret float %exp
+}
+
+; check exp10 intrinsic is handled
+define nofpclass(nan) float @handle_exp10(i1 %cond, float %maybe.nan, float nofpclass(inf zero sub norm) %only.nan) {
+; CHECK-LABEL: define nofpclass(nan) float @handle_exp10(
+; CHECK-SAME: i1 [[COND:%.*]], float [[MAYBE_NAN:%.*]], float nofpclass(inf zero sub norm) [[ONLY_NAN:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MAYBE_NAN]], float [[ONLY_NAN]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp10.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %maybe.nan, float %only.nan
+ %exp = call float @llvm.exp10.f32(float %select)
+ ret float %exp
+}
+
+; zero or sub result implies the input must be normal, so excludes the
+; second select source.
+define nofpclass(inf norm nan) float @ret_nofpclass_only_subzero__exp2_select_unknown_or_not_norm(i1 %cond, float %unknown, float nofpclass(norm) %not.norm) {
+; CHECK-LABEL: define nofpclass(nan inf norm) float @ret_nofpclass_only_subzero__exp2_select_unknown_or_not_norm(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(norm) [[NOT_NORM:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[NOT_NORM]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %unknown, float %not.norm
+ %exp = call float @llvm.exp2.f32(float %select)
+ ret float %exp
+}
+
+define nofpclass(inf norm nan zero) float @ret_nofpclass_only_sub__exp2_select_unknown_or_not_norm(i1 %cond, float %unknown, float nofpclass(norm) %not.norm) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) float @ret_nofpclass_only_sub__exp2_select_unknown_or_not_norm(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(norm) [[NOT_NORM:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[NOT_NORM]]
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[SELECT]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %select = select i1 %cond, float %unknown, float %not.norm
+ %exp = call float @llvm.exp2.f32(float %select)
+ ret float %exp
+}
+
+define nofpclass(inf norm nan sub) float @ret_nofpclass_only_zero__exp2_select_unknown_or_not_norm(i1 %cond, float %unknown, float nofpclass(norm) %not.norm) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_nofpclass_only_zero__exp2_select_unknown_or_not_norm(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(norm) [[NOT_NORM:%.*]]) {
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %select = select i1 %cond, float %unknown, float %not.norm
+ %exp = call float @llvm.exp2.f32(float %select)
+ ret float %exp
+}
+
+; Result only permits +inf or nan. The source value forbids pinf, but
+; the possible pnorm value could overflow, so this should not fold to
+; return poison.
+define nofpclass(ninf norm zero sub) float @pinf_result_implies_pnorm_source(float nofpclass(pinf nan) %maybe.pnorm) {
+; CHECK-LABEL: define nofpclass(ninf zero sub norm) float @pinf_result_implies_pnorm_source(
+; CHECK-SAME: float nofpclass(nan pinf) [[MAYBE_PNORM:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_PNORM]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.pnorm)
+ ret float %exp
+}
+
+define nofpclass(ninf norm zero sub) float @pinf_result_implies_pnorm_source_nan(float nofpclass(pinf) %maybe.pnorm.or.nan) {
+; CHECK-LABEL: define nofpclass(ninf zero sub norm) float @pinf_result_implies_pnorm_source_nan(
+; CHECK-SAME: float nofpclass(pinf) [[MAYBE_PNORM_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_PNORM_OR_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.pnorm.or.nan)
+ ret float %exp
+}
+
+define nofpclass(pinf norm zero sub) float @ninf_result_implies_poison(float nofpclass(ninf nan) %maybe.nnorm) {
+; CHECK-LABEL: define nofpclass(pinf zero sub norm) float @ninf_result_implies_poison(
+; CHECK-SAME: float nofpclass(nan ninf) [[MAYBE_NNORM:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_NNORM]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.nnorm)
+ ret float %exp
+}
+
+; Cannot fold to poison
+define nofpclass(inf norm nan sub) float @zero_result_implies_nnorm_source_valid(float nofpclass(pnorm sub nan) %maybe.nnorm) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @zero_result_implies_nnorm_source_valid(
+; CHECK-SAME: float nofpclass(nan sub pnorm) [[MAYBE_NNORM:%.*]]) {
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.nnorm)
+ ret float %exp
+}
+
+define nofpclass(inf norm nan sub) float @zero_result_implies_nnorm_source_valid_nan(float nofpclass(pnorm sub) %maybe.nnorm.or.nan) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @zero_result_implies_nnorm_source_valid_nan(
+; CHECK-SAME: float nofpclass(sub pnorm) [[MAYBE_NNORM_OR_NAN:%.*]]) {
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.nnorm.or.nan)
+ ret float %exp
+}
+
+; Cannot fold to poison
+define nofpclass(inf norm nan sub) float @zero_result_implies_nsub_source_valid(float nofpclass(norm psub nan) %maybe.nsub) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @zero_result_implies_nsub_source_valid(
+; CHECK-SAME: float nofpclass(nan psub norm) [[MAYBE_NSUB:%.*]]) {
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.nsub)
+ ret float %exp
+}
+
+define nofpclass(inf norm nan sub) float @zero_result_implies_nsub_source_valid_nan(float nofpclass(norm psub) %maybe.nsub.or.nan) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @zero_result_implies_nsub_source_valid_nan(
+; CHECK-SAME: float nofpclass(psub norm) [[MAYBE_NSUB_OR_NAN:%.*]]) {
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.nsub.or.nan)
+ ret float %exp
+}
+
+; Cannot fold to poison
+define nofpclass(inf norm nan zero) float @sub_result_implies_nnorm_source_valid(float nofpclass(pnorm sub nan) %maybe.nnorm) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) float @sub_result_implies_nnorm_source_valid(
+; CHECK-SAME: float nofpclass(nan sub pnorm) [[MAYBE_NNORM:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_NNORM]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.nnorm)
+ ret float %exp
+}
+
+; Cannot fold to poison
+define nofpclass(inf norm nan zero) float @sub_result_implies_nsub_source_valid(float nofpclass(norm psub nan) %maybe.nsub) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) float @sub_result_implies_nsub_source_valid(
+; CHECK-SAME: float nofpclass(nan psub norm) [[MAYBE_NSUB:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_NSUB]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.nsub)
+ ret float %exp
+}
+
+define nofpclass(inf norm nan sub) float @zero_result_implies_pnorm_source_valid(float nofpclass(nnorm sub nan) %maybe.pnorm) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @zero_result_implies_pnorm_source_valid(
+; CHECK-SAME: float nofpclass(nan sub nnorm) [[MAYBE_PNORM:%.*]]) {
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.pnorm)
+ ret float %exp
+}
+
+define nofpclass(inf norm nan sub) float @zero_result_implies_pnorm_source_valid_nan(float nofpclass(nnorm sub) %maybe.pnorm.or.nan) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @zero_result_implies_pnorm_source_valid_nan(
+; CHECK-SAME: float nofpclass(sub nnorm) [[MAYBE_PNORM_OR_NAN:%.*]]) {
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.pnorm.or.nan)
+ ret float %exp
+}
+
+define nofpclass(inf norm nan zero) float @sub_result_implies_pnorm_source_valid(float nofpclass(pnorm sub nan) %maybe.pnorm) {
+; CHECK-LABEL: define nofpclass(nan inf zero norm) float @sub_result_implies_pnorm_source_valid(
+; CHECK-SAME: float nofpclass(nan sub pnorm) [[MAYBE_PNORM:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_PNORM]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.pnorm)
+ ret float %exp
+}
+
+define nofpclass(inf nnorm nan zero) float @pnorm_result_implies_possible_0_source(float nofpclass(pnorm sub) %maybe.zero.or.nan) {
+; CHECK-LABEL: define nofpclass(nan inf zero nnorm) float @pnorm_result_implies_possible_0_source(
+; CHECK-SAME: float nofpclass(sub pnorm) [[MAYBE_ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_ZERO_OR_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.zero.or.nan)
+ ret float %exp
+}
+
+define nofpclass(inf nnorm nan zero sub) float @pnorm_result_implies_possible_0_source_no_inf(float nofpclass(inf norm sub) %maybe.zero.or.nan) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @pnorm_result_implies_possible_0_source_no_inf(
+; CHECK-SAME: float nofpclass(inf sub norm) [[MAYBE_ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_ZERO_OR_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.zero.or.nan)
+ ret float %exp
+}
+
+define nofpclass(inf nnorm nan zero sub) float @pnorm_result_implies_possible_sub_source(float nofpclass(inf norm zero) %maybe.sub.or.nan) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @pnorm_result_implies_possible_sub_source(
+; CHECK-SAME: float nofpclass(inf zero norm) [[MAYBE_SUB_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MAYBE_SUB_OR_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %maybe.sub.or.nan)
+ ret float %exp
+}
+
+; FIXME: Does not happen unless nofpclass set on return value.
+define nofpclass(pzero) float @source_is_known_zero(float nofpclass(nan inf norm sub) %must.be.zero) {
+; CHECK-LABEL: define nofpclass(pzero) float @source_is_known_zero(
+; CHECK-SAME: float nofpclass(nan inf sub norm) [[MUST_BE_ZERO:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_ZERO]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.zero)
+ ret float %exp
+}
+
+define nofpclass(pzero) <2 x float> @source_is_known_zero_vec(<2 x float> nofpclass(nan inf norm sub) %must.be.zero) {
+; CHECK-LABEL: define nofpclass(pzero) <2 x float> @source_is_known_zero_vec(
+; CHECK-SAME: <2 x float> nofpclass(nan inf sub norm) [[MUST_BE_ZERO:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUST_BE_ZERO]])
+; CHECK-NEXT: ret <2 x float> [[EXP]]
+;
+ %exp = call <2 x float> @llvm.exp2.v2f32(<2 x float> %must.be.zero)
+ ret <2 x float> %exp
+}
+
+define nofpclass(pzero) float @source_is_known_pzero(float nofpclass(nan inf norm sub nzero) %must.be.pzero) {
+; CHECK-LABEL: define nofpclass(pzero) float @source_is_known_pzero(
+; CHECK-SAME: float nofpclass(nan inf nzero sub norm) [[MUST_BE_PZERO:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_PZERO]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.pzero)
+ ret float %exp
+}
+
+define nofpclass(pzero) float @source_is_known_nzero(float nofpclass(nan inf norm sub pzero) %must.be.nzero) {
+; CHECK-LABEL: define nofpclass(pzero) float @source_is_known_nzero(
+; CHECK-SAME: float nofpclass(nan inf pzero sub norm) [[MUST_BE_NZERO:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_NZERO]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.nzero)
+ ret float %exp
+}
+
+define nofpclass(nzero) float @source_is_known_inf(float nofpclass(nan norm sub zero) %must.be.inf) {
+; CHECK-LABEL: define nofpclass(nzero) float @source_is_known_inf(
+; CHECK-SAME: float nofpclass(nan zero sub norm) [[MUST_BE_INF:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_INF]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.inf)
+ ret float %exp
+}
+
+define nofpclass(nzero) <2 x float> @source_is_known_inf_vec(<2 x float> nofpclass(nan norm sub zero) %must.be.inf) {
+; CHECK-LABEL: define nofpclass(nzero) <2 x float> @source_is_known_inf_vec(
+; CHECK-SAME: <2 x float> nofpclass(nan zero sub norm) [[MUST_BE_INF:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUST_BE_INF]])
+; CHECK-NEXT: ret <2 x float> [[EXP]]
+;
+ %exp = call <2 x float> @llvm.exp2.v2f32(<2 x float> %must.be.inf)
+ ret <2 x float> %exp
+}
+
+define nofpclass(nzero) float @source_is_known_pinf(float nofpclass(ninf nan norm sub zero) %must.be.pinf) {
+; CHECK-LABEL: define nofpclass(nzero) float @source_is_known_pinf(
+; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_PINF]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.pinf)
+ ret float %exp
+}
+
+define nofpclass(nzero) float @source_is_known_ninf(float nofpclass(pinf nan norm sub zero) %must.be.ninf) {
+; CHECK-LABEL: define nofpclass(nzero) float @source_is_known_ninf(
+; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_NINF]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.ninf)
+ ret float %exp
+}
+
+define nofpclass(nzero) float @source_is_known_nan(float nofpclass(inf norm sub zero) %must.be.nan) {
+; CHECK-LABEL: define nofpclass(nzero) float @source_is_known_nan(
+; CHECK-SAME: float nofpclass(inf zero sub norm) [[MUST_BE_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.nan)
+ ret float %exp
+}
+
+define nofpclass(nzero) float @source_is_known_inf_or_nan(float nofpclass(norm sub zero) %must.be.inf.or.nan) {
+; CHECK-LABEL: define nofpclass(nzero) float @source_is_known_inf_or_nan(
+; CHECK-SAME: float nofpclass(zero sub norm) [[MUST_BE_INF_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_INF_OR_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.inf.or.nan)
+ ret float %exp
+}
+
+define nofpclass(nzero nan) float @source_is_known_inf_or_nan__nnan_result(float nofpclass(norm sub zero) %must.be.inf.or.nan) {
+; CHECK-LABEL: define nofpclass(nan nzero) float @source_is_known_inf_or_nan__nnan_result(
+; CHECK-SAME: float nofpclass(zero sub norm) [[MUST_BE_INF_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_INF_OR_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.inf.or.nan)
+ ret float %exp
+}
+
+define nofpclass(pzero) float @source_is_known_zero_or_nan(float nofpclass(inf norm sub) %must.be.zero.or.nan) {
+; CHECK-LABEL: define nofpclass(pzero) float @source_is_known_zero_or_nan(
+; CHECK-SAME: float nofpclass(inf sub norm) [[MUST_BE_ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_ZERO_OR_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.zero.or.nan)
+ ret float %exp
+}
+
+define nofpclass(pzero) <2 x float> @source_is_known_zero_or_nan_vec(<2 x float> nofpclass(inf norm sub) %must.be.zero.or.nan) {
+; CHECK-LABEL: define nofpclass(pzero) <2 x float> @source_is_known_zero_or_nan_vec(
+; CHECK-SAME: <2 x float> nofpclass(inf sub norm) [[MUST_BE_ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUST_BE_ZERO_OR_NAN]])
+; CHECK-NEXT: ret <2 x float> [[EXP]]
+;
+ %exp = call <2 x float> @llvm.exp2.v2f32(<2 x float> %must.be.zero.or.nan)
+ ret <2 x float> %exp
+}
+
+define nofpclass(nzero) float @source_is_known_snan(float nofpclass(inf norm sub zero qnan) %must.be.snan) {
+; CHECK-LABEL: define nofpclass(nzero) float @source_is_known_snan(
+; CHECK-SAME: float nofpclass(qnan inf zero sub norm) [[MUST_BE_SNAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_SNAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.snan)
+ ret float %exp
+}
+
+define nofpclass(nzero) float @source_is_known_qnan(float nofpclass(inf norm sub zero snan) %must.be.qnan) {
+; CHECK-LABEL: define nofpclass(nzero) float @source_is_known_qnan(
+; CHECK-SAME: float nofpclass(snan inf zero sub norm) [[MUST_BE_QNAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_QNAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.qnan)
+ ret float %exp
+}
+
+define nofpclass(pzero nan) float @source_is_known_zero_or_nan__nnan_result(float nofpclass(inf norm sub) %must.be.zero.or.nan) {
+; CHECK-LABEL: define nofpclass(nan pzero) float @source_is_known_zero_or_nan__nnan_result(
+; CHECK-SAME: float nofpclass(inf sub norm) [[MUST_BE_ZERO_OR_NAN:%.*]]) {
+; CHECK-NEXT: [[EXP:%.*]] = call float @llvm.exp2.f32(float [[MUST_BE_ZERO_OR_NAN]])
+; CHECK-NEXT: ret float [[EXP]]
+;
+ %exp = call float @llvm.exp2.f32(float %must.be.zero.or.nan)
+ ret float %exp
+}
More information about the llvm-branch-commits
mailing list