[llvm] 4be3df8 - ValueTracking: Add baseline test for fmul denormal scaling handling (#171729)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 11 04:06:13 PST 2025
Author: Matt Arsenault
Date: 2025-12-11T13:06:08+01:00
New Revision: 4be3df8cf1392249b199ec30c0e30b1958f251d7
URL: https://github.com/llvm/llvm-project/commit/4be3df8cf1392249b199ec30c0e30b1958f251d7
DIFF: https://github.com/llvm/llvm-project/commit/4be3df8cf1392249b199ec30c0e30b1958f251d7.diff
LOG: ValueTracking: Add baseline test for fmul denormal scaling handling (#171729)
Added:
llvm/test/Transforms/Attributor/nofpclass-fmul.ll
Modified:
Removed:
################################################################################
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fmul.ll b/llvm/test/Transforms/Attributor/nofpclass-fmul.ll
new file mode 100644
index 0000000000000..6d0edf0681ed4
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/nofpclass-fmul.ll
@@ -0,0 +1,288 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal < %s | FileCheck %s
+
+; Test that multiply by a constant with a sufficiently large exponent
+; proves the result is not subnormal.
+
+define float @ret_fmul_f32(float %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fmul_f32(
+; CHECK-SAME: float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
+; CHECK-NEXT: ret float [[FMUL]]
+;
+ %fmul = fmul float %arg0, %arg1
+ ret float %fmul
+}
+
+define float @ret_fmul_square_f32(float %arg) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_fmul_square_f32(
+; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[ARG]], [[ARG]]
+; CHECK-NEXT: ret float [[FMUL]]
+;
+ %fmul = fmul float %arg, %arg
+ ret float %fmul
+}
+
+define float @ret_mul_exponent_f32_22(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_exponent_f32_22(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x4150000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x4150000000000000
+ ret float %call
+}
+
+define float @ret_mul_exponent_f32_23(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_exponent_f32_23(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x4160000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x4160000000000000
+ ret float %call
+}
+
+define float @ret_mul_exponent_f32_24(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_exponent_f32_24(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x4170000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x4170000000000000
+ ret float %call
+}
+
+define float @ret_mul_exponent_f32_23_nnan(float nofpclass(nan) %arg0) {
+; CHECK-LABEL: define nofpclass(nan) float @ret_mul_exponent_f32_23_nnan(
+; CHECK-SAME: float nofpclass(nan) [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x4160000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x4160000000000000
+ ret float %call
+}
+
+define double @ret_mul_exponent_f64_24(double %arg0) {
+; CHECK-LABEL: define double @ret_mul_exponent_f64_24(
+; CHECK-SAME: double [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul double [[ARG0]], 0x4170000000000000
+; CHECK-NEXT: ret double [[CALL]]
+;
+ %call = fmul double %arg0, 0x4170000000000000
+ ret double %call
+}
+
+define double @ret_mul_exponent_f64_51(double %arg0) {
+; CHECK-LABEL: define double @ret_mul_exponent_f64_51(
+; CHECK-SAME: double [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul double [[ARG0]], 0x4320000000000000
+; CHECK-NEXT: ret double [[CALL]]
+;
+ %call = fmul double %arg0, 0x4320000000000000
+ ret double %call
+}
+
+define double @ret_mul_exponent_f64_52(double %arg0) {
+; CHECK-LABEL: define double @ret_mul_exponent_f64_52(
+; CHECK-SAME: double [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul double [[ARG0]], 0x4330000000000000
+; CHECK-NEXT: ret double [[CALL]]
+;
+ %call = fmul double %arg0, 0x4330000000000000
+ ret double %call
+}
+
+define double @ret_mul_exponent_f64_53(double %arg0) {
+; CHECK-LABEL: define double @ret_mul_exponent_f64_53(
+; CHECK-SAME: double [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul double [[ARG0]], 0x4340000000000000
+; CHECK-NEXT: ret double [[CALL]]
+;
+ %call = fmul double %arg0, 0x4340000000000000
+ ret double %call
+}
+
+define half @ret_mul_exponent_f16_8(half %arg0) {
+; CHECK-LABEL: define half @ret_mul_exponent_f16_8(
+; CHECK-SAME: half [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul half [[ARG0]], 0xH5C00
+; CHECK-NEXT: ret half [[CALL]]
+;
+ %call = fmul half %arg0, 0xH5C00
+ ret half %call
+}
+
+define half @ret_mul_exponent_f16_9(half %arg0) {
+; CHECK-LABEL: define half @ret_mul_exponent_f16_9(
+; CHECK-SAME: half [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul half [[ARG0]], 0xH6000
+; CHECK-NEXT: ret half [[CALL]]
+;
+ %call = fmul half %arg0, 0xH6000
+ ret half %call
+}
+
+define half @ret_mul_exponent_f16_10(half %arg0) {
+; CHECK-LABEL: define half @ret_mul_exponent_f16_10(
+; CHECK-SAME: half [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul half [[ARG0]], 0xH6400
+; CHECK-NEXT: ret half [[CALL]]
+;
+ %call = fmul half %arg0, 0xH6400
+ ret half %call
+}
+
+define bfloat @ret_mul_exponent_bf16_6(bfloat %arg0) {
+; CHECK-LABEL: define bfloat @ret_mul_exponent_bf16_6(
+; CHECK-SAME: bfloat [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul bfloat [[ARG0]], 0xR4280
+; CHECK-NEXT: ret bfloat [[CALL]]
+;
+ %call = fmul bfloat %arg0, 0xR4280
+ ret bfloat %call
+}
+
+define bfloat @ret_mul_exponent_bf16_7(bfloat %arg0) {
+; CHECK-LABEL: define bfloat @ret_mul_exponent_bf16_7(
+; CHECK-SAME: bfloat [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul bfloat [[ARG0]], 0xR4300
+; CHECK-NEXT: ret bfloat [[CALL]]
+;
+ %call = fmul bfloat %arg0, 0xR4300
+ ret bfloat %call
+}
+
+define bfloat @ret_mul_exponent_bf16_8(bfloat %arg0) {
+; CHECK-LABEL: define bfloat @ret_mul_exponent_bf16_8(
+; CHECK-SAME: bfloat [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul bfloat [[ARG0]], 0xR4380
+; CHECK-NEXT: ret bfloat [[CALL]]
+;
+ %call = fmul bfloat %arg0, 0xR4380
+ ret bfloat %call
+}
+
+define float @ret_mul_exponent_f32_neg22(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_exponent_f32_neg22(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3E90000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x3E90000000000000
+ ret float %call
+}
+
+define float @ret_mul_exponent_f32_neg23(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_exponent_f32_neg23(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3E80000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x3E80000000000000
+ ret float %call
+}
+
+define float @ret_mul_exponent_f32_neg24(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_exponent_f32_neg24(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3E70000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x3E70000000000000
+ ret float %call
+}
+
+define float @ret_mul_exponent_f32_neg126(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_exponent_f32_neg126(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3810000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x3810000000000000
+ ret float %call
+}
+
+define float @ret_mul_exponent_f32_neg127(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_exponent_f32_neg127(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x3800000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x3800000000000000
+ ret float %call
+}
+
+define <2 x float> @ret_mul_exponent_v2f32_splat_23(<2 x float> %arg0) {
+; CHECK-LABEL: define <2 x float> @ret_mul_exponent_v2f32_splat_23(
+; CHECK-SAME: <2 x float> [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul <2 x float> [[ARG0]], splat (float 0x4160000000000000)
+; CHECK-NEXT: ret <2 x float> [[CALL]]
+;
+ %call = fmul <2 x float> %arg0, splat (float 0x4160000000000000)
+ ret <2 x float> %call
+}
+
+define <2 x float> @ret_mul_exponent_v2f32_splat_poison_23(<2 x float> %arg0) {
+; CHECK-LABEL: define <2 x float> @ret_mul_exponent_v2f32_splat_poison_23(
+; CHECK-SAME: <2 x float> [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul <2 x float> [[ARG0]], <float 0x4160000000000000, float poison>
+; CHECK-NEXT: ret <2 x float> [[CALL]]
+;
+ %call = fmul <2 x float> %arg0, <float 0x4160000000000000, float poison>
+ ret <2 x float> %call
+}
+
+; TODO: Should be able to prove nofpclass(sub)
+define <2 x float> @ret_mul_exponent_v2f32_nonsplat(<2 x float> %arg0) {
+; CHECK-LABEL: define <2 x float> @ret_mul_exponent_v2f32_nonsplat(
+; CHECK-SAME: <2 x float> [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul <2 x float> [[ARG0]], <float 0x4160000000000000, float 0x4170000000000000>
+; CHECK-NEXT: ret <2 x float> [[CALL]]
+;
+ %call = fmul <2 x float> %arg0, <float 0x4160000000000000, float 0x4170000000000000>
+ ret <2 x float> %call
+}
+
+; Cannot prove this is not-subnormal
+define <2 x float> @ret_mul_partially_foldable_exponent_v2f32(<2 x float> %arg0) {
+; CHECK-LABEL: define <2 x float> @ret_mul_partially_foldable_exponent_v2f32(
+; CHECK-SAME: <2 x float> [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul <2 x float> [[ARG0]], <float 0x4160000000000000, float 0x4150000000000000>
+; CHECK-NEXT: ret <2 x float> [[CALL]]
+;
+ %call = fmul <2 x float> %arg0, <float 0x4160000000000000, float 0x4150000000000000>
+ ret <2 x float> %call
+}
+
+define float @ret_mul_f32_0(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_f32_0(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0.000000e+00
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0.0
+ ret float %call
+}
+
+define float @ret_mul_f32_inf(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_f32_inf(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x7FF0000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x7FF0000000000000
+ ret float %call
+}
+
+define float @ret_mul_f32_nan(float %arg0) {
+; CHECK-LABEL: define float @ret_mul_f32_nan(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[CALL:%.*]] = fmul float [[ARG0]], 0x7FF8000000000000
+; CHECK-NEXT: ret float [[CALL]]
+;
+ %call = fmul float %arg0, 0x7FF8000000000000
+ ret float %call
+}
+
More information about the llvm-commits
mailing list