Skip to content

Commit 2b58244

Browse files
committed
InstCombine: Fold is.fpclass(x, fcInf) to fabs+fcmp
This is a better canonical form. fcmp and fabs are more widely understood and fabs can fold for free into some sources. Addresses todo from D146170 https://reviews.llvm.org/D159084
1 parent e8824e0 commit 2b58244

File tree

5 files changed

+88
-46
lines changed

5 files changed

+88
-46
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,23 @@ Instruction *InstCombinerImpl::foldIntrinsicIsFPClass(IntrinsicInst &II) {
903903
return replaceOperand(II, 0, FAbsSrc);
904904
}
905905

906-
// TODO: is.fpclass(x, fcInf) -> fabs(x) == inf
906+
if ((OrderedMask == fcInf || OrderedInvertedMask == fcInf) &&
907+
(IsOrdered || IsUnordered) && !IsStrict) {
908+
// is.fpclass(x, fcInf) -> fcmp oeq fabs(x), +inf
909+
// is.fpclass(x, ~fcInf) -> fcmp one fabs(x), +inf
910+
// is.fpclass(x, fcInf|fcNan) -> fcmp ueq fabs(x), +inf
911+
// is.fpclass(x, ~(fcInf|fcNan)) -> fcmp une fabs(x), +inf
912+
Constant *Inf = ConstantFP::getInfinity(Src0->getType());
913+
FCmpInst::Predicate Pred =
914+
IsUnordered ? FCmpInst::FCMP_UEQ : FCmpInst::FCMP_OEQ;
915+
if (OrderedInvertedMask == fcInf)
916+
Pred = IsUnordered ? FCmpInst::FCMP_UNE : FCmpInst::FCMP_ONE;
917+
918+
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, Src0);
919+
Value *CmpInf = Builder.CreateFCmp(Pred, Fabs, Inf);
920+
CmpInf->takeName(&II);
921+
return replaceInstUsesWith(II, CmpInf);
922+
}
907923

908924
if ((OrderedMask == fcPosInf || OrderedMask == fcNegInf) &&
909925
(IsOrdered || IsUnordered) && !IsStrict) {

llvm/test/Transforms/InstCombine/and-fcmp.ll

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4794,7 +4794,8 @@ define i1 @clang_builtin_isnormal_inf_check_ord(half %x) {
47944794

47954795
define i1 @clang_builtin_isnormal_inf_check_oge(half %x) {
47964796
; CHECK-LABEL: @clang_builtin_isnormal_inf_check_oge(
4797-
; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516)
4797+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
4798+
; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[TMP1]], 0xH7C00
47984799
; CHECK-NEXT: ret i1 [[AND]]
47994800
;
48004801
%fabs.x = call half @llvm.fabs.f16(half %x)
@@ -4806,7 +4807,8 @@ define i1 @clang_builtin_isnormal_inf_check_oge(half %x) {
48064807

48074808
define i1 @clang_builtin_isnormal_inf_check_olt(half %x) {
48084809
; CHECK-LABEL: @clang_builtin_isnormal_inf_check_olt(
4809-
; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 504)
4810+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
4811+
; CHECK-NEXT: [[AND:%.*]] = fcmp one half [[TMP1]], 0xH7C00
48104812
; CHECK-NEXT: ret i1 [[AND]]
48114813
;
48124814
%fabs.x = call half @llvm.fabs.f16(half %x)
@@ -4833,7 +4835,8 @@ define i1 @clang_builtin_isnormal_inf_check_ole(half %x) {
48334835

48344836
define i1 @clang_builtin_isnormal_inf_check_oeq(half %x) {
48354837
; CHECK-LABEL: @clang_builtin_isnormal_inf_check_oeq(
4836-
; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516)
4838+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
4839+
; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[TMP1]], 0xH7C00
48374840
; CHECK-NEXT: ret i1 [[AND]]
48384841
;
48394842
%fabs.x = call half @llvm.fabs.f16(half %x)

llvm/test/Transforms/InstCombine/combine-is.fpclass-and-fcmp.ll

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ define i1 @fcmp_isfinite_and_class_subnormal(half %x) {
135135

136136
define i1 @fcmp_isfinite_or_class_subnormal(half %x) {
137137
; CHECK-LABEL: @fcmp_isfinite_or_class_subnormal(
138-
; CHECK-NEXT: [[SUBNORMAL_CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 504)
138+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
139+
; CHECK-NEXT: [[SUBNORMAL_CLASS:%.*]] = fcmp one half [[TMP1]], 0xH7C00
139140
; CHECK-NEXT: ret i1 [[SUBNORMAL_CLASS]]
140141
;
141142
%fabs = call half @llvm.fabs.f16(half %x)
@@ -148,8 +149,9 @@ define i1 @fcmp_isfinite_or_class_subnormal(half %x) {
148149
; -> isfinite
149150
define i1 @fcmp_issubnormal_or_class_finite(half %x) {
150151
; CHECK-LABEL: @fcmp_issubnormal_or_class_finite(
151-
; CHECK-NEXT: [[IS_FINITE_CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 504)
152-
; CHECK-NEXT: ret i1 [[IS_FINITE_CLASS]]
152+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
153+
; CHECK-NEXT: [[OR:%.*]] = fcmp one half [[TMP1]], 0xH7C00
154+
; CHECK-NEXT: ret i1 [[OR]]
153155
;
154156
%fabs = call half @llvm.fabs.f16(half %x)
155157
%is.subnormal = fcmp olt half %fabs, 0xH0400
@@ -161,8 +163,9 @@ define i1 @fcmp_issubnormal_or_class_finite(half %x) {
161163
; -> isfinite
162164
define i1 @class_finite_or_fcmp_issubnormal(half %x) {
163165
; CHECK-LABEL: @class_finite_or_fcmp_issubnormal(
164-
; CHECK-NEXT: [[IS_FINITE_CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 504)
165-
; CHECK-NEXT: ret i1 [[IS_FINITE_CLASS]]
166+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
167+
; CHECK-NEXT: [[OR:%.*]] = fcmp one half [[TMP1]], 0xH7C00
168+
; CHECK-NEXT: ret i1 [[OR]]
166169
;
167170
%fabs = call half @llvm.fabs.f16(half %x)
168171
%is.subnormal = fcmp olt half %fabs, 0xH0400
@@ -174,8 +177,8 @@ define i1 @class_finite_or_fcmp_issubnormal(half %x) {
174177
; -> issubnormal
175178
define i1 @fcmp_issubnormal_and_class_finite(half %x) {
176179
; CHECK-LABEL: @fcmp_issubnormal_and_class_finite(
177-
; CHECK-NEXT: [[IS_FINITE_CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 240)
178-
; CHECK-NEXT: ret i1 [[IS_FINITE_CLASS]]
180+
; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 240)
181+
; CHECK-NEXT: ret i1 [[AND]]
179182
;
180183
%fabs = call half @llvm.fabs.f16(half %x)
181184
%is.subnormal = fcmp olt half %fabs, 0xH0400
@@ -186,8 +189,8 @@ define i1 @fcmp_issubnormal_and_class_finite(half %x) {
186189

187190
define i1 @class_inf_or_fcmp_issubnormal(half %x) {
188191
; CHECK-LABEL: @class_inf_or_fcmp_issubnormal(
189-
; CHECK-NEXT: [[IS_INF_CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 756)
190-
; CHECK-NEXT: ret i1 [[IS_INF_CLASS]]
192+
; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 756)
193+
; CHECK-NEXT: ret i1 [[OR]]
191194
;
192195
%fabs = call half @llvm.fabs.f16(half %x)
193196
%is.subnormal = fcmp olt half %fabs, 0xH0400
@@ -199,8 +202,9 @@ define i1 @class_inf_or_fcmp_issubnormal(half %x) {
199202
; -> isfinite
200203
define <2 x i1> @class_finite_or_fcmp_issubnormal_vector(<2 x half> %x) {
201204
; CHECK-LABEL: @class_finite_or_fcmp_issubnormal_vector(
202-
; CHECK-NEXT: [[IS_FINITE_CLASS:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X:%.*]], i32 504)
203-
; CHECK-NEXT: ret <2 x i1> [[IS_FINITE_CLASS]]
205+
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]])
206+
; CHECK-NEXT: [[OR:%.*]] = fcmp one <2 x half> [[TMP1]], <half 0xH7C00, half 0xH7C00>
207+
; CHECK-NEXT: ret <2 x i1> [[OR]]
204208
;
205209
%fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x)
206210
%is.subnormal = fcmp olt <2 x half> %fabs, <half 0xH0400, half 0xH0400>

llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ define i1 @olt_0_or_fabs_ueq_inf(half %x) {
250250
; Negative test
251251
define i1 @oeq_0_or_fabs_ult_inf(half %x) {
252252
; CHECK-LABEL: @oeq_0_or_fabs_ult_inf(
253-
; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 507)
253+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
254+
; CHECK-NEXT: [[CLASS:%.*]] = fcmp une half [[TMP1]], 0xH7C00
254255
; CHECK-NEXT: ret i1 [[CLASS]]
255256
;
256257
%fabs = call half @llvm.fabs.f16(half %x)
@@ -623,7 +624,8 @@ define i1 @fneg_fabs_olt_neg_smallest_normal_or_inf(half %x) {
623624

624625
define i1 @issubnormal_or_finite_olt(half %x) {
625626
; CHECK-LABEL: @issubnormal_or_finite_olt(
626-
; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 504)
627+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
628+
; CHECK-NEXT: [[OR:%.*]] = fcmp one half [[TMP1]], 0xH7C00
627629
; CHECK-NEXT: ret i1 [[OR]]
628630
;
629631
%fabs = call half @llvm.fabs.f16(half %x)
@@ -724,7 +726,8 @@ define i1 @is_finite_or_ord(half %x) {
724726

725727
define i1 @is_finite_or_uno(half %x) {
726728
; CHECK-LABEL: @is_finite_or_uno(
727-
; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 519)
729+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
730+
; CHECK-NEXT: [[OR:%.*]] = fcmp ueq half [[TMP1]], 0xH7C00
728731
; CHECK-NEXT: ret i1 [[OR]]
729732
;
730733
%fabs = call half @llvm.fabs.f16(half %x)
@@ -736,7 +739,8 @@ define i1 @is_finite_or_uno(half %x) {
736739

737740
define i1 @oeq_isinf_or_uno(half %x) {
738741
; CHECK-LABEL: @oeq_isinf_or_uno(
739-
; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 519)
742+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
743+
; CHECK-NEXT: [[CLASS:%.*]] = fcmp ueq half [[TMP1]], 0xH7C00
740744
; CHECK-NEXT: ret i1 [[CLASS]]
741745
;
742746
%fabs = call half @llvm.fabs.f16(half %x)
@@ -771,7 +775,8 @@ define i1 @oeq_isinf_and_uno(half %x) {
771775

772776
define i1 @oeq_isinf_and_ord(half %x) {
773777
; CHECK-LABEL: @oeq_isinf_and_ord(
774-
; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516)
778+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
779+
; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[TMP1]], 0xH7C00
775780
; CHECK-NEXT: ret i1 [[AND]]
776781
;
777782
%fabs = call half @llvm.fabs.f16(half %x)
@@ -902,7 +907,8 @@ define i1 @isnormalinf_or_posinf(half %x) #0 {
902907
; -> pinf|ninf
903908
define i1 @isnormalinf_and_inf(half %x) #0 {
904909
; CHECK-LABEL: @isnormalinf_and_inf(
905-
; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516)
910+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
911+
; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[TMP1]], 0xH7C00
906912
; CHECK-NEXT: ret i1 [[AND]]
907913
;
908914
%fabs = call half @llvm.fabs.f16(half %x)
@@ -970,7 +976,8 @@ define i1 @not_isnormalinf_and_ord(half %x) #0 {
970976
; -> ~ninf
971977
define i1 @not_isnormalinf_or_inf(half %x) #0 {
972978
; CHECK-LABEL: @not_isnormalinf_or_inf(
973-
; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 507)
979+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
980+
; CHECK-NEXT: [[OR:%.*]] = fcmp une half [[TMP1]], 0xH7C00
974981
; CHECK-NEXT: ret i1 [[OR]]
975982
;
976983
%fabs = call half @llvm.fabs.f16(half %x)
@@ -1287,7 +1294,8 @@ define i1 @olt_smallest_normal_and_une_inf_or_one_smallest_normal(half %x) #0 {
12871294

12881295
define i1 @oge_fabs_eq_inf_and_ord(half %x) #0 {
12891296
; CHECK-LABEL: @oge_fabs_eq_inf_and_ord(
1290-
; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516)
1297+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
1298+
; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[TMP1]], 0xH7C00
12911299
; CHECK-NEXT: ret i1 [[AND]]
12921300
;
12931301
%fabs = call half @llvm.fabs.f16(half %x)
@@ -1310,7 +1318,8 @@ define i1 @oge_eq_inf_and_ord(half %x) #0 {
13101318

13111319
define i1 @oge_fabs_eq_inf_or_uno(half %x) #0 {
13121320
; CHECK-LABEL: @oge_fabs_eq_inf_or_uno(
1313-
; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 519)
1321+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
1322+
; CHECK-NEXT: [[OR:%.*]] = fcmp ueq half [[TMP1]], 0xH7C00
13141323
; CHECK-NEXT: ret i1 [[OR]]
13151324
;
13161325
%fabs = call half @llvm.fabs.f16(half %x)
@@ -1357,7 +1366,8 @@ define i1 @ult_eq_inf_and_ord(half %x) #0 {
13571366

13581367
define i1 @ult_fabs_eq_inf_or_uno(half %x) #0 {
13591368
; CHECK-LABEL: @ult_fabs_eq_inf_or_uno(
1360-
; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 507)
1369+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
1370+
; CHECK-NEXT: [[OR:%.*]] = fcmp une half [[TMP1]], 0xH7C00
13611371
; CHECK-NEXT: ret i1 [[OR]]
13621372
;
13631373
%fabs = call half @llvm.fabs.f16(half %x)

0 commit comments

Comments
 (0)