[llvm] 7c135e1 - [InstSimplify] Treat float binop with identity as refining (#120098)

via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 17 01:58:55 PST 2024


Author: Nikita Popov
Date: 2024-12-17T10:58:52+01:00
New Revision: 7c135e17fbb7178466eafce9826c896518907637

URL: https://github.com/llvm/llvm-project/commit/7c135e17fbb7178466eafce9826c896518907637
DIFF: https://github.com/llvm/llvm-project/commit/7c135e17fbb7178466eafce9826c896518907637.diff

LOG: [InstSimplify] Treat float binop with identity as refining (#120098)

If x is 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.

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll

Removed: 
    


################################################################################
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 
diff erent 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 
diff erent 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


        


More information about the llvm-commits mailing list