[llvm-branch-commits] [llvm] InstCombine: Add baseline tests for sqrt SimplifyDemandedFPClass (PR #173882)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 6 12:34:54 PST 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/173882

>From 89d7d666e3e5c77e39055a6597ac08d9f90b9d8d Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 23 Dec 2025 20:39:02 +0100
Subject: [PATCH] InstCombine: Add baseline tests for sqrt
 SimplifyDemandedFPClass

---
 .../simplify-demanded-fpclass-sqrt.ll         | 308 ++++++++++++++++++
 1 file changed, 308 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll

diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
new file mode 100644
index 0000000000000..447b3786109ee
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -0,0 +1,308 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare float @func()
+
+declare nofpclass(ninf nnorm nsub nzero nan) float @returns_positive()
+declare nofpclass(ninf nnorm nsub nzero) float @returns_positive_or_nan()
+
+declare nofpclass(pinf pnorm psub pzero nan) float @returns_negative()
+declare nofpclass(pinf pnorm psub pzero) float @returns_negative_or_nan()
+
+declare nofpclass(pinf pnorm psub zero nan) float @returns_negative_nonzero()
+declare nofpclass(pinf pnorm psub zero nan) <2 x float> @returns_negative_nonzero_vec()
+declare nofpclass(pinf pnorm psub zero) float @returns_negative_nonzero_or_nan()
+
+
+; -> qnan
+define nofpclass(inf norm sub zero) float @ret_only_nan_sqrt(float %x) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan_sqrt(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+; -> copysign(0, x)
+; https://alive2.llvm.org/ce/z/ab5wX8
+define nofpclass(inf nan norm sub) float @ret_only_zero_sqrt(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero_sqrt(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub) float @ret_only_zero_sqrt_preserve_flags(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero_sqrt_preserve_flags(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call ninf float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call ninf float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub) float @ret_only_zero_sqrt_nsz(float %x) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero_sqrt_nsz(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %result = call nsz float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(inf nan norm sub) <2 x float> @ret_only_zero_sqrt_vec(<2 x float> %x) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) <2 x float> @ret_only_zero_sqrt_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    ret <2 x float> [[RESULT]]
+;
+  %result = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x)
+  ret <2 x float> %result
+}
+
+; -> pinf
+define nofpclass(nan norm sub zero) float @ret_only_inf_sqrt(float %x) {
+; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf_sqrt(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    ret float 0x7FF0000000000000
+;
+  %result = call float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(norm sub zero) float @ret_only_inf_nan_sqrt(float %x) {
+; CHECK-LABEL: define nofpclass(zero sub norm) float @ret_only_inf_nan_sqrt(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+; Could still be -0
+define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative() {
+; CHECK-LABEL: define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[KNOWN_NEGATIVE]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative = call float @returns_negative()
+  %result = call float @llvm.sqrt.f32(float %known.negative)
+  ret float %result
+}
+
+; -> qnan
+define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero() {
+; CHECK-LABEL: define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_NONZERO:%.*]] = call float @returns_negative_nonzero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[KNOWN_NEGATIVE_NONZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.nonzero = call float @returns_negative_nonzero()
+  %result = call float @llvm.sqrt.f32(float %known.negative.nonzero)
+  ret float %result
+}
+
+; -> qnan
+define nofpclass(ninf) <2 x float> @ret_only_ninf__sqrt__known_negative_nonzero_vec() {
+; CHECK-LABEL: define nofpclass(ninf) <2 x float> @ret_only_ninf__sqrt__known_negative_nonzero_vec() {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_NONZERO:%.*]] = call <2 x float> @returns_negative_nonzero_vec()
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[KNOWN_NEGATIVE_NONZERO]])
+; CHECK-NEXT:    ret <2 x float> [[RESULT]]
+;
+  %known.negative.nonzero = call <2 x float> @returns_negative_nonzero_vec()
+  %result = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %known.negative.nonzero)
+  ret <2 x float> %result
+}
+
+; The negative subnormal may be flushed to -0, which returns a non-nan result.
+define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero_daz() #0 {
+; CHECK-LABEL: define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero_daz(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_NONZERO:%.*]] = call float @returns_negative_nonzero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[KNOWN_NEGATIVE_NONZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.nonzero = call float @returns_negative_nonzero()
+  %result = call float @llvm.sqrt.f32(float %known.negative.nonzero)
+  ret float %result
+}
+
+; The negative subnormal may be flushed to -0, which returns a non-nan result.
+define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero_dynamic() #1 {
+; CHECK-LABEL: define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero_dynamic(
+; CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_NONZERO:%.*]] = call float @returns_negative_nonzero()
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[KNOWN_NEGATIVE_NONZERO]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.nonzero = call float @returns_negative_nonzero()
+  %result = call float @llvm.sqrt.f32(float %known.negative.nonzero)
+  ret float %result
+}
+
+; Cannot fold select. Demanded nan results demand negative inputs.
+define nofpclass(inf norm zero) float @ret_only_nan_or_sub__sqrt__select_unknown_or_known_neg_nonzero(i1 %cond, float %x) {
+; CHECK-LABEL: define nofpclass(inf zero norm) float @ret_only_nan_or_sub__sqrt__select_unknown_or_known_neg_nonzero(
+; CHECK-SAME: i1 [[COND:%.*]], float [[X:%.*]]) {
+; CHECK-NEXT:    [[KNOWN_NEGATIVE_NONZERO:%.*]] = call float @returns_negative_nonzero()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[KNOWN_NEGATIVE_NONZERO]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %known.negative.nonzero = call float @returns_negative_nonzero()
+  %select = select i1 %cond, float %x, float %known.negative.nonzero
+  %result = call float @llvm.sqrt.f32(float %select)
+  ret float %result
+}
+
+; Cannot fold select. Demanded nan results permits negative infinity
+define nofpclass(inf norm zero) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_ninf(i1 %cond, float nofpclass(nan) %x) {
+; CHECK-LABEL: define nofpclass(inf zero norm) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_ninf(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[X:%.*]]) {
+; CHECK-NEXT:    [[MAYBE_NINF:%.*]] = call nofpclass(nan pinf sub norm) float @func()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[MAYBE_NINF]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %maybe.ninf = call nofpclass(pinf norm sub nan) float @func()
+  %select = select i1 %cond, float %x, float %maybe.ninf
+  %result = call float @llvm.sqrt.f32(float %select)
+  ret float %result
+}
+
+; Cannot fold select. Demanded nan results permits negative normals
+define nofpclass(inf norm zero) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_nnorm(i1 %cond, float nofpclass(nan) %x) {
+; CHECK-LABEL: define nofpclass(inf zero norm) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_nnorm(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[X:%.*]]) {
+; CHECK-NEXT:    [[MAYBE_NNORM:%.*]] = call nofpclass(nan inf sub pnorm) float @func()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[MAYBE_NNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %maybe.nnorm = call nofpclass(inf pnorm sub nan) float @func()
+  %select = select i1 %cond, float %x, float %maybe.nnorm
+  %result = call float @llvm.sqrt.f32(float %select)
+  ret float %result
+}
+
+; Cannot fold select. Demanded nan results permits negative subnormals
+define nofpclass(inf norm zero) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_nsub(i1 %cond, float nofpclass(nan) %x) {
+; CHECK-LABEL: define nofpclass(inf zero norm) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_nsub(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[X:%.*]]) {
+; CHECK-NEXT:    [[MAYBE_NSUB:%.*]] = call nofpclass(nan inf psub norm) float @func()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[MAYBE_NSUB]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %maybe.nsub = call nofpclass(inf norm psub nan) float @func()
+  %select = select i1 %cond, float %x, float %maybe.nsub
+  %result = call float @llvm.sqrt.f32(float %select)
+  ret float %result
+}
+
+; -> sqrt
+define nofpclass(pinf) float @no_pinf_result_implies_no_pinf_source(i1 %cond, float %unknown) {
+; CHECK-LABEL: define nofpclass(pinf) float @no_pinf_result_implies_no_pinf_source(
+; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float 0x7FF0000000000000
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %select = select i1 %cond, float %unknown, float 0x7ff0000000000000
+  %result = call float @llvm.sqrt.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan inf zero sub nnorm) float @pnorm_result_demands_pnorm_source(i1 %cond, float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @pnorm_result_demands_pnorm_source(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[ONLY_PNORM:%.*]] = call nofpclass(nan inf zero sub nnorm) float @func()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NOT_NAN]], float [[ONLY_PNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
+  %select = select i1 %cond, float %not.nan, float %only.pnorm
+  %result = call float @llvm.sqrt.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan inf zero sub nnorm) float @pnorm_result_demands_psub_source(i1 %cond, float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @pnorm_result_demands_psub_source(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[ONLY_PSUB:%.*]] = call nofpclass(nan inf zero nsub norm) float @func()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NOT_NAN]], float [[ONLY_PSUB]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %only.psub = call nofpclass(nan inf norm nsub zero) float @func()
+  %select = select i1 %cond, float %not.nan, float %only.psub
+  %result = call float @llvm.sqrt.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan inf zero nsub norm) float @psub_result_implies_not_pnorm_source(i1 %cond, float nofpclass(nan) %not.nan) {
+; CHECK-LABEL: define nofpclass(nan inf zero nsub norm) float @psub_result_implies_not_pnorm_source(
+; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) {
+; CHECK-NEXT:    [[ONLY_PNORM:%.*]] = call nofpclass(nan inf zero sub nnorm) float @func()
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[NOT_NAN]], float [[ONLY_PNORM]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
+  %select = select i1 %cond, float %not.nan, float %only.pnorm
+  %result = call float @llvm.sqrt.f32(float %select)
+  ret float %result
+}
+
+define nofpclass(nan) float @ret_no_nan__sqrt(float %x) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__sqrt(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call contract float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(snan) float @ret_no_snan__sqrt__no_neg_inputs(float nofpclass(ninf nnorm nsub) %x) {
+; CHECK-LABEL: define nofpclass(snan) float @ret_no_snan__sqrt__no_neg_inputs(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call contract float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+define nofpclass(snan) float @ret_no_snan__sqrt__no_neg_or_nan_inputs(float nofpclass(nan ninf nnorm nsub) %x) {
+; CHECK-LABEL: define nofpclass(snan) float @ret_no_snan__sqrt__no_neg_or_nan_inputs(
+; CHECK-SAME: float nofpclass(nan ninf nsub nnorm) [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call contract float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+; Need to drop noundef to add nnan flag
+define nofpclass(snan) float @ret_no_snan__noundef_sqrt__no_neg_or_nan_inputs(float nofpclass(nan ninf nnorm nsub) %x) {
+; CHECK-LABEL: define nofpclass(snan) float @ret_no_snan__noundef_sqrt__no_neg_or_nan_inputs(
+; CHECK-SAME: float nofpclass(nan ninf nsub nnorm) [[X:%.*]]) {
+; CHECK-NEXT:    [[RESULT:%.*]] = call contract noundef float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    ret float [[RESULT]]
+;
+  %result = call contract noundef float @llvm.sqrt.f32(float %x)
+  ret float %result
+}
+
+attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }
+attributes #1 = { "denormal-fp-math"="dynamic,dynamic" }



More information about the llvm-branch-commits mailing list