Skip to content

Commit

Permalink
[InstSimplify] Treat float binop with identity as refining (#120098)
Browse files Browse the repository at this point in the history
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
llvm/llvm-project#115152 (comment).
  • Loading branch information
nikic authored Dec 17, 2024
1 parent 75b2d78 commit 7c135e1
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 9 deletions.
13 changes: 8 additions & 5 deletions llvm/lib/Analysis/InstructionSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) &&
Expand Down
14 changes: 10 additions & 4 deletions llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 7c135e1

Please sign in to comment.