[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 896bab60a885541f92ee83e17717ba83c3a847be Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 113 +-
.../simplify-demanded-fpclass-fma.ll | 47 +++-
2 files changed, 98 insertions(+), 62 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 342420f049fb8..31c962dbae502 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2058,6 +2058,39 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
return nullptr;
}
+/// 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) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
+static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
+ FastMathFlags FMF) {
+ if (FMF.noNaNs())
+DemandedMask &= ~fcNan;
+
+ if (FMF.noInfs())
+DemandedMask &= ~fcInf;
+ return DemandedMask;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2188,35 +2221,6 @@ static Value
*simplifyDemandedUseFPClassFPTrunc(InstCombinerImpl &IC,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
-static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
- FastMathFlags FMF) {
- if (FMF.noNaNs())
-DemandedMask &= ~fcNan;
-
- if (FMF.noInfs())
-DemandedMask &= ~fcInf;
- return DemandedMask;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2336,7 +2340,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2502,7 +2506,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2600,6 +2604,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 896bab60a885541f92ee83e17717ba83c3a847be Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 113 +-
.../simplify-demanded-fpclass-fma.ll | 47 +++-
2 files changed, 98 insertions(+), 62 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 342420f049fb8..31c962dbae502 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2058,6 +2058,39 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
return nullptr;
}
+/// 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) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
+static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
+ FastMathFlags FMF) {
+ if (FMF.noNaNs())
+DemandedMask &= ~fcNan;
+
+ if (FMF.noInfs())
+DemandedMask &= ~fcInf;
+ return DemandedMask;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2188,35 +2221,6 @@ static Value
*simplifyDemandedUseFPClassFPTrunc(InstCombinerImpl &IC,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
-static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
- FastMathFlags FMF) {
- if (FMF.noNaNs())
-DemandedMask &= ~fcNan;
-
- if (FMF.noInfs())
-DemandedMask &= ~fcInf;
- return DemandedMask;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2336,7 +2340,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2502,7 +2506,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2600,6 +2604,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 0e8a87d1ffc98de650a88770dd03ef9634e062a3 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 113 +-
.../simplify-demanded-fpclass-fma.ll | 47 +++-
2 files changed, 98 insertions(+), 62 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index a0aa7c89a7744..1ae0395814fe6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2058,6 +2058,39 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
return nullptr;
}
+/// 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) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
+static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
+ FastMathFlags FMF) {
+ if (FMF.noNaNs())
+DemandedMask &= ~fcNan;
+
+ if (FMF.noInfs())
+DemandedMask &= ~fcInf;
+ return DemandedMask;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2153,35 +2186,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
-static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
- FastMathFlags FMF) {
- if (FMF.noNaNs())
-DemandedMask &= ~fcNan;
-
- if (FMF.noInfs())
-DemandedMask &= ~fcInf;
- return DemandedMask;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2295,7 +2299,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2461,7 +2465,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2556,6 +2560,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 0e8a87d1ffc98de650a88770dd03ef9634e062a3 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 113 +-
.../simplify-demanded-fpclass-fma.ll | 47 +++-
2 files changed, 98 insertions(+), 62 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index a0aa7c89a7744..1ae0395814fe6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2058,6 +2058,39 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
return nullptr;
}
+/// 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) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
+static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
+ FastMathFlags FMF) {
+ if (FMF.noNaNs())
+DemandedMask &= ~fcNan;
+
+ if (FMF.noInfs())
+DemandedMask &= ~fcInf;
+ return DemandedMask;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2153,35 +2186,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
-static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
- FastMathFlags FMF) {
- if (FMF.noNaNs())
-DemandedMask &= ~fcNan;
-
- if (FMF.noInfs())
-DemandedMask &= ~fcInf;
- return DemandedMask;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2295,7 +2299,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2461,7 +2465,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2556,6 +2560,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 3158e3cae25f2c1ec4f7b8272c79b5815876e7bc Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 113 +-
.../simplify-demanded-fpclass-fma.ll | 47 +++-
2 files changed, 98 insertions(+), 62 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index b83cb48b8cd8f..2746671b1b048 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2058,6 +2058,39 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
return nullptr;
}
+/// 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) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
+static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
+ FastMathFlags FMF) {
+ if (FMF.noNaNs())
+DemandedMask &= ~fcNan;
+
+ if (FMF.noInfs())
+DemandedMask &= ~fcInf;
+ return DemandedMask;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2153,35 +2186,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
-static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
- FastMathFlags FMF) {
- if (FMF.noNaNs())
-DemandedMask &= ~fcNan;
-
- if (FMF.noInfs())
-DemandedMask &= ~fcInf;
- return DemandedMask;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2297,7 +2301,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2464,7 +2468,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2559,6 +2563,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 3158e3cae25f2c1ec4f7b8272c79b5815876e7bc Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 113 +-
.../simplify-demanded-fpclass-fma.ll | 47 +++-
2 files changed, 98 insertions(+), 62 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index b83cb48b8cd8f..2746671b1b048 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2058,6 +2058,39 @@ static Value *simplifyDemandedFPClassFabs(KnownFPClass
&Known, Value *Src,
return nullptr;
}
+/// 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) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
+static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
+ FastMathFlags FMF) {
+ if (FMF.noNaNs())
+DemandedMask &= ~fcNan;
+
+ if (FMF.noInfs())
+DemandedMask &= ~fcInf;
+ return DemandedMask;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2153,35 +2186,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
-static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
- FastMathFlags FMF) {
- if (FMF.noNaNs())
-DemandedMask &= ~fcNan;
-
- if (FMF.noInfs())
-DemandedMask &= ~fcInf;
- return DemandedMask;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2297,7 +2301,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2464,7 +2468,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2559,6 +2563,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From adab85ebe9519123b5f2c6dc560b5417986edc75 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH 1/2] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 93 ++-
.../simplify-demanded-fpclass-fma.ll | 47 --
2 files changed, 88 insertions(+), 52 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 78d7be41fae67..77dba8bc62da5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,6 +2033,29 @@ 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,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2128,25 +2151,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2262,7 +2266,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2429,7 +2433,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2523,6 +2527,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From adab85ebe9519123b5f2c6dc560b5417986edc75 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH 1/2] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 93 ++-
.../simplify-demanded-fpclass-fma.ll | 47 --
2 files changed, 88 insertions(+), 52 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 78d7be41fae67..77dba8bc62da5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,6 +2033,29 @@ 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,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2128,25 +2151,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2262,7 +2266,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2429,7 +2433,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2523,6 +2527,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From e78d12436ad5a3b4329db1ef25bf50b96a375cd9 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH 1/2] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 93 ++-
.../simplify-demanded-fpclass-fma.ll | 47 --
2 files changed, 88 insertions(+), 52 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 78d7be41fae67..77dba8bc62da5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,6 +2033,29 @@ 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,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2128,25 +2151,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2262,7 +2266,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2429,7 +2433,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2523,6 +2527,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From e78d12436ad5a3b4329db1ef25bf50b96a375cd9 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH 1/2] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 93 ++-
.../simplify-demanded-fpclass-fma.ll | 47 --
2 files changed, 88 insertions(+), 52 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 78d7be41fae67..77dba8bc62da5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,6 +2033,29 @@ 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,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2128,25 +2151,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2262,7 +2266,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2429,7 +2433,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2523,6 +2527,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 5c37906ac54361c53bf22204d276934b2a347df5 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH 1/2] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 93 ++-
.../simplify-demanded-fpclass-fma.ll | 47 --
2 files changed, 88 insertions(+), 52 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 358fac1ec07d7..1cfd4a61e88c5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,6 +2033,29 @@ 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,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2128,25 +2151,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2262,7 +2266,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2429,7 +2433,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2523,6 +2527,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 5c37906ac54361c53bf22204d276934b2a347df5 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH 1/2] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 93 ++-
.../simplify-demanded-fpclass-fma.ll | 47 --
2 files changed, 88 insertions(+), 52 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 358fac1ec07d7..1cfd4a61e88c5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,6 +2033,29 @@ 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,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
+
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
+
+ return FMF;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2128,25 +2151,6 @@ simplifyDemandedFPClassMinMax(KnownFPClass &Known,
Intrinsic::ID IID,
/*IsCanonicalizing=*/true);
}
-/// 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,
-/// \p KnownLHS and \p KnownRHS)
-static FastMathFlags
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
-
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
-
- return FMF;
-}
-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
FPClassTest DemandedMask,
KnownFPClass &Known,
@@ -2262,7 +2266,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2429,7 +2433,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return SingleVal;
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2523,6 +2527,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From f3a855449e79a090c8821e4d2ef58dd7d34ddc4e Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH 1/3] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 79 +++
.../simplify-demanded-fpclass-fma.ll | 47 ---
2 files changed, 81 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 05ed123b8be75..cde505dd4496c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,21 +2033,25 @@ 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,
-/// \p KnownLHS and \p KnownRHS)
+/// 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
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
+inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
return FMF;
}
@@ -2167,7 +2171,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2428,6 +2432,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(KnownSrc[0], KnownSrc[2], Mode);
+ } else {
+for (int OpIdx = 0; OpIdx != 3; ++OpIdx) {
+ if (SimplifyDemandedFPClass(CI, OpIdx, SrcDemandedMask,
+ KnownSrc[OpIdx], Depth + 1))
+return CI;
+}
+
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
+ }
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ if (Constant *SingleVal =
+ getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
+return SingleVal;
+
+ FastMathFlags InferredFMF = inferFastMathValueFlags(
+ FMF, ValidResults, {KnownSrc[0], KnownSrc[1], KnownSrc[2]});
+ if (InferredFMF != FMF) {
+CI->dropUBImplyingAttrsAndMetadata();
+CI->setFastMathFlags(InferredFMF);
+return I;
+ }
+
+ break;
+}
case Intrinsic::
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From f3a855449e79a090c8821e4d2ef58dd7d34ddc4e Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH 1/3] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 79 +++
.../simplify-demanded-fpclass-fma.ll | 47 ---
2 files changed, 81 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 05ed123b8be75..cde505dd4496c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,21 +2033,25 @@ 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,
-/// \p KnownLHS and \p KnownRHS)
+/// 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
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
+inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
return FMF;
}
@@ -2167,7 +2171,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2428,6 +2432,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(KnownSrc[0], KnownSrc[2], Mode);
+ } else {
+for (int OpIdx = 0; OpIdx != 3; ++OpIdx) {
+ if (SimplifyDemandedFPClass(CI, OpIdx, SrcDemandedMask,
+ KnownSrc[OpIdx], Depth + 1))
+return CI;
+}
+
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
+ }
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ if (Constant *SingleVal =
+ getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
+return SingleVal;
+
+ FastMathFlags InferredFMF = inferFastMathValueFlags(
+ FMF, ValidResults, {KnownSrc[0], KnownSrc[1], KnownSrc[2]});
+ if (InferredFMF != FMF) {
+CI->dropUBImplyingAttrsAndMetadata();
+CI->setFastMathFlags(InferredFMF);
+return I;
+ }
+
+ break;
+}
case Intrinsic::
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From a80cec9000cf1f7f0e8ba8de41c6abe9c657631c Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 79 +++
.../simplify-demanded-fpclass-fma.ll | 47 ---
2 files changed, 81 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3d51c5d986ef6..e40db6650aa71 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,21 +2033,25 @@ 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,
-/// \p KnownLHS and \p KnownRHS)
+/// 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
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
+inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
return FMF;
}
@@ -2167,7 +2171,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2417,6 +2421,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(KnownSrc[0], KnownSrc[2], Mode);
+ } else {
+for (int OpIdx = 0; OpIdx != 3; ++OpIdx) {
+ if (SimplifyDemandedFPClass(CI, OpIdx, SrcDemandedMask,
+ KnownSrc[OpIdx], Depth + 1))
+return CI;
+}
+
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
+ }
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ if (Constant *SingleVal =
+ getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
+return SingleVal;
+
+ FastMathFlags InferredFMF = inferFastMathValueFlags(
+ FMF, ValidResults, {KnownSrc[0], KnownSrc[1], KnownSrc[2]});
+ if (InferredFMF != FMF) {
+CI->dropUBImplyingAttrsAndMetadata();
+CI->setFastMathFlags(InferredFMF);
+return I;
+ }
+
+ break;
+}
case Intrinsic::maxi
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From a80cec9000cf1f7f0e8ba8de41c6abe9c657631c Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 79 +++
.../simplify-demanded-fpclass-fma.ll | 47 ---
2 files changed, 81 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3d51c5d986ef6..e40db6650aa71 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,21 +2033,25 @@ 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,
-/// \p KnownLHS and \p KnownRHS)
+/// 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
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
+inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
return FMF;
}
@@ -2167,7 +2171,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2417,6 +2421,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(KnownSrc[0], KnownSrc[2], Mode);
+ } else {
+for (int OpIdx = 0; OpIdx != 3; ++OpIdx) {
+ if (SimplifyDemandedFPClass(CI, OpIdx, SrcDemandedMask,
+ KnownSrc[OpIdx], Depth + 1))
+return CI;
+}
+
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
+ }
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ if (Constant *SingleVal =
+ getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
+return SingleVal;
+
+ FastMathFlags InferredFMF = inferFastMathValueFlags(
+ FMF, ValidResults, {KnownSrc[0], KnownSrc[1], KnownSrc[2]});
+ if (InferredFMF != FMF) {
+CI->dropUBImplyingAttrsAndMetadata();
+CI->setFastMathFlags(InferredFMF);
+return I;
+ }
+
+ break;
+}
case Intrinsic::maxi
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/dtcxzyw edited https://github.com/llvm/llvm-project/pull/175616 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
@@ -2033,21 +2033,25 @@ 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,
-/// \p KnownLHS and \p KnownRHS)
+/// 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
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
+inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
+std::initializer_list Known) {
dtcxzyw wrote:
Use ArrayRef instead.
https://github.com/llvm/llvm-project/pull/175616
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
@@ -2417,6 +2421,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(KnownSrc[0], KnownSrc[2], Mode);
+ } else {
+for (int OpIdx = 0; OpIdx != 3; ++OpIdx) {
+ if (SimplifyDemandedFPClass(CI, OpIdx, SrcDemandedMask,
+ KnownSrc[OpIdx], Depth + 1))
+return CI;
+}
+
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
+ }
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ if (Constant *SingleVal =
+ getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
+return SingleVal;
+
+ FastMathFlags InferredFMF = inferFastMathValueFlags(
+ FMF, ValidResults, {KnownSrc[0], KnownSrc[1], KnownSrc[2]});
dtcxzyw wrote:
```suggestion
FMF, ValidResults, KnownSrc);
```
https://github.com/llvm/llvm-project/pull/175616
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/dtcxzyw approved this pull request. LGTM (only for this patch and the pre-commit tests) https://github.com/llvm/llvm-project/pull/175616 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 5ad12d0a734365ea31275d6da8aeb331979282a1 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 79 +++
.../simplify-demanded-fpclass-fma.ll | 47 ---
2 files changed, 81 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3d51c5d986ef6..e40db6650aa71 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,21 +2033,25 @@ 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,
-/// \p KnownLHS and \p KnownRHS)
+/// 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
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
+inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
return FMF;
}
@@ -2167,7 +2171,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2417,6 +2421,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(KnownSrc[0], KnownSrc[2], Mode);
+ } else {
+for (int OpIdx = 0; OpIdx != 3; ++OpIdx) {
+ if (SimplifyDemandedFPClass(CI, OpIdx, SrcDemandedMask,
+ KnownSrc[OpIdx], Depth + 1))
+return CI;
+}
+
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
+ }
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ if (Constant *SingleVal =
+ getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
+return SingleVal;
+
+ FastMathFlags InferredFMF = inferFastMathValueFlags(
+ FMF, ValidResults, {KnownSrc[0], KnownSrc[1], KnownSrc[2]});
+ if (InferredFMF != FMF) {
+CI->dropUBImplyingAttrsAndMetadata();
+CI->setFastMathFlags(InferredFMF);
+return I;
+ }
+
+ break;
+}
case Intrinsic::maxi
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
https://github.com/arsenm updated
https://github.com/llvm/llvm-project/pull/175616
>From 5ad12d0a734365ea31275d6da8aeb331979282a1 Mon Sep 17 00:00:00 2001
From: Matt Arsenault
Date: Mon, 12 Jan 2026 14:49:56 +0100
Subject: [PATCH] InstCombine: Implement SimplifyDemandedFPClass for fma
This can't do much filtering on the sources, except for nans.
We can also attempt to introduce ninf/nnan.
---
.../InstCombineSimplifyDemanded.cpp | 79 +++
.../simplify-demanded-fpclass-fma.ll | 47 ---
2 files changed, 81 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 3d51c5d986ef6..e40db6650aa71 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,21 +2033,25 @@ 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,
-/// \p KnownLHS and \p KnownRHS)
+/// 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
-inferFastMathValueFlagsBinOp(FastMathFlags FMF, FPClassTest ValidResults,
- const KnownFPClass &KnownLHS,
- const KnownFPClass &KnownRHS) {
- if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone &&
- KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN())
-FMF.setNoNaNs();
+inferFastMathValueFlags(FastMathFlags FMF, FPClassTest ValidResults,
+std::initializer_list Known) {
+ if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverNaN();
+}))
+ FMF.setNoNaNs();
+ }
- if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone &&
- KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity())
-FMF.setNoInfs();
+ if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
+if (all_of(Known, [](const KnownFPClass &KnownSrc) {
+ return KnownSrc.isKnownNeverInfinity();
+}))
+ FMF.setNoInfs();
+ }
return FMF;
}
@@ -2167,7 +2171,7 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I->getOperand(0);
FastMathFlags InferredFMF =
-inferFastMathValueFlagsBinOp(FMF, ValidResults, KnownLHS, KnownRHS);
+inferFastMathValueFlags(FMF, ValidResults, {KnownLHS, KnownRHS});
if (InferredFMF != FMF) {
I->setFastMathFlags(InferredFMF);
return I;
@@ -2417,6 +2421,53 @@ Value
*InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
Known.copysign(KnownSign);
break;
}
+case Intrinsic::fma:
+case Intrinsic::fmuladd: {
+ // We can't do any simplification on the source besides stripping out
+ // unneeded nans.
+ FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | ~fcNan;
+
+ KnownFPClass KnownSrc[3];
+
+ Type *EltTy = VTy->getScalarType();
+ if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
+ isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, CxtI, SQ.DT,
+ Depth + 1)) {
+if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0],
+Depth + 1) ||
+SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2],
+Depth + 1))
+ return I;
+
+KnownSrc[1] = KnownSrc[0];
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma_square(KnownSrc[0], KnownSrc[2], Mode);
+ } else {
+for (int OpIdx = 0; OpIdx != 3; ++OpIdx) {
+ if (SimplifyDemandedFPClass(CI, OpIdx, SrcDemandedMask,
+ KnownSrc[OpIdx], Depth + 1))
+return CI;
+}
+
+DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
+ }
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ if (Constant *SingleVal =
+ getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
+return SingleVal;
+
+ FastMathFlags InferredFMF = inferFastMathValueFlags(
+ FMF, ValidResults, {KnownSrc[0], KnownSrc[1], KnownSrc[2]});
+ if (InferredFMF != FMF) {
+CI->dropUBImplyingAttrsAndMetadata();
+CI->setFastMathFlags(InferredFMF);
+return I;
+ }
+
+ break;
+}
case Intrinsic::maxi
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
github-actions[bot] wrote: # :penguin: Linux x64 Test Results * 167926 tests passed * 2989 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:36:15: error: CHECK-NEXT: expected string not found in input # | ; CHECK-NEXT: xxlxor 2, 2, 2 # | ^ # | :39:16: note: scanning from here # | xxlxor 0, 0, 0 # |^ # | :40:2: note: possible intended match here # | xvsubdp 1, 0, 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: # | << # |. # |. # |. # | 34: L..BB0_3: # %bb13 # | 35: # =>This Inner Loop Header: Depth=1 # | 36: bc 4, 2, L..BB0_3 # | 37: # %bb.4: # %bb14 # | 38: xxmfacc 0 # | 39: xxlxor 0, 0, 0 # | next:36'0X error: no match found # | 40: xvsubdp 1, 0, 1 # | next:36'0 ~ # | next:36'1 ?possible intended match # | 41: xvmaddadp 0, 1, 0 # | next:36'0 ~~~ # | 42: xxswapd 0, 0 # | next:36'0 ~~ # | 43: stxv 0, 0(3) # | next:36'0 ~~ # | 44: blr # | next:36'0 ~ # | 45: L..baz0: # | next:36'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+
[llvm-branch-commits] [llvm] InstCombine: Implement SimplifyDemandedFPClass for fma (PR #175616)
github-actions[bot] wrote: # :window: Windows x64 Test Results * 129353 tests passed * 2860 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:36:15: error: CHECK-NEXT: expected string not found in input # | ; CHECK-NEXT: xxlxor 2, 2, 2 # | ^ # | :39:16: note: scanning from here # | xxlxor 0, 0, 0 # |^ # | :40:2: note: possible intended match here # | xvsubdp 1, 0, 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: # | << # |. # |. # |. # | 34: L..BB0_3: # %bb13 # | 35: # =>This Inner Loop Header: Depth=1 # | 36: bc 4, 2, L..BB0_3 # | 37: # %bb.4: # %bb14 # | 38: xxmfacc 0 # | 39: xxlxor 0, 0, 0 # | next:36'0X error: no match found # | 40: xvsubdp 1, 0, 1 # | next:36'0 ~ # | next:36'1 ?possible intended match # | 41: xvmaddadp 0, 1, 0 # | next:36'0 ~~~ # | 42: xxswapd 0, 0 # | next:36'0 ~~ # | 43: stxv 0, 0(3) # | next:36'0 ~~ # | 44: blr # | next:36'0 ~ # | 45: L..baz0: # | next:36'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. # |
