-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[InstCombine] Preserve signbit semantics of NaN with fold to fabs #136648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesAs per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is preserved if there is no floating-point operation being performed. Alive2: https://alive2.llvm.org/ce/z/4mBcJx Full diff: https://github.com/llvm/llvm-project/pull/136648.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 4bba2f406b4c1..06792e32de3e1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2793,7 +2793,11 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
// fold (X <= +/-0.0) ? (0.0 - X) : X to fabs(X), when 'Swap' is false
// fold (X > +/-0.0) ? X : (0.0 - X) to fabs(X), when 'Swap' is true
- if (match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(X)))) {
+ // Note: We require "nnan" for this fold because fcmp ignores the signbit
+ // of NAN, but IEEE-754 specifies the signbit of NAN values with
+ // fneg/fabs operations.
+ if (cast<FPMathOperator>(CondVal)->hasNoNaNs() &&
+ match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(X)))) {
if (!Swap && (Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)) {
Value *Fabs = IC.Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, &SI);
return IC.replaceInstUsesWith(SI, Fabs);
diff --git a/llvm/test/Transforms/InstCombine/fabs.ll b/llvm/test/Transforms/InstCombine/fabs.ll
index 7b9a672f188ca..827315b184085 100644
--- a/llvm/test/Transforms/InstCombine/fabs.ll
+++ b/llvm/test/Transforms/InstCombine/fabs.ll
@@ -256,6 +256,19 @@ define double @select_fcmp_ole_zero(double %x) {
; CHECK-LABEL: @select_fcmp_ole_zero(
; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
; CHECK-NEXT: ret double [[FABS]]
+;
+ %lezero = fcmp nnan ole double %x, 0.0
+ %negx = fsub double 0.0, %x
+ %fabs = select i1 %lezero, double %negx, double %x
+ ret double %fabs
+}
+
+define double @select_fcmp_ole_zero_no_nnan(double %x) {
+; CHECK-LABEL: @select_fcmp_ole_zero_no_nnan(
+; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NEGX:%.*]] = fsub double 0.000000e+00, [[X]]
+; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]]
+; CHECK-NEXT: ret double [[FABS]]
;
%lezero = fcmp ole double %x, 0.0
%negx = fsub double 0.0, %x
@@ -268,7 +281,7 @@ define double @select_fcmp_nnan_ole_zero(double %x) {
; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
; CHECK-NEXT: ret double [[FABS]]
;
- %lezero = fcmp ole double %x, 0.0
+ %lezero = fcmp nnan ole double %x, 0.0
%negx = fsub nnan double 0.0, %x
%fabs = select i1 %lezero, double %negx, double %x
ret double %fabs
@@ -279,7 +292,7 @@ define double @select_nnan_fcmp_nnan_ole_zero(double %x) {
; CHECK-NEXT: [[FABS:%.*]] = call nnan double @llvm.fabs.f64(double [[X:%.*]])
; CHECK-NEXT: ret double [[FABS]]
;
- %lezero = fcmp ole double %x, 0.0
+ %lezero = fcmp nnan ole double %x, 0.0
%negx = fsub nnan double 0.0, %x
%fabs = select nnan i1 %lezero, double %negx, double %x
ret double %fabs
@@ -292,7 +305,7 @@ define double @select_fcmp_nnan_ule_zero(double %x) {
; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
; CHECK-NEXT: ret double [[FABS]]
;
- %lezero = fcmp ule double %x, 0.0
+ %lezero = fcmp nnan ule double %x, 0.0
%negx = fsub nnan double 0.0, %x
%fabs = select i1 %lezero, double %negx, double %x
ret double %fabs
@@ -320,7 +333,7 @@ define <2 x float> @select_fcmp_nnan_ole_negzero(<2 x float> %x) {
; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
- %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0>
+ %lezero = fcmp nnan ole <2 x float> %x, <float -0.0, float -0.0>
%negx = fsub nnan <2 x float> <float 0.0, float poison>, %x
%fabs = select <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x
ret <2 x float> %fabs
@@ -331,7 +344,7 @@ define <2 x float> @select_nnan_fcmp_nnan_ole_negzero(<2 x float> %x) {
; CHECK-NEXT: [[FABS:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]])
; CHECK-NEXT: ret <2 x float> [[FABS]]
;
- %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0>
+ %lezero = fcmp nnan ole <2 x float> %x, <float -0.0, float -0.0>
%negx = fsub nnan <2 x float> <float 0.0, float poison>, %x
%fabs = select nnan <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x
ret <2 x float> %fabs
@@ -344,7 +357,7 @@ define fp128 @select_fcmp_ogt_zero(fp128 %x) {
; CHECK-NEXT: [[FABS:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
; CHECK-NEXT: ret fp128 [[FABS]]
;
- %gtzero = fcmp ogt fp128 %x, zeroinitializer
+ %gtzero = fcmp nnan ogt fp128 %x, zeroinitializer
%negx = fsub fp128 zeroinitializer, %x
%fabs = select i1 %gtzero, fp128 %x, fp128 %negx
ret fp128 %fabs
@@ -382,7 +395,7 @@ define fp128 @select_fcmp_nnan_ogt_zero(fp128 %x) {
; CHECK-NEXT: [[FABS:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
; CHECK-NEXT: ret fp128 [[FABS]]
;
- %gtzero = fcmp ogt fp128 %x, zeroinitializer
+ %gtzero = fcmp nnan ogt fp128 %x, zeroinitializer
%negx = fsub nnan fp128 zeroinitializer, %x
%fabs = select i1 %gtzero, fp128 %x, fp128 %negx
ret fp128 %fabs
@@ -393,7 +406,7 @@ define fp128 @select_nnan_fcmp_nnan_ogt_zero(fp128 %x) {
; CHECK-NEXT: [[FABS:%.*]] = call nnan fp128 @llvm.fabs.f128(fp128 [[X:%.*]])
; CHECK-NEXT: ret fp128 [[FABS]]
;
- %gtzero = fcmp ogt fp128 %x, zeroinitializer
+ %gtzero = fcmp nnan ogt fp128 %x, zeroinitializer
%negx = fsub nnan fp128 zeroinitializer, %x
%fabs = select nnan i1 %gtzero, fp128 %x, fp128 %negx
ret fp128 %fabs
@@ -406,7 +419,7 @@ define half @select_fcmp_nnan_ogt_negzero(half %x) {
; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
; CHECK-NEXT: ret half [[FABS]]
;
- %gtzero = fcmp ogt half %x, -0.0
+ %gtzero = fcmp nnan ogt half %x, -0.0
%negx = fsub nnan half 0.0, %x
%fabs = select i1 %gtzero, half %x, half %negx
ret half %fabs
@@ -417,7 +430,7 @@ define half @select_nnan_fcmp_nnan_ogt_negzero(half %x) {
; CHECK-NEXT: [[FABS:%.*]] = call nnan half @llvm.fabs.f16(half [[X:%.*]])
; CHECK-NEXT: ret half [[FABS]]
;
- %gtzero = fcmp ogt half %x, -0.0
+ %gtzero = fcmp nnan ogt half %x, -0.0
%negx = fsub nnan half 0.0, %x
%fabs = select nnan i1 %gtzero, half %x, half %negx
ret half %fabs
@@ -430,7 +443,7 @@ define half @select_fcmp_nnan_ugt_negzero(half %x) {
; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
; CHECK-NEXT: ret half [[FABS]]
;
- %gtzero = fcmp ugt half %x, -0.0
+ %gtzero = fcmp nnan ugt half %x, -0.0
%negx = fsub nnan half 0.0, %x
%fabs = select i1 %gtzero, half %x, half %negx
ret half %fabs
|
No real-world impact. |
/cherry-pick 3e1e406 |
Error: Command failed due to missing milestone. |
/cherry-pick 3e1e406 |
/pull-request #137608 |
…vm#136648) As per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is preserved if there is no floating-point operation being performed. See also llvm@862e35e for reference. Alive2: https://alive2.llvm.org/ce/z/QYtEGj Closes llvm#136646
…vm#136648) As per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is preserved if there is no floating-point operation being performed. See also llvm@862e35e for reference. Alive2: https://alive2.llvm.org/ce/z/QYtEGj Closes llvm#136646 (cherry picked from commit 3e1e406)
…vm#136648) As per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is preserved if there is no floating-point operation being performed. See also llvm@862e35e for reference. Alive2: https://alive2.llvm.org/ce/z/QYtEGj Closes llvm#136646
…vm#136648) As per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is preserved if there is no floating-point operation being performed. See also llvm@862e35e for reference. Alive2: https://alive2.llvm.org/ce/z/QYtEGj Closes llvm#136646
…vm#136648) As per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is preserved if there is no floating-point operation being performed. See also llvm@862e35e for reference. Alive2: https://alive2.llvm.org/ce/z/QYtEGj Closes llvm#136646
…vm#136648) As per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is preserved if there is no floating-point operation being performed. See also llvm@862e35e for reference. Alive2: https://alive2.llvm.org/ce/z/QYtEGj Closes llvm#136646
As per the LangRef and IEEE 754-2008 standard, the sign bit of NaN is preserved if there is no floating-point operation being performed.
See also 862e35e for reference.
Alive2: https://alive2.llvm.org/ce/z/QYtEGj
Closes #136646