https://github.com/c-rhodes updated https://github.com/llvm/llvm-project/pull/178866
>From 6299a3229101c635261c54f5aeb7b83348a3509c Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Fri, 30 Jan 2026 11:48:36 +0100 Subject: [PATCH] ValueTracking: Revert noundef checks in computeKnownFPClass for fmul/fma (#178850) This functionally reverts fd5cfcc41311c6287e9dc408b8aae499501660e1 and 35ce17b6f6ca5dd321af8e6763554b10824e4ac4. This was correct and necessary, but is causing performance regressions since isGuaranteedNotToBeUndef is apparently not smart enough to detect through recurrences. Revert this for the release branch. Also the test coverage was inadequate for the fma case, so add a new case which changes with and without the check. (cherry picked from commit 07ec2fa1443ccd3cbb55612937f1dddebfe51c15) --- llvm/lib/Analysis/ValueTracking.cpp | 9 +++-- .../Transforms/Attributor/nofpclass-fma.ll | 34 ++++++++++++++++--- .../Transforms/Attributor/nofpclass-fmul.ll | 2 +- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index ab64156e2d173..e893dcb50cded 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5108,9 +5108,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, if ((InterestedClasses & fcNegative) == fcNone) break; - if (II->getArgOperand(0) != II->getArgOperand(1) || - !isGuaranteedNotToBeUndef(II->getArgOperand(0), Q.AC, Q.CxtI, Q.DT, - Depth + 1)) + // FIXME: This should check isGuaranteedNotToBeUndef + if (II->getArgOperand(0) != II->getArgOperand(1)) break; // The multiply cannot be -0 and therefore the add can't be -0 @@ -5589,8 +5588,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, : DenormalMode::getDynamic(); // X * X is always non-negative or a NaN. - if (Op->getOperand(0) == Op->getOperand(1) && - isGuaranteedNotToBeUndef(Op->getOperand(0), Q.AC, Q.CxtI, Q.DT)) { + // FIXME: Should check isGuaranteedNotToBeUndef + if (Op->getOperand(0) == Op->getOperand(1)) { KnownFPClass KnownSrc; computeKnownFPClass(Op->getOperand(0), DemandedElts, fcAllFlags, KnownSrc, Q, Depth + 1); diff --git a/llvm/test/Transforms/Attributor/nofpclass-fma.ll b/llvm/test/Transforms/Attributor/nofpclass-fma.ll index 877057c4fadc3..d30e0dab240ec 100644 --- a/llvm/test/Transforms/Attributor/nofpclass-fma.ll +++ b/llvm/test/Transforms/Attributor/nofpclass-fma.ll @@ -4,6 +4,8 @@ declare float @llvm.fma.f32(float, float, float) declare float @llvm.fmuladd.f32(float, float, float) +declare nofpclass(ninf nzero nsub nnorm) half @returns_positive_or_nan() + define float @ret_fma_same_mul_arg(float noundef %arg0, float %arg1) { ; CHECK-LABEL: define nofpclass(nzero) float @ret_fma_same_mul_arg ; CHECK-SAME: (float noundef [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1:[0-9]+]] { @@ -15,9 +17,9 @@ define float @ret_fma_same_mul_arg(float noundef %arg0, float %arg1) { } define float @ret_fma_same_mul_arg_maybe_undef(float %arg0, float %arg1) { -; CHECK-LABEL: define float @ret_fma_same_mul_arg_maybe_undef +; CHECK-LABEL: define nofpclass(nzero) float @ret_fma_same_mul_arg_maybe_undef ; CHECK-SAME: (float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.fma.f32(float [[ARG0]], float [[ARG0]], float [[ARG1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero) float @llvm.fma.f32(float [[ARG0]], float [[ARG0]], float [[ARG1]]) #[[ATTR2]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg1) @@ -55,9 +57,9 @@ define float @ret_fmuladd_same_mul_arg(float noundef %arg0, float %arg1) { } define float @ret_fmuladd_same_mul_arg_maybe_undef(float %arg0, float %arg1) { -; CHECK-LABEL: define float @ret_fmuladd_same_mul_arg_maybe_undef +; CHECK-LABEL: define nofpclass(nzero) float @ret_fmuladd_same_mul_arg_maybe_undef ; CHECK-SAME: (float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.fmuladd.f32(float [[ARG0]], float [[ARG0]], float [[ARG1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero) float @llvm.fmuladd.f32(float [[ARG0]], float [[ARG0]], float [[ARG1]]) #[[ATTR2]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.fmuladd.f32(float %arg0, float %arg0, float %arg1) @@ -74,5 +76,29 @@ define float @ret_fmuladd_different_same_arg_positive_addend(float noundef %arg0 ret float %call } +define half @ret_fma__square_maybe_undef__pos2(half %unknown) { +; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fma__square_maybe_undef__pos2 +; CHECK-SAME: (half [[UNKNOWN:%.*]]) { +; CHECK-NEXT: [[POS2:%.*]] = call half @returns_positive_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fma.f16(half [[UNKNOWN]], half [[UNKNOWN]], half [[POS2]]) +; CHECK-NEXT: ret half [[RESULT]] +; + %pos2 = call half @returns_positive_or_nan() + %result = call half @llvm.fma.f16(half %unknown, half %unknown, half %pos2) + ret half %result +} + +define half @ret_fma__square__pos2(half noundef %unknown) { +; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fma__square__pos2 +; CHECK-SAME: (half noundef [[UNKNOWN:%.*]]) { +; CHECK-NEXT: [[POS2:%.*]] = call half @returns_positive_or_nan() +; CHECK-NEXT: [[RESULT:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fma.f16(half noundef [[UNKNOWN]], half noundef [[UNKNOWN]], half [[POS2]]) +; CHECK-NEXT: ret half [[RESULT]] +; + %pos2 = call half @returns_positive_or_nan() + %result = call half @llvm.fma.f16(half %unknown, half %unknown, half %pos2) + ret half %result +} + ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: ; TUNIT: {{.*}} diff --git a/llvm/test/Transforms/Attributor/nofpclass-fmul.ll b/llvm/test/Transforms/Attributor/nofpclass-fmul.ll index 57c6f1de6abb2..ce75db2f41fca 100644 --- a/llvm/test/Transforms/Attributor/nofpclass-fmul.ll +++ b/llvm/test/Transforms/Attributor/nofpclass-fmul.ll @@ -25,7 +25,7 @@ define float @ret_fmul_square_f32(float noundef %arg) { } define float @ret_fmul_square_f32_maybe_undef(float %arg) { -; CHECK-LABEL: define float @ret_fmul_square_f32_maybe_undef( +; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_fmul_square_f32_maybe_undef( ; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FMUL]] _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
