[llvm] [InstSimplify] Treat float binop with identity as refining (PR #120098)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 16 07:34:21 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Nikita Popov (nikic)

<details>
<summary>Changes</summary>

If x if NaN, then fmul (x, 1) may produce a different NaN value.

Our float semantics explicitly permit folding fmul (x, 1) to x, but we can't do this when we're replacing a select input, as selects are supposed to preserve the exact bitwise value.

Fixes https://github.com/llvm/llvm-project/pull/115152#issuecomment-2545773114.

---
Full diff: https://github.com/llvm/llvm-project/pull/120098.diff


2 Files Affected:

- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+8-5) 
- (modified) llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll (+10-4) 


``````````diff
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 3325cd972cf1eb..726c0f29e39928 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4345,11 +4345,14 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
     if (auto *BO = dyn_cast<BinaryOperator>(I)) {
       unsigned Opcode = BO->getOpcode();
       // id op x -> x, x op id -> x
-      if (NewOps[0] == ConstantExpr::getBinOpIdentity(Opcode, I->getType()))
-        return NewOps[1];
-      if (NewOps[1] == ConstantExpr::getBinOpIdentity(Opcode, I->getType(),
-                                                      /* RHS */ true))
-        return NewOps[0];
+      // Exclude floats, because x op id may produce a different NaN value.
+      if (!BO->getType()->isFPOrFPVectorTy()) {
+        if (NewOps[0] == ConstantExpr::getBinOpIdentity(Opcode, I->getType()))
+          return NewOps[1];
+        if (NewOps[1] == ConstantExpr::getBinOpIdentity(Opcode, I->getType(),
+                                                        /* RHS */ true))
+          return NewOps[0];
+      }
 
       // x & x -> x, x | x -> x
       if ((Opcode == Instruction::And || Opcode == Instruction::Or) &&
diff --git a/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll b/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
index 8af751d0a4246d..81132029466f90 100644
--- a/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
+++ b/llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
@@ -114,10 +114,14 @@ define <2 x float> @select_fcmp_fadd_vec(<2 x float> %x) {
 }
 
 
+; Should not fold, because the fmul by identity may produce a different NaN
+; value.
 define float @select_fcmp_fmul_nonrefinement(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_fmul_nonrefinement(
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    ret float [[FMUL]]
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[Y:%.*]], [[X]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[Y]], float [[FMUL]]
+; CHECK-NEXT:    ret float [[SEL]]
 ;
   %fcmp = fcmp oeq float %x, 1.0
   %fmul = fmul float %y, %x
@@ -137,8 +141,10 @@ define float @select_fcmp_fmul(float %x) {
 
 define float @select_fcmp_fdiv_nonrefinement(float %x, float %y) {
 ; CHECK-LABEL: @select_fcmp_fdiv_nonrefinement(
-; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    ret float [[FDIV]]
+; CHECK-NEXT:    [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[Y:%.*]], [[X]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[FCMP]], float [[Y]], float [[FDIV]]
+; CHECK-NEXT:    ret float [[SEL]]
 ;
   %fcmp = fcmp oeq float %x, 1.0
   %fdiv = fdiv float %y, %x

``````````

</details>


https://github.com/llvm/llvm-project/pull/120098


More information about the llvm-commits mailing list