[llvm] [InstCombine] Generalize ignoreSignBitOfZero/NaN to handle more cases (PR #141015)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Thu May 22 00:41:13 PDT 2025
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/141015
This patch was originally part of https://github.com/llvm/llvm-project/pull/139861. It generalizes `ignoreSignBitOfZero/NaN` to handle more instructions/intrinsics.
BTW, I find it mitigates performance regressions caused by https://github.com/llvm/llvm-project/pull/141010 (IR diff https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2365/files). We don't need to propagate FMF from fcmp into select, since we can infer demanded properties from the user of select.
>From db7e339019d868f2d23923672c75e02f6e7a5476 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 22 May 2025 15:16:49 +0800
Subject: [PATCH 1/3] [InstCombine] Add pre-commit tests. NFC.
---
llvm/test/Transforms/InstCombine/fabs.ll | 119 +++++++++++++++++++++++
1 file changed, 119 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/fabs.ll b/llvm/test/Transforms/InstCombine/fabs.ll
index ab4376bf78a67..089ec0e44d001 100644
--- a/llvm/test/Transforms/InstCombine/fabs.ll
+++ b/llvm/test/Transforms/InstCombine/fabs.ll
@@ -1361,6 +1361,110 @@ define float @test_fabs_used_by_fcopysign_mag(float %x, float %y) {
ret float %copysign
}
+define float @test_fabs_nsz_used_by_canonicalize(float %x) {
+; CHECK-LABEL: @test_fabs_nsz_used_by_canonicalize(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SEL]])
+; CHECK-NEXT: ret float [[CANON]]
+;
+ %cmp = fcmp oge float %x, 0.000000e+00
+ %neg = fneg float %x
+ %sel = select nsz i1 %cmp, float %x, float %neg
+ %canon = call float @llvm.canonicalize.f32(float %sel)
+ ret float %canon
+}
+
+define void @test_fabs_used_by_nofpclass_nan(float %x) {
+; CHECK-LABEL: @test_fabs_used_by_nofpclass_nan(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: call void @use(float nofpclass(nan) [[SEL]])
+; CHECK-NEXT: ret void
+;
+ %cmp = fcmp oge float %x, 0.000000e+00
+ %neg = fneg float %x
+ %sel = select nsz i1 %cmp, float %x, float %neg
+ call void @use(float nofpclass(nan) %sel)
+ ret void
+}
+
+define i32 @test_fabs_used_fptosi(float %x) {
+; CHECK-LABEL: @test_fabs_used_fptosi(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[FPTOSI:%.*]] = fptosi float [[SEL]] to i32
+; CHECK-NEXT: ret i32 [[FPTOSI]]
+;
+ %cmp = fcmp oge float %x, 0.000000e+00
+ %neg = fneg float %x
+ %sel = select i1 %cmp, float %x, float %neg
+ %fptosi = fptosi float %sel to i32
+ ret i32 %fptosi
+}
+
+define i32 @test_fabs_used_fptoui(float %x) {
+; CHECK-LABEL: @test_fabs_used_fptoui(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[FPTOSI:%.*]] = fptoui float [[SEL]] to i32
+; CHECK-NEXT: ret i32 [[FPTOSI]]
+;
+ %cmp = fcmp oge float %x, 0.000000e+00
+ %neg = fneg float %x
+ %sel = select i1 %cmp, float %x, float %neg
+ %fptosi = fptoui float %sel to i32
+ ret i32 %fptosi
+}
+
+define float @test_fabs_nsz_used_by_maxnum(float %x, float %y) {
+; CHECK-LABEL: @test_fabs_nsz_used_by_maxnum(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[Y:%.*]], float [[SEL]])
+; CHECK-NEXT: ret float [[MAX]]
+;
+ %cmp = fcmp oge float %x, 0.000000e+00
+ %neg = fneg float %x
+ %sel = select nsz i1 %cmp, float %x, float %neg
+ %max = call float @llvm.maxnum.f32(float %y, float %sel)
+ ret float %max
+}
+
+define i1 @test_fabs_used_is_fpclass_pnorm_or_nan(float %x) {
+; CHECK-LABEL: @test_fabs_used_is_fpclass_pnorm_or_nan(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[IS_FPCLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[SEL]], i32 259)
+; CHECK-NEXT: ret i1 [[IS_FPCLASS]]
+;
+ %cmp = fcmp oge float %x, 0.000000e+00
+ %neg = fneg float %x
+ %sel = select i1 %cmp, float %x, float %neg
+ %is_fpclass = call i1 @llvm.is.fpclass.f32(float %sel, i32 259)
+ ret i1 %is_fpclass
+}
+
+define i1 @test_fabs_used_is_fpclass_zero_or_pinf(float %x) {
+; CHECK-LABEL: @test_fabs_used_is_fpclass_zero_or_pinf(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[IS_FPCLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[SEL]], i32 608)
+; CHECK-NEXT: ret i1 [[IS_FPCLASS]]
+;
+ %cmp = fcmp oge float %x, 0.000000e+00
+ %neg = fneg float %x
+ %sel = select i1 %cmp, float %x, float %neg
+ %is_fpclass = call i1 @llvm.is.fpclass.f32(float %sel, i32 608)
+ ret i1 %is_fpclass
+}
; Negative tests
@@ -1455,3 +1559,18 @@ define float @test_fabs_used_by_select(float %x, i1 %cond) {
%sel2 = select i1 %cond, float %sel, float 0.000000e+00
ret float %sel2
}
+
+define i1 @test_fabs_used_is_fpclass_pzero(float %x) {
+; CHECK-LABEL: @test_fabs_used_is_fpclass_pzero(
+; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[IS_FPCLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[SEL]], i32 64)
+; CHECK-NEXT: ret i1 [[IS_FPCLASS]]
+;
+ %cmp = fcmp oge float %x, 0.000000e+00
+ %neg = fneg float %x
+ %sel = select i1 %cmp, float %x, float %neg
+ %is_fpclass = call i1 @llvm.is.fpclass.f32(float %sel, i32 64)
+ ret i1 %is_fpclass
+}
>From 4ac3c5396e32669bf608d04309975ec83f4f5395 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 22 May 2025 15:29:34 +0800
Subject: [PATCH 2/3] [InstCombine] Generalize ignoreSignBitOfZero/NaN to
handle more cases
---
.../InstCombine/InstCombineSelect.cpp | 103 ++++++++++++++++--
llvm/test/Transforms/InstCombine/fabs.ll | 41 ++-----
2 files changed, 101 insertions(+), 43 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 2ef233bc25d72..a6655796ab173 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2783,15 +2783,42 @@ static bool ignoreSignBitOfZero(Instruction &I) {
if (!I.hasOneUse())
return false;
Instruction *User = I.user_back();
-
- // fcmp treats both positive and negative zero as equal.
- if (User->getOpcode() == Instruction::FCmp)
+ if (User->getOpcode() == Instruction::FPToSI ||
+ User->getOpcode() == Instruction::FPToUI)
return true;
- if (auto *FPOp = dyn_cast<FPMathOperator>(User))
- return FPOp->hasNoSignedZeros();
+ if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
+ if (FPOp->hasNoSignedZeros())
+ return true;
+ }
- return false;
+ switch (User->getOpcode()) {
+ case Instruction::FCmp:
+ // fcmp treats both positive and negative zero as equal.
+ return true;
+ case Instruction::Call:
+ if (auto *II = dyn_cast<IntrinsicInst>(User)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::fabs:
+ return true;
+ case Intrinsic::copysign:
+ return II->getArgOperand(0) == &I;
+ case Intrinsic::is_fpclass:
+ case Intrinsic::vp_is_fpclass: {
+ auto Test =
+ static_cast<FPClassTest>(
+ cast<ConstantInt>(II->getArgOperand(1))->getZExtValue()) &
+ FPClassTest::fcZero;
+ return Test == FPClassTest::fcZero || Test == FPClassTest::fcNone;
+ }
+ default:
+ return false;
+ }
+ }
+ return false;
+ default:
+ return false;
+ }
}
/// Return true if the sign bit of result can be ignored when the result is NaN.
@@ -2804,14 +2831,68 @@ static bool ignoreSignBitOfNaN(Instruction &I) {
return false;
Instruction *User = I.user_back();
- // fcmp ignores the sign bit of NaN.
- if (User->getOpcode() == Instruction::FCmp)
+ if (User->getOpcode() == Instruction::FPToSI ||
+ User->getOpcode() == Instruction::FPToUI)
return true;
- if (auto *FPOp = dyn_cast<FPMathOperator>(User))
- return FPOp->hasNoNaNs();
+ if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
+ if (FPOp->hasNoNaNs())
+ return true;
+ }
+
+ switch (User->getOpcode()) {
+ // Proper FP math operations ignore the sign bit of NaN.
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FMul:
+ case Instruction::FDiv:
+ case Instruction::FRem:
+ case Instruction::FPTrunc:
+ case Instruction::FPExt:
+ case Instruction::FCmp:
+ return true;
+ // Bitwise FP operations should preserve the sign bit of NaN.
+ case Instruction::FNeg:
+ case Instruction::Select:
+ case Instruction::PHI:
+ return false;
+ case Instruction::Call:
+ case Instruction::Invoke: {
+ if (auto *II = dyn_cast<IntrinsicInst>(User)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::fabs:
+ return true;
+ case Intrinsic::copysign:
+ return II->getArgOperand(0) == &I;
+ // Other proper FP math intrinsics ignore the sign bit of NaN.
+ case Intrinsic::maxnum:
+ case Intrinsic::minnum:
+ case Intrinsic::maximum:
+ case Intrinsic::minimum:
+ case Intrinsic::maximumnum:
+ case Intrinsic::minimumnum:
+ case Intrinsic::canonicalize:
+ case Intrinsic::fma:
+ case Intrinsic::fmuladd:
+ case Intrinsic::sqrt:
+ case Intrinsic::pow:
+ case Intrinsic::powi:
+ case Intrinsic::fptoui_sat:
+ case Intrinsic::fptosi_sat:
+ case Intrinsic::is_fpclass:
+ return true;
+ default:
+ return false;
+ }
+ }
- return false;
+ FPClassTest NoFPClass = cast<CallBase>(User)->getParamNoFPClass(
+ I.uses().begin()->getOperandNo());
+ return NoFPClass & FPClassTest::fcNan;
+ }
+ default:
+ return false;
+ }
}
// Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need
diff --git a/llvm/test/Transforms/InstCombine/fabs.ll b/llvm/test/Transforms/InstCombine/fabs.ll
index 089ec0e44d001..b889f6c2c028c 100644
--- a/llvm/test/Transforms/InstCombine/fabs.ll
+++ b/llvm/test/Transforms/InstCombine/fabs.ll
@@ -1329,12 +1329,9 @@ define float @test_fabs_fsub_used_by_fpop_nnan(float %x, float %y) {
ret float %add
}
-; TODO: fadd ignores the sign bit of NaN.
define float @test_fabs_used_by_fpop_nsz(float %x, float %y) {
; CHECK-LABEL: @test_fabs_used_by_fpop_nsz(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[SEL:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: [[ADD:%.*]] = fadd nsz float [[SEL]], [[Y:%.*]]
; CHECK-NEXT: ret float [[ADD]]
;
@@ -1345,13 +1342,9 @@ define float @test_fabs_used_by_fpop_nsz(float %x, float %y) {
ret float %add
}
-; TODO: copysign ignores the sign bit of NaN magnitude.
define float @test_fabs_used_by_fcopysign_mag(float %x, float %y) {
; CHECK-LABEL: @test_fabs_used_by_fcopysign_mag(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X1:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X1]]
-; CHECK-NEXT: [[X:%.*]] = select i1 [[CMP]], float [[X1]], float [[NEG]]
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[Y:%.*]])
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]])
; CHECK-NEXT: ret float [[COPYSIGN]]
;
%cmp = fcmp oge float %x, 0.000000e+00
@@ -1363,9 +1356,7 @@ define float @test_fabs_used_by_fcopysign_mag(float %x, float %y) {
define float @test_fabs_nsz_used_by_canonicalize(float %x) {
; CHECK-LABEL: @test_fabs_nsz_used_by_canonicalize(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
-; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[SEL:%.*]] = call nsz float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SEL]])
; CHECK-NEXT: ret float [[CANON]]
;
@@ -1378,9 +1369,7 @@ define float @test_fabs_nsz_used_by_canonicalize(float %x) {
define void @test_fabs_used_by_nofpclass_nan(float %x) {
; CHECK-LABEL: @test_fabs_used_by_nofpclass_nan(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
-; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[SEL:%.*]] = call nsz float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: call void @use(float nofpclass(nan) [[SEL]])
; CHECK-NEXT: ret void
;
@@ -1393,9 +1382,7 @@ define void @test_fabs_used_by_nofpclass_nan(float %x) {
define i32 @test_fabs_used_fptosi(float %x) {
; CHECK-LABEL: @test_fabs_used_fptosi(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[SEL:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: [[FPTOSI:%.*]] = fptosi float [[SEL]] to i32
; CHECK-NEXT: ret i32 [[FPTOSI]]
;
@@ -1408,9 +1395,7 @@ define i32 @test_fabs_used_fptosi(float %x) {
define i32 @test_fabs_used_fptoui(float %x) {
; CHECK-LABEL: @test_fabs_used_fptoui(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[SEL:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: [[FPTOSI:%.*]] = fptoui float [[SEL]] to i32
; CHECK-NEXT: ret i32 [[FPTOSI]]
;
@@ -1423,9 +1408,7 @@ define i32 @test_fabs_used_fptoui(float %x) {
define float @test_fabs_nsz_used_by_maxnum(float %x, float %y) {
; CHECK-LABEL: @test_fabs_nsz_used_by_maxnum(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
-; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], float [[X]], float [[NEG]]
+; CHECK-NEXT: [[SEL:%.*]] = call nsz float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[Y:%.*]], float [[SEL]])
; CHECK-NEXT: ret float [[MAX]]
;
@@ -1438,10 +1421,7 @@ define float @test_fabs_nsz_used_by_maxnum(float %x, float %y) {
define i1 @test_fabs_used_is_fpclass_pnorm_or_nan(float %x) {
; CHECK-LABEL: @test_fabs_used_is_fpclass_pnorm_or_nan(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
-; CHECK-NEXT: [[IS_FPCLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[SEL]], i32 259)
+; CHECK-NEXT: [[IS_FPCLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 267)
; CHECK-NEXT: ret i1 [[IS_FPCLASS]]
;
%cmp = fcmp oge float %x, 0.000000e+00
@@ -1453,10 +1433,7 @@ define i1 @test_fabs_used_is_fpclass_pnorm_or_nan(float %x) {
define i1 @test_fabs_used_is_fpclass_zero_or_pinf(float %x) {
; CHECK-LABEL: @test_fabs_used_is_fpclass_zero_or_pinf(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
-; CHECK-NEXT: [[IS_FPCLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[SEL]], i32 608)
+; CHECK-NEXT: [[IS_FPCLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X:%.*]], i32 612)
; CHECK-NEXT: ret i1 [[IS_FPCLASS]]
;
%cmp = fcmp oge float %x, 0.000000e+00
>From b314ab2ff0563574da09964c600167cb61b8aca1 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 22 May 2025 15:32:59 +0800
Subject: [PATCH 3/3] [InstCombine] Simplify code. NFC.
---
.../Transforms/InstCombine/InstCombineSelect.cpp | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index a6655796ab173..13cbf7b215557 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2783,16 +2783,15 @@ static bool ignoreSignBitOfZero(Instruction &I) {
if (!I.hasOneUse())
return false;
Instruction *User = I.user_back();
- if (User->getOpcode() == Instruction::FPToSI ||
- User->getOpcode() == Instruction::FPToUI)
- return true;
-
if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
if (FPOp->hasNoSignedZeros())
return true;
}
switch (User->getOpcode()) {
+ case Instruction::FPToSI:
+ case Instruction::FPToUI:
+ return true;
case Instruction::FCmp:
// fcmp treats both positive and negative zero as equal.
return true;
@@ -2830,17 +2829,15 @@ static bool ignoreSignBitOfNaN(Instruction &I) {
if (!I.hasOneUse())
return false;
Instruction *User = I.user_back();
-
- if (User->getOpcode() == Instruction::FPToSI ||
- User->getOpcode() == Instruction::FPToUI)
- return true;
-
if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
if (FPOp->hasNoNaNs())
return true;
}
switch (User->getOpcode()) {
+ case Instruction::FPToSI:
+ case Instruction::FPToUI:
+ return true;
// Proper FP math operations ignore the sign bit of NaN.
case Instruction::FAdd:
case Instruction::FSub:
More information about the llvm-commits
mailing list