[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