[llvm] [InstCombine] Prevent folding shuffle-select with binary operation when FMF is more restrictive than input (PR #201315)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 03:59:39 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Fuad Ismail (fuad1502)
<details>
<summary>Changes</summary>
Solves https://github.com/llvm/llvm-project/issues/74326
When binary operation has `ninf` FMF, but the input does not have `nofpclass(inf)`, we should not perform the transformation. Because the transformation may produce poison value when the input has an `Inf` element, whereas the original code will simply pass through the `Inf` element.
Alive proof: https://alive2.llvm.org/ce/
---
Full diff: https://github.com/llvm/llvm-project/pull/201315.diff
3 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp (+20-10)
- (modified) llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll (+37)
- (modified) llvm/test/Transforms/InstCombine/shuffle_select.ll (+37)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 3a7fbbcb468da..e85a50919efee 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -2283,16 +2283,26 @@ static Instruction *foldSelectShuffleWith1Binop(ShuffleVectorInst &Shuf,
Value *X = Op0IsBinop ? Op1 : Op0;
- // Prevent folding in the case the non-binop operand might have NaN values.
- // If X can have NaN elements then we have that the floating point math
- // operation in the transformed code may not preserve the exact NaN
- // bit-pattern -- e.g. `fadd sNaN, 0.0 -> qNaN`.
- // This makes the transformation incorrect since the original program would
- // have preserved the exact NaN bit-pattern.
- // Avoid the folding if X can have NaN elements.
- if (Shuf.getType()->getElementType()->isFloatingPointTy() &&
- !isKnownNeverNaN(X, SQ))
- return nullptr;
+ if (Shuf.getType()->getElementType()->isFloatingPointTy()) {
+ // Prevent folding in the case the non-binop operand might have NaN values.
+ // If X can have NaN elements then we have that the floating point math
+ // operation in the transformed code may not preserve the exact NaN
+ // bit-pattern -- e.g. `fadd sNaN, 0.0 -> qNaN`.
+ // This makes the transformation incorrect since the original program would
+ // have preserved the exact NaN bit-pattern.
+ // Avoid the folding if X can have NaN elements.
+ if (!isKnownNeverNaN(X, SQ))
+ return nullptr;
+
+ // Prevent folding when input can be infinity but noinf fast math flags is
+ // set. If X can have Inf elements and fast math flag noinf is set, the
+ // transformation may generate poison where the original program would
+ // preserve the Inf value.
+ auto Fmf = BO->getFastMathFlags();
+ if (Fmf.noInfs() && !isKnownNeverInfinity(X, SQ)) {
+ return nullptr;
+ }
+ }
// Shuffle identity constants into the lanes that return the original value.
// Example: shuf (mul X, {-1,-2,-3,-4}), X, {0,5,6,3} --> mul X, {-1,1,1,-4}
diff --git a/llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll b/llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll
index 3ed7fc2589d7a..62aacec027b14 100644
--- a/llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll
+++ b/llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll
@@ -372,6 +372,31 @@ define <4 x double> @fsub(<4 x double> %v) {
define <4 x float> @fmul(<4 x float> nofpclass(nan) %v) {
; CHECK-LABEL: @fmul(
+; CHECK-NEXT: [[S:%.*]] = fmul nnan <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <4 x float> [[S]]
+;
+ %b = fmul nnan <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
+ %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+ ret <4 x float> %s
+}
+
+; Negative test: FMF more restrictive than input FP class
+
+define <4 x float> @fmul_fmf_more_restrictive(<4 x float> nofpclass(nan) %v) {
+; CHECK-LABEL: @fmul_fmf_more_restrictive(
+; CHECK-NEXT: [[B:%.*]] = fmul nnan ninf <4 x float> [[V:%.*]], <float 4.100000e+01, float poison, float poison, float poison>
+; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x float> [[B]], <4 x float> [[V]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+; CHECK-NEXT: ret <4 x float> [[S]]
+;
+ %b = fmul nnan ninf <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
+ %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+ ret <4 x float> %s
+}
+
+; Try FMF (nnan ninf) as restrictive input FP class
+
+define <4 x float> @fmul_fmf_as_restrictive(<4 x float> nofpclass(nan inf) %v) {
+; CHECK-LABEL: @fmul_fmf_as_restrictive(
; CHECK-NEXT: [[S:%.*]] = fmul nnan ninf <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
; CHECK-NEXT: ret <4 x float> [[S]]
;
@@ -380,6 +405,18 @@ define <4 x float> @fmul(<4 x float> nofpclass(nan) %v) {
ret <4 x float> %s
}
+; Try FMF less restrictive than input FP class
+
+define <4 x float> @fmul_fmf_less_restrictive(<4 x float> nofpclass(nan) %v) {
+; CHECK-LABEL: @fmul_fmf_less_restrictive(
+; CHECK-NEXT: [[S:%.*]] = fmul nnan <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <4 x float> [[S]]
+;
+ %b = fmul <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
+ %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+ ret <4 x float> %s
+}
+
define <4 x double> @fdiv_constant_op0(<4 x double> %v) {
; CHECK-LABEL: @fdiv_constant_op0(
; CHECK-NEXT: [[B:%.*]] = fdiv fast <4 x double> <double poison, double poison, double 4.300000e+01, double 4.400000e+01>, [[V:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/shuffle_select.ll b/llvm/test/Transforms/InstCombine/shuffle_select.ll
index 21765f74dad78..a4d314066a536 100644
--- a/llvm/test/Transforms/InstCombine/shuffle_select.ll
+++ b/llvm/test/Transforms/InstCombine/shuffle_select.ll
@@ -372,6 +372,31 @@ define <4 x double> @fsub(<4 x double> %v) {
define <4 x float> @fmul(<4 x float> nofpclass(nan) %v) {
; CHECK-LABEL: @fmul(
+; CHECK-NEXT: [[S:%.*]] = fmul nnan <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <4 x float> [[S]]
+;
+ %b = fmul nnan <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
+ %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+ ret <4 x float> %s
+}
+
+; Negative test: FMF more restrictive than input FP class
+
+define <4 x float> @fmul_fmf_more_restrictive(<4 x float> nofpclass(nan) %v) {
+; CHECK-LABEL: @fmul_fmf_more_restrictive(
+; CHECK-NEXT: [[B:%.*]] = fmul nnan ninf <4 x float> [[V:%.*]], <float 4.100000e+01, float poison, float poison, float poison>
+; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x float> [[B]], <4 x float> [[V]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+; CHECK-NEXT: ret <4 x float> [[S]]
+;
+ %b = fmul nnan ninf <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
+ %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+ ret <4 x float> %s
+}
+
+; Try FMF (nnan ninf) as restrictive input FP class
+
+define <4 x float> @fmul_fmf_as_restrictive(<4 x float> nofpclass(nan inf) %v) {
+; CHECK-LABEL: @fmul_fmf_as_restrictive(
; CHECK-NEXT: [[S:%.*]] = fmul nnan ninf <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
; CHECK-NEXT: ret <4 x float> [[S]]
;
@@ -380,6 +405,18 @@ define <4 x float> @fmul(<4 x float> nofpclass(nan) %v) {
ret <4 x float> %s
}
+; Try FMF less restrictive than input FP class
+
+define <4 x float> @fmul_fmf_less_restrictive(<4 x float> nofpclass(nan) %v) {
+; CHECK-LABEL: @fmul_fmf_less_restrictive(
+; CHECK-NEXT: [[S:%.*]] = fmul nnan <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <4 x float> [[S]]
+;
+ %b = fmul <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>
+ %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+ ret <4 x float> %s
+}
+
define <4 x double> @fdiv_constant_op0(<4 x double> %v) {
; CHECK-LABEL: @fdiv_constant_op0(
; CHECK-NEXT: [[B:%.*]] = fdiv fast <4 x double> <double poison, double poison, double 4.300000e+01, double 4.400000e+01>, [[V:%.*]]
``````````
</details>
https://github.com/llvm/llvm-project/pull/201315
More information about the llvm-commits
mailing list