[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From e2f1df9225a3953e9344ba887c03a631132f8fdd Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 899b52fdc951b..ff1df59b54cf4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2064,9 +2064,9 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2094,6 +2094,29 @@ static FPClassTest
adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
return DemandedMask;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2998,6 +3021,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -3019,7 +3050,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index 0520fef0f0e79..7a05e27d88184 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -214,7 +214,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -228,7 +228,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From e2f1df9225a3953e9344ba887c03a631132f8fdd Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 899b52fdc951b..ff1df59b54cf4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2064,9 +2064,9 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2094,6 +2094,29 @@ static FPClassTest
adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
return DemandedMask;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2998,6 +3021,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -3019,7 +3050,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index 0520fef0f0e79..7a05e27d88184 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -214,7 +214,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -228,7 +228,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 9bdfe6aabfa77e12d19d09f5a9fe558ce336318b Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 31c962dbae502..043896b96921f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2061,9 +2061,9 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2091,6 +2091,29 @@ static FPClassTest
adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
return DemandedMask;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2865,6 +2888,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2886,7 +2917,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 9bdfe6aabfa77e12d19d09f5a9fe558ce336318b Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 31c962dbae502..043896b96921f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2061,9 +2061,9 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2091,6 +2091,29 @@ static FPClassTest
adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
return DemandedMask;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2865,6 +2888,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2886,7 +2917,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 290308872e026304dc598e83153779d5f6245eee Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 1ae0395814fe6..afab0796edaf0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2061,9 +2061,9 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2091,6 +2091,29 @@ static FPClassTest
adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
return DemandedMask;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2821,6 +2844,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2842,7 +2873,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 290308872e026304dc598e83153779d5f6245eee Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 1ae0395814fe6..afab0796edaf0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2061,9 +2061,9 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2091,6 +2091,29 @@ static FPClassTest
adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
return DemandedMask;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2821,6 +2844,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2842,7 +2873,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 4d3dbfe8dc0e49fc6e6d67db09114e1ad1057caa Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 2746671b1b048..6e49fcf7e754c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2061,9 +2061,9 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2091,6 +2091,29 @@ static FPClassTest
adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
return DemandedMask;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2824,6 +2847,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2845,7 +2876,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 4d3dbfe8dc0e49fc6e6d67db09114e1ad1057caa Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 2746671b1b048..6e49fcf7e754c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2061,9 +2061,9 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2091,6 +2091,29 @@ static FPClassTest
adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
return DemandedMask;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2824,6 +2847,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2845,7 +2876,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From d7ada803fcf8772d893dc72db5f55a3c7b9468b0 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3c15400d90b48..5fe889df057bf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,29 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2788,6 +2811,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2809,7 +2840,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From d7ada803fcf8772d893dc72db5f55a3c7b9468b0 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3c15400d90b48..5fe889df057bf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,29 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2788,6 +2811,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2809,7 +2840,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
github-actions[bot] wrote: # :penguin: Linux x64 Test Results * 168128 tests passed * 2995 tests skipped * 2 tests failed ## Failed Tests (click on a test name to see its output) ### LLVM LLVM.CodeGen/PowerPC/peephole-mma-phi-liveness.ll ``` Exit Code: 1 Command Output (stdout): -- # RUN: at line 2 /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc -verify-machineinstrs -mcpu=ppc -mtriple=powerpc64-ibm-aix < /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/PowerPC/peephole-mma-phi-liveness.ll | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/PowerPC/peephole-mma-phi-liveness.ll # executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/llc -verify-machineinstrs -mcpu=ppc -mtriple=powerpc64-ibm-aix # note: command had no output on stdout or stderr # executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/PowerPC/peephole-mma-phi-liveness.ll # .---command stderr # | /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/PowerPC/peephole-mma-phi-liveness.ll:22:15: error: CHECK-NEXT: is not on the line after the previous match # | ; CHECK-NEXT: stxv 2, 0(3) # | ^ # | :28:2: note: 'next' match was here # | stxv 2, 0(3) # | ^ # | :25:19: note: previous match ended here # | xvmaddadp 0, 1, 1 # | ^ # | :26:1: note: non-matching line after previous match is here # | xvadddp 2, 2, 1 # | ^ # | # | Input file: # | Check file: /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/CodeGen/PowerPC/peephole-mma-phi-liveness.ll # | # | -dump-input=help explains the following input dump. # | # | Input was: # | << # | . # | . # | . # | 23: xvmuldp 0, 0, 1 # | 24: xvmaddadp 2, 1, 1 # | 25: xvmaddadp 0, 1, 1 # | 26: xvadddp 2, 2, 1 # | 27: xvadddp 0, 0, 1 # | 28: stxv 2, 0(3) # | next:22 !~~~ error: match on wrong line # | 29: stxv 0, 0(3) # | 30: # implicit-def: $acc0 # | 31: bc 12, 20, L..BB0_2 # | 32: # %bb.1: # %bb10 # | 33: xvf64gerpp 0, 34, 0 # | . # | . # | . # | >> # `- # error: command failed with exit status: 1 -- ``` LLVM.Transforms/InstCombine/fabs.ll ``` Exit Code: 1 Command Output (stdout): -- # RUN: at line 2 /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/opt -mtriple=x86_64-unknown-linux-gnu < /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/Transforms/InstCombine/fabs.ll -passes=instcombine -S | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/Transforms/InstCombine/fabs.ll # executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/opt -mtriple=x86_64-unknown-linux-gnu -passes=instcombine -S # note: command had no output on stdout or stderr # executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/Transforms/InstCombine/fabs.ll # .---command stderr # | /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/Transforms/InstCombine/fabs.ll:210:15: error: CHECK-NEXT: expected string not found in input # | ; CHECK-NEXT: ret float [[FMA]] # | ^ # | :125:78: note: scanning from here # | %fma = call nnan float @llvm.fma.f32(float %x, float %x, float 1.00e+00) # | ^ # | :125:78: note: with "FMA" equal to "%fma" # | %fma = call nnan float @llvm.fma.f32(float %x, float %x, float 1.00e+00) # | ^ # | :127:2: note: possible intended match here # | ret float %fabsf # | ^ # | /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/Transforms/InstCombine/fabs.ll:231:15: error: CHECK-NEXT: expected string not found in input # | ; CHECK-NEXT: ret float [[FMULADD]] # | ^ # | :137:86: note: scanning from here # | %fmuladd = call nnan float @llvm.fmuladd.f32(float %x, float %x, float 1.00e+00) # | ^ # | :137:86: note: with "FMULADD" equal to "%fmuladd" # | %fmuladd = call nnan float @llvm.fmuladd.f32(float %x, float %x, float 1.00e+00) # | ^ # | :139:2: note: possible intended match here # | ret float %fabsf # | ^ # | # | Input file: # | Ch
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
github-actions[bot] wrote: # :window: Windows x64 Test Results * 129520 tests passed * 2866 tests skipped * 2 tests failed ## Failed Tests (click on a test name to see its output) ### LLVM LLVM.CodeGen/PowerPC/peephole-mma-phi-liveness.ll ``` Exit Code: 1 Command Output (stdout): -- # RUN: at line 2 c:\_work\llvm-project\llvm-project\build\bin\llc.exe -verify-machineinstrs -mcpu=ppc -mtriple=powerpc64-ibm-aix < C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\PowerPC\peephole-mma-phi-liveness.ll | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\PowerPC\peephole-mma-phi-liveness.ll # executed command: 'c:\_work\llvm-project\llvm-project\build\bin\llc.exe' -verify-machineinstrs -mcpu=ppc -mtriple=powerpc64-ibm-aix # note: command had no output on stdout or stderr # executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' 'C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\PowerPC\peephole-mma-phi-liveness.ll' # .---command stderr # | C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\PowerPC\peephole-mma-phi-liveness.ll:22:15: error: CHECK-NEXT: is not on the line after the previous match # | ; CHECK-NEXT: stxv 2, 0(3) # | ^ # | :28:2: note: 'next' match was here # | stxv 2, 0(3) # | ^ # | :25:19: note: previous match ended here # | xvmaddadp 0, 1, 1 # | ^ # | :26:1: note: non-matching line after previous match is here # | xvadddp 2, 2, 1 # | ^ # | # | Input file: # | Check file: C:\_work\llvm-project\llvm-project\llvm\test\CodeGen\PowerPC\peephole-mma-phi-liveness.ll # | # | -dump-input=help explains the following input dump. # | # | Input was: # | << # | . # | . # | . # | 23: xvmuldp 0, 0, 1 # | 24: xvmaddadp 2, 1, 1 # | 25: xvmaddadp 0, 1, 1 # | 26: xvadddp 2, 2, 1 # | 27: xvadddp 0, 0, 1 # | 28: stxv 2, 0(3) # | next:22 !~~~ error: match on wrong line # | 29: stxv 0, 0(3) # | 30: # implicit-def: $acc0 # | 31: bc 12, 20, L..BB0_2 # | 32: # %bb.1: # %bb10 # | 33: xvf64gerpp 0, 34, 0 # | . # | . # | . # | >> # `- # error: command failed with exit status: 1 -- ``` LLVM.Transforms/InstCombine/fabs.ll ``` Exit Code: 1 Command Output (stdout): -- # RUN: at line 2 c:\_work\llvm-project\llvm-project\build\bin\opt.exe -mtriple=x86_64-unknown-linux-gnu < C:\_work\llvm-project\llvm-project\llvm\test\Transforms\InstCombine\fabs.ll -passes=instcombine -S | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe C:\_work\llvm-project\llvm-project\llvm\test\Transforms\InstCombine\fabs.ll # executed command: 'c:\_work\llvm-project\llvm-project\build\bin\opt.exe' -mtriple=x86_64-unknown-linux-gnu -passes=instcombine -S # note: command had no output on stdout or stderr # executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' 'C:\_work\llvm-project\llvm-project\llvm\test\Transforms\InstCombine\fabs.ll' # .---command stderr # | C:\_work\llvm-project\llvm-project\llvm\test\Transforms\InstCombine\fabs.ll:210:15: error: CHECK-NEXT: expected string not found in input # | ; CHECK-NEXT: ret float [[FMA]] # | ^ # | :125:78: note: scanning from here # | %fma = call nnan float @llvm.fma.f32(float %x, float %x, float 1.00e+00) # | ^ # | :125:78: note: with "FMA" equal to "%fma" # | %fma = call nnan float @llvm.fma.f32(float %x, float %x, float 1.00e+00) # | ^ # | :127:2: note: possible intended match here # | ret float %fabsf # | ^ # | C:\_work\llvm-project\llvm-project\llvm\test\Transforms\InstCombine\fabs.ll:231:15: error: CHECK-NEXT: expected string not found in input # | ; CHECK-NEXT: ret float [[FMULADD]] # | ^ # | :137:86: note: scanning from here # | %fmuladd = call nnan float @llvm.fmuladd.f32(float %x, float %x, float 1.00e+00) # | ^ # | :137:86: note: with "FMULADD" equal to "%fmuladd" # | %fmuladd = call nnan float @llvm.fmuladd.f32(float %x, float %x, float 1.00e+00) # | ^ # | :139:2: note: possible intended match here # | ret float %fabsf # | ^ # | # | Input file: # | Check file: C:\_work\llvm-project\llvm-project\llvm\test\Transforms\InstCombine\fabs.ll # | # | -dump-input=help explains the following input dump. # | # | Input was: # | << # | . # | . # | . # | 120: %fabsf = call float @llvm.fabs.f32(float %fma) # | 121: ret float %fabsf # |
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 4cbd9dbb839d6ff0944e58799cd2177c482b34ba Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3c15400d90b48..5fe889df057bf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,29 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2788,6 +2811,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2809,7 +2840,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 4cbd9dbb839d6ff0944e58799cd2177c482b34ba Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3c15400d90b48..5fe889df057bf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,29 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2788,6 +2811,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2809,7 +2840,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/dtcxzyw edited https://github.com/llvm/llvm-project/pull/176003 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/dtcxzyw approved this pull request. LG https://github.com/llvm/llvm-project/pull/176003 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 4d6a3911109ece865521de43104e2d7102b41062 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 87a03a558e5ac..b198e5e824f1f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,29 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2771,6 +2794,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2792,7 +2823,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/176003
>From 4d6a3911109ece865521de43104e2d7102b41062 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 40 ++--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 87a03a558e5ac..b198e5e824f1f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,29 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->dropUBImplyingAttrsAndMetadata();
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2771,6 +2794,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2792,7 +2823,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..9b5274b9e7459 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
@@ -2056,6 +2056,28 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->setFastMathFlags(InferredFMF);
arsenm wrote:
Missing the attribute drop
https://github.com/llvm/llvm-project/pull/176003
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
llvmbot wrote:
@llvm/pr-subscribers-llvm-adt
Author: Matt Arsenault (arsenm)
Changes
---
Full diff: https://github.com/llvm/llvm-project/pull/176003.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
(+35-4)
- (modified) llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
(+60-5)
``diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3bbc4a913ada6..3292d3538b4e3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,28 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2790,6 +2812,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2811,7 +2841,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..6ec5daa48e125 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ 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
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
llvmbot wrote:
@llvm/pr-subscribers-llvm-transforms
Author: Matt Arsenault (arsenm)
Changes
---
Full diff: https://github.com/llvm/llvm-project/pull/176003.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
(+35-4)
- (modified) llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
(+60-5)
``diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3bbc4a913ada6..3292d3538b4e3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,28 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2790,6 +2812,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2811,7 +2841,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..6ec5daa48e125 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ 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 ze
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
arsenm wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.com/github/pr/llvm/llvm-project/176003?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#176003** https://app.graphite.com/github/pr/llvm/llvm-project/176003?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/176003?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#175616** https://app.graphite.com/github/pr/llvm/llvm-project/175616?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#175615** https://app.graphite.com/github/pr/llvm/llvm-project/175615?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#175614** https://app.graphite.com/github/pr/llvm/llvm-project/175614?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/>: 1 other dependent PR ([#175999](https://github.com/llvm/llvm-project/pull/175999) https://app.graphite.com/github/pr/llvm/llvm-project/175999?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/>) * **#175613** https://app.graphite.com/github/pr/llvm/llvm-project/175613?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#174853** https://app.graphite.com/github/pr/llvm/llvm-project/174853?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#174852** https://app.graphite.com/github/pr/llvm/llvm-project/174852?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/176003 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm ready_for_review https://github.com/llvm/llvm-project/pull/176003 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Infer fast math flags for sqrt (PR #176003)
https://github.com/arsenm created
https://github.com/llvm/llvm-project/pull/176003
None
>From 82372b2c36018ae7b2abc9af106e07bbc8bac689 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Wed, 14 Jan 2026 18:40:41 +0100
Subject: [PATCH] InstCombine: Infer fast math flags for sqrt
---
.../InstCombineSimplifyDemanded.cpp | 39 +--
.../simplify-demanded-fpclass-sqrt.ll | 65 +--
2 files changed, 95 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3bbc4a913ada6..3292d3538b4e3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2036,9 +2036,9 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest
Mask,
/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
-static FastMathFlags
-inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
-ArrayRef Known) {
+static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
+ FPClassTest ValidResults,
+ ArrayRef Known) {
if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
if (all_of(Known, [](const KnownFPClass KnownSrc) {
return KnownSrc.isKnownNeverNaN();
@@ -2056,6 +2056,28 @@ inferFastMathValueFlags(FastMathFlags FMF, FPClassTest
ValidResults,
return FMF;
}
+/// Apply epilog fixups to a floating-point intrinsic. See if the result can
+/// fold to a constant, or apply fast math flags.
+static Value *simplifyDemandedFPClassResult(CallInst *FPOp, FastMathFlags FMF,
+FPClassTest DemandedMask,
+KnownFPClass &Known,
+ArrayRef KnownSrcs) {
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
+ /*IsCanonicalizing=*/true);
+ if (SingleVal)
+return SingleVal;
+
+ FastMathFlags InferredFMF =
+ inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
+ if (InferredFMF != FMF) {
+FPOp->setFastMathFlags(InferredFMF);
+return FPOp;
+ }
+
+ return nullptr;
+}
+
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2790,6 +2812,14 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
return I;
+ // Infer the source cannot be negative if the result cannot be nan.
+ if ((DemandedMask & fcNan) == fcNone)
+KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);
+
+ // Infer the source cannot be +inf if the result is not +nf
+ if ((DemandedMask & fcPosInf) == fcNone)
+KnownSrc.knownNot(fcPosInf);
+
Type *EltTy = VTy->getScalarType();
DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
@@ -2811,7 +2841,8 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return Copysign;
}
- return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
+ {KnownSrc});
}
case Intrinsic::trunc:
case Intrinsic::floor:
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
index b09faf0f4c3af..6ec5daa48e125 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-sqrt.ll
@@ -220,7 +220,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_pnorm_sourc
; 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:[[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float
[[SELECT]])
; CHECK-NEXT:ret float [[RESULT]]
;
%only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func()
@@ -234,7 +234,7 @@ define nofpclass(nan inf zero sub nnorm) float
@pnorm_result_demands_psub_source
; CHECK-SAME: i1 [[COND:%.*]], float nofpcl
