Skip to content

Commit 7c135e1

Browse files
authored
[InstSimplify] Treat float binop with identity as refining (llvm#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 llvm#115152 (comment).
1 parent 75b2d78 commit 7c135e1

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4345,11 +4345,14 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
43454345
if (auto *BO = dyn_cast<BinaryOperator>(I)) {
43464346
unsigned Opcode = BO->getOpcode();
43474347
// id op x -> x, x op id -> x
4348-
if (NewOps[0] == ConstantExpr::getBinOpIdentity(Opcode, I->getType()))
4349-
return NewOps[1];
4350-
if (NewOps[1] == ConstantExpr::getBinOpIdentity(Opcode, I->getType(),
4351-
/* RHS */ true))
4352-
return NewOps[0];
4348+
// Exclude floats, because x op id may produce a different NaN value.
4349+
if (!BO->getType()->isFPOrFPVectorTy()) {
4350+
if (NewOps[0] == ConstantExpr::getBinOpIdentity(Opcode, I->getType()))
4351+
return NewOps[1];
4352+
if (NewOps[1] == ConstantExpr::getBinOpIdentity(Opcode, I->getType(),
4353+
/* RHS */ true))
4354+
return NewOps[0];
4355+
}
43534356

43544357
// x & x -> x, x | x -> x
43554358
if ((Opcode == Instruction::And || Opcode == Instruction::Or) &&

llvm/test/Transforms/InstSimplify/select-equivalence-fp.ll

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,14 @@ define <2 x float> @select_fcmp_fadd_vec(<2 x float> %x) {
114114
}
115115

116116

117+
; Should not fold, because the fmul by identity may produce a different NaN
118+
; value.
117119
define float @select_fcmp_fmul_nonrefinement(float %x, float %y) {
118120
; CHECK-LABEL: @select_fcmp_fmul_nonrefinement(
119-
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[Y:%.*]], [[X:%.*]]
120-
; CHECK-NEXT: ret float [[FMUL]]
121+
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
122+
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[Y:%.*]], [[X]]
123+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[Y]], float [[FMUL]]
124+
; CHECK-NEXT: ret float [[SEL]]
121125
;
122126
%fcmp = fcmp oeq float %x, 1.0
123127
%fmul = fmul float %y, %x
@@ -137,8 +141,10 @@ define float @select_fcmp_fmul(float %x) {
137141

138142
define float @select_fcmp_fdiv_nonrefinement(float %x, float %y) {
139143
; CHECK-LABEL: @select_fcmp_fdiv_nonrefinement(
140-
; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[Y:%.*]], [[X:%.*]]
141-
; CHECK-NEXT: ret float [[FDIV]]
144+
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
145+
; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[Y:%.*]], [[X]]
146+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[Y]], float [[FDIV]]
147+
; CHECK-NEXT: ret float [[SEL]]
142148
;
143149
%fcmp = fcmp oeq float %x, 1.0
144150
%fdiv = fdiv float %y, %x

0 commit comments

Comments
 (0)