[llvm] [InstCombine] Handle isnormal idiom (PR #125454)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 2 21:06:36 PST 2025
https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/125454
>From dba78d01ef8c88bd852d691dd29002f9dbfb5e4b Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 3 Feb 2025 12:07:29 +0800
Subject: [PATCH 1/3] [InstCombine] Add pre-commit tests. NFC.
---
.../InstCombine/fpclass-check-idioms.ll | 176 ++++++++++++++++++
1 file changed, 176 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
index 66970a9d48ddf1..179fcfc33a40a7 100644
--- a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
+++ b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
@@ -877,6 +877,182 @@ define i1 @isnan_idiom_ppc_fp128(ppc_fp128 %x) {
ret i1 %ret
}
+define i1 @fpclass_test_normal(float %num) {
+; CHECK-LABEL: define i1 @fpclass_test_normal(
+; CHECK-SAME: float [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i32 [[MASKED]], 2139095040
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i32 [[MASKED]], 0
+; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095040
+ %test1 = icmp ne i32 %masked, 2139095040
+ %test2 = icmp ne i32 %masked, 0
+ %res = and i1 %test1, %test2
+ ret i1 %res
+}
+
+define i1 @fpclass_test_normal_half(half %num) {
+; CHECK-LABEL: define i1 @fpclass_test_normal_half(
+; CHECK-SAME: half [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast half [[NUM]] to i16
+; CHECK-NEXT: [[MASKED:%.*]] = and i16 [[CAST]], 31744
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i16 [[MASKED]], 31744
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i16 [[MASKED]], 0
+; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast half %num to i16
+ %masked = and i16 %cast, 31744
+ %test1 = icmp ne i16 %masked, 31744
+ %test2 = icmp ne i16 %masked, 0
+ %res = and i1 %test1, %test2
+ ret i1 %res
+}
+
+define <2 x i1> @fpclass_test_normal_half_vec(<2 x half> %num) {
+; CHECK-LABEL: define <2 x i1> @fpclass_test_normal_half_vec(
+; CHECK-SAME: <2 x half> [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast <2 x half> [[NUM]] to <2 x i16>
+; CHECK-NEXT: [[MASKED:%.*]] = and <2 x i16> [[CAST]], splat (i16 31744)
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne <2 x i16> [[MASKED]], splat (i16 31744)
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne <2 x i16> [[MASKED]], zeroinitializer
+; CHECK-NEXT: [[RES:%.*]] = and <2 x i1> [[TEST1]], [[TEST2]]
+; CHECK-NEXT: ret <2 x i1> [[RES]]
+;
+ %cast = bitcast <2 x half> %num to <2 x i16>
+ %masked = and <2 x i16> %cast, splat(i16 31744)
+ %test1 = icmp ne <2 x i16> %masked, splat(i16 31744)
+ %test2 = icmp ne <2 x i16> %masked, zeroinitializer
+ %res = and <2 x i1> %test1, %test2
+ ret <2 x i1> %res
+}
+
+define i1 @fpclass_test_not_normal(float %num) {
+; CHECK-LABEL: define i1 @fpclass_test_not_normal(
+; CHECK-SAME: float [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
+; CHECK-NEXT: [[TEST1:%.*]] = icmp eq i32 [[MASKED]], 2139095040
+; CHECK-NEXT: [[TEST2:%.*]] = icmp eq i32 [[MASKED]], 0
+; CHECK-NEXT: [[RES:%.*]] = or i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095040
+ %test1 = icmp eq i32 %masked, 2139095040
+ %test2 = icmp eq i32 %masked, 0
+ %res = or i1 %test1, %test2
+ ret i1 %res
+}
+
+define i1 @fpclass_test_normal_commuted(float %num) {
+; CHECK-LABEL: define i1 @fpclass_test_normal_commuted(
+; CHECK-SAME: float [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i32 [[MASKED]], 2139095040
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i32 [[MASKED]], 0
+; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST2]], [[TEST1]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095040
+ %test1 = icmp ne i32 %masked, 2139095040
+ %test2 = icmp ne i32 %masked, 0
+ %res = and i1 %test2, %test1
+ ret i1 %res
+}
+
+define i1 @fpclass_test_normal_mismatch_pred(float %num) {
+; CHECK-LABEL: define i1 @fpclass_test_normal_mismatch_pred(
+; CHECK-SAME: float [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
+; CHECK-NEXT: [[TEST2:%.*]] = icmp eq i32 [[MASKED]], 0
+; CHECK-NEXT: ret i1 [[TEST2]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095040
+ %test1 = icmp ne i32 %masked, 2139095040
+ %test2 = icmp eq i32 %masked, 0
+ %res = and i1 %test1, %test2
+ ret i1 %res
+}
+
+define i1 @fpclass_test_normal_no_implicit_fp(float %num) #0 {
+; CHECK-LABEL: define i1 @fpclass_test_normal_no_implicit_fp(
+; CHECK-SAME: float [[NUM:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i32 [[MASKED]], 2139095040
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i32 [[MASKED]], 0
+; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095040
+ %test1 = icmp ne i32 %masked, 2139095040
+ %test2 = icmp ne i32 %masked, 0
+ %res = and i1 %test1, %test2
+ ret i1 %res
+}
+
+define i1 @fpclass_test_normal_invalid_constant1(float %num) {
+; CHECK-LABEL: define i1 @fpclass_test_normal_invalid_constant1(
+; CHECK-SAME: float [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095039
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i32 [[MASKED]], 2139095039
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i32 [[MASKED]], 0
+; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095039
+ %test1 = icmp ne i32 %masked, 2139095039
+ %test2 = icmp ne i32 %masked, 0
+ %res = and i1 %test1, %test2
+ ret i1 %res
+}
+
+define i1 @fpclass_test_normal_invalid_constant2(float %num) {
+; CHECK-LABEL: define i1 @fpclass_test_normal_invalid_constant2(
+; CHECK-SAME: float [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i32 [[MASKED]], 2130706432
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i32 [[MASKED]], 0
+; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095040
+ %test1 = icmp ne i32 %masked, 2130706432
+ %test2 = icmp ne i32 %masked, 0
+ %res = and i1 %test1, %test2
+ ret i1 %res
+}
+
+define i1 @fpclass_test_normal_invalid_constant3(float %num) {
+; CHECK-LABEL: define i1 @fpclass_test_normal_invalid_constant3(
+; CHECK-SAME: float [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[CAST]], 2130706432
+; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[TMP1]], 2130706432
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095040
+ %test1 = icmp ne i32 %masked, 2139095040
+ %test2 = icmp ne i32 %masked, 2130706432
+ %res = and i1 %test1, %test2
+ ret i1 %res
+}
+
declare void @usei32(i32)
attributes #0 = { noimplicitfloat }
>From 3ee644a9d61ae0ceb183829200912c4a52b57e29 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 3 Feb 2025 12:08:16 +0800
Subject: [PATCH 2/3] [InstCombine] Handle isnormal idioms
---
.../InstCombine/InstCombineAndOrXor.cpp | 16 ++++++++++
.../InstCombine/fpclass-check-idioms.ll | 30 ++++---------------
2 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index ca8a20b4b7312d..55b6d4880814fe 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3500,6 +3500,22 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
}
}
+ // (X & ExpMask) != 0 && (X & ExpMask) != ExpMask -> isnormal(X)
+ // (X & ExpMask) == 0 || (X & ExpMask) == ExpMask -> !isnormal(X)
+ Value *X;
+ const APInt *MaskC;
+ if (LHS0 == RHS0 && PredL == PredR &&
+ PredL == (IsAnd ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ) &&
+ !I.getFunction()->hasFnAttribute(Attribute::NoImplicitFloat) &&
+ match(LHS0, m_And(m_ElementWiseBitCast(m_Value(X)), m_APInt(MaskC))) &&
+ X->getType()->getScalarType()->isIEEELikeFPTy() &&
+ APFloat(X->getType()->getScalarType()->getFltSemantics(), *MaskC)
+ .isPosInfinity() &&
+ ((LHSC->isZero() && *RHSC == *MaskC) ||
+ (RHSC->isZero() && *LHSC == *MaskC)))
+ return Builder.createIsFPClass(X, IsAnd ? FPClassTest::fcNormal
+ : ~FPClassTest::fcNormal);
+
return foldAndOrOfICmpsUsingRanges(LHS, RHS, IsAnd);
}
diff --git a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
index 179fcfc33a40a7..1d7e2bd96d1897 100644
--- a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
+++ b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
@@ -880,11 +880,7 @@ define i1 @isnan_idiom_ppc_fp128(ppc_fp128 %x) {
define i1 @fpclass_test_normal(float %num) {
; CHECK-LABEL: define i1 @fpclass_test_normal(
; CHECK-SAME: float [[NUM:%.*]]) {
-; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
-; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
-; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i32 [[MASKED]], 2139095040
-; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i32 [[MASKED]], 0
-; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: [[RES:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NUM]], i32 264)
; CHECK-NEXT: ret i1 [[RES]]
;
%cast = bitcast float %num to i32
@@ -898,11 +894,7 @@ define i1 @fpclass_test_normal(float %num) {
define i1 @fpclass_test_normal_half(half %num) {
; CHECK-LABEL: define i1 @fpclass_test_normal_half(
; CHECK-SAME: half [[NUM:%.*]]) {
-; CHECK-NEXT: [[CAST:%.*]] = bitcast half [[NUM]] to i16
-; CHECK-NEXT: [[MASKED:%.*]] = and i16 [[CAST]], 31744
-; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i16 [[MASKED]], 31744
-; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i16 [[MASKED]], 0
-; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: [[RES:%.*]] = call i1 @llvm.is.fpclass.f16(half [[NUM]], i32 264)
; CHECK-NEXT: ret i1 [[RES]]
;
%cast = bitcast half %num to i16
@@ -916,11 +908,7 @@ define i1 @fpclass_test_normal_half(half %num) {
define <2 x i1> @fpclass_test_normal_half_vec(<2 x half> %num) {
; CHECK-LABEL: define <2 x i1> @fpclass_test_normal_half_vec(
; CHECK-SAME: <2 x half> [[NUM:%.*]]) {
-; CHECK-NEXT: [[CAST:%.*]] = bitcast <2 x half> [[NUM]] to <2 x i16>
-; CHECK-NEXT: [[MASKED:%.*]] = and <2 x i16> [[CAST]], splat (i16 31744)
-; CHECK-NEXT: [[TEST1:%.*]] = icmp ne <2 x i16> [[MASKED]], splat (i16 31744)
-; CHECK-NEXT: [[TEST2:%.*]] = icmp ne <2 x i16> [[MASKED]], zeroinitializer
-; CHECK-NEXT: [[RES:%.*]] = and <2 x i1> [[TEST1]], [[TEST2]]
+; CHECK-NEXT: [[RES:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[NUM]], i32 264)
; CHECK-NEXT: ret <2 x i1> [[RES]]
;
%cast = bitcast <2 x half> %num to <2 x i16>
@@ -934,11 +922,7 @@ define <2 x i1> @fpclass_test_normal_half_vec(<2 x half> %num) {
define i1 @fpclass_test_not_normal(float %num) {
; CHECK-LABEL: define i1 @fpclass_test_not_normal(
; CHECK-SAME: float [[NUM:%.*]]) {
-; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
-; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
-; CHECK-NEXT: [[TEST1:%.*]] = icmp eq i32 [[MASKED]], 2139095040
-; CHECK-NEXT: [[TEST2:%.*]] = icmp eq i32 [[MASKED]], 0
-; CHECK-NEXT: [[RES:%.*]] = or i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: [[RES:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NUM]], i32 759)
; CHECK-NEXT: ret i1 [[RES]]
;
%cast = bitcast float %num to i32
@@ -952,11 +936,7 @@ define i1 @fpclass_test_not_normal(float %num) {
define i1 @fpclass_test_normal_commuted(float %num) {
; CHECK-LABEL: define i1 @fpclass_test_normal_commuted(
; CHECK-SAME: float [[NUM:%.*]]) {
-; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
-; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
-; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i32 [[MASKED]], 2139095040
-; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i32 [[MASKED]], 0
-; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST2]], [[TEST1]]
+; CHECK-NEXT: [[RES:%.*]] = call i1 @llvm.is.fpclass.f32(float [[NUM]], i32 264)
; CHECK-NEXT: ret i1 [[RES]]
;
%cast = bitcast float %num to i32
>From 408aa81bbdd65cc5bb72c77688079f02fd3e8504 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 3 Feb 2025 12:57:50 +0800
Subject: [PATCH 3/3] [InstCombine] Address review comments.
---
.../InstCombine/InstCombineAndOrXor.cpp | 1 +
.../InstCombine/fpclass-check-idioms.ll | 55 +++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 55b6d4880814fe..3f966c307899d0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3507,6 +3507,7 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
if (LHS0 == RHS0 && PredL == PredR &&
PredL == (IsAnd ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ) &&
!I.getFunction()->hasFnAttribute(Attribute::NoImplicitFloat) &&
+ LHS->hasOneUse() && RHS->hasOneUse() &&
match(LHS0, m_And(m_ElementWiseBitCast(m_Value(X)), m_APInt(MaskC))) &&
X->getType()->getScalarType()->isIEEELikeFPTy() &&
APFloat(X->getType()->getScalarType()->getFltSemantics(), *MaskC)
diff --git a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
index 1d7e2bd96d1897..5dcf909e5b45d2 100644
--- a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
+++ b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll
@@ -933,6 +933,20 @@ define i1 @fpclass_test_not_normal(float %num) {
ret i1 %res
}
+define <2 x i1> @fpclass_test_not_normal_vec(<2 x float> %num) {
+; CHECK-LABEL: define <2 x i1> @fpclass_test_not_normal_vec(
+; CHECK-SAME: <2 x float> [[NUM:%.*]]) {
+; CHECK-NEXT: [[RES:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> [[NUM]], i32 759)
+; CHECK-NEXT: ret <2 x i1> [[RES]]
+;
+ %cast = bitcast <2 x float> %num to <2 x i32>
+ %masked = and <2 x i32> %cast, splat(i32 2139095040)
+ %test1 = icmp eq <2 x i32> %masked, splat(i32 2139095040)
+ %test2 = icmp eq <2 x i32> %masked, zeroinitializer
+ %res = or <2 x i1> %test1, %test2
+ ret <2 x i1> %res
+}
+
define i1 @fpclass_test_normal_commuted(float %num) {
; CHECK-LABEL: define i1 @fpclass_test_normal_commuted(
; CHECK-SAME: float [[NUM:%.*]]) {
@@ -947,6 +961,26 @@ define i1 @fpclass_test_normal_commuted(float %num) {
ret i1 %res
}
+; Negative tests
+
+define i1 @fpclass_test_normal_fp128(ppc_fp128 %x) {
+; CHECK-LABEL: define i1 @fpclass_test_normal_fp128(
+; CHECK-SAME: ppc_fp128 [[X:%.*]]) {
+; CHECK-NEXT: [[BITS:%.*]] = bitcast ppc_fp128 [[X]] to i128
+; CHECK-NEXT: [[MASKED:%.*]] = and i128 [[BITS]], 170058106710732674489630815774616584192
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i128 [[MASKED]], 170058106710732674489630815774616584192
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i128 [[MASKED]], 0
+; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST2]], [[TEST1]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %bits = bitcast ppc_fp128 %x to i128
+ %masked = and i128 %bits, 170058106710732674489630815774616584192
+ %test1 = icmp ne i128 %masked, 170058106710732674489630815774616584192
+ %test2 = icmp ne i128 %masked, 0
+ %res = and i1 %test2, %test1
+ ret i1 %res
+}
+
define i1 @fpclass_test_normal_mismatch_pred(float %num) {
; CHECK-LABEL: define i1 @fpclass_test_normal_mismatch_pred(
; CHECK-SAME: float [[NUM:%.*]]) {
@@ -1033,6 +1067,27 @@ define i1 @fpclass_test_normal_invalid_constant3(float %num) {
ret i1 %res
}
+define i1 @fpclass_test_normal_multiuse(float %num) {
+; CHECK-LABEL: define i1 @fpclass_test_normal_multiuse(
+; CHECK-SAME: float [[NUM:%.*]]) {
+; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[NUM]] to i32
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[CAST]], 2139095040
+; CHECK-NEXT: [[TEST1:%.*]] = icmp ne i32 [[MASKED]], 2139095040
+; CHECK-NEXT: [[TEST2:%.*]] = icmp ne i32 [[MASKED]], 0
+; CHECK-NEXT: call void @usei1(i1 [[TEST1]])
+; CHECK-NEXT: [[RES:%.*]] = and i1 [[TEST1]], [[TEST2]]
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %cast = bitcast float %num to i32
+ %masked = and i32 %cast, 2139095040
+ %test1 = icmp ne i32 %masked, 2139095040
+ %test2 = icmp ne i32 %masked, 0
+ call void @usei1(i1 %test1)
+ %res = and i1 %test1, %test2
+ ret i1 %res
+}
+
declare void @usei32(i32)
+declare void @usei1(i1)
attributes #0 = { noimplicitfloat }
More information about the llvm-commits
mailing list