Skip to content

Commit 42ed775

Browse files
authored
[InstSimplify] Generalize simplifyAndOrOfFCmps to handle fabs (#116590)
This patch generalizes #81027 to handle pattern `and/or (fcmp ord/uno X, 0), (fcmp pred fabs(X), Y)`. Alive2: https://alive2.llvm.org/ce/z/tsgUrz The correctness is straightforward because `fcmp ord/uno X, 0.0` is equivalent to `fcmp ord/uno fabs(X), 0.0`. We may generalize it to handle fneg as well. Address comment #116065 (review)
1 parent a59976b commit 42ed775

File tree

4 files changed

+83
-15
lines changed

4 files changed

+83
-15
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

+14-10
Original file line numberDiff line numberDiff line change
@@ -1857,27 +1857,31 @@ static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS,
18571857
return nullptr;
18581858

18591859
FCmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
1860+
auto AbsOrSelfLHS0 = m_CombineOr(m_Specific(LHS0), m_FAbs(m_Specific(LHS0)));
18601861
if ((PredL == FCmpInst::FCMP_ORD || PredL == FCmpInst::FCMP_UNO) &&
18611862
((FCmpInst::isOrdered(PredR) && IsAnd) ||
18621863
(FCmpInst::isUnordered(PredR) && !IsAnd))) {
1863-
// (fcmp ord X, 0) & (fcmp o** X, Y) --> fcmp o** X, Y
1864-
// (fcmp uno X, 0) & (fcmp o** X, Y) --> false
1865-
// (fcmp uno X, 0) | (fcmp u** X, Y) --> fcmp u** X, Y
1866-
// (fcmp ord X, 0) | (fcmp u** X, Y) --> true
1867-
if ((LHS0 == RHS0 || LHS0 == RHS1) && match(LHS1, m_PosZeroFP()))
1864+
// (fcmp ord X, 0) & (fcmp o** X/abs(X), Y) --> fcmp o** X/abs(X), Y
1865+
// (fcmp uno X, 0) & (fcmp o** X/abs(X), Y) --> false
1866+
// (fcmp uno X, 0) | (fcmp u** X/abs(X), Y) --> fcmp u** X/abs(X), Y
1867+
// (fcmp ord X, 0) | (fcmp u** X/abs(X), Y) --> true
1868+
if ((match(RHS0, AbsOrSelfLHS0) || match(RHS1, AbsOrSelfLHS0)) &&
1869+
match(LHS1, m_PosZeroFP()))
18681870
return FCmpInst::isOrdered(PredL) == FCmpInst::isOrdered(PredR)
18691871
? static_cast<Value *>(RHS)
18701872
: ConstantInt::getBool(LHS->getType(), !IsAnd);
18711873
}
18721874

1875+
auto AbsOrSelfRHS0 = m_CombineOr(m_Specific(RHS0), m_FAbs(m_Specific(RHS0)));
18731876
if ((PredR == FCmpInst::FCMP_ORD || PredR == FCmpInst::FCMP_UNO) &&
18741877
((FCmpInst::isOrdered(PredL) && IsAnd) ||
18751878
(FCmpInst::isUnordered(PredL) && !IsAnd))) {
1876-
// (fcmp o** X, Y) & (fcmp ord X, 0) --> fcmp o** X, Y
1877-
// (fcmp o** X, Y) & (fcmp uno X, 0) --> false
1878-
// (fcmp u** X, Y) | (fcmp uno X, 0) --> fcmp u** X, Y
1879-
// (fcmp u** X, Y) | (fcmp ord X, 0) --> true
1880-
if ((RHS0 == LHS0 || RHS0 == LHS1) && match(RHS1, m_PosZeroFP()))
1879+
// (fcmp o** X/abs(X), Y) & (fcmp ord X, 0) --> fcmp o** X/abs(X), Y
1880+
// (fcmp o** X/abs(X), Y) & (fcmp uno X, 0) --> false
1881+
// (fcmp u** X/abs(X), Y) | (fcmp uno X, 0) --> fcmp u** X/abs(X), Y
1882+
// (fcmp u** X/abs(X), Y) | (fcmp ord X, 0) --> true
1883+
if ((match(LHS0, AbsOrSelfRHS0) || match(LHS1, AbsOrSelfRHS0)) &&
1884+
match(RHS1, m_PosZeroFP()))
18811885
return FCmpInst::isOrdered(PredL) == FCmpInst::isOrdered(PredR)
18821886
? static_cast<Value *>(LHS)
18831887
: ConstantInt::getBool(LHS->getType(), !IsAnd);

llvm/test/CodeGen/AMDGPU/fp-classify.ll

-3
Original file line numberDiff line numberDiff line change
@@ -698,12 +698,9 @@ define amdgpu_kernel void @test_isfinite_pattern_4_f16(ptr addrspace(1) nocaptur
698698
; SI-NEXT: s_mov_b32 s3, 0xf000
699699
; SI-NEXT: s_mov_b32 s2, -1
700700
; SI-NEXT: s_waitcnt lgkmcnt(0)
701-
; SI-NEXT: v_cvt_f32_f16_e32 v0, s6
702701
; SI-NEXT: s_and_b32 s4, s6, 0x7fff
703-
; SI-NEXT: v_cmp_o_f32_e32 vcc, v0, v0
704702
; SI-NEXT: s_cmpk_lt_i32 s4, 0x7c00
705703
; SI-NEXT: s_cselect_b64 s[4:5], -1, 0
706-
; SI-NEXT: s_and_b64 s[4:5], vcc, s[4:5]
707704
; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5]
708705
; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0
709706
; SI-NEXT: s_endpgm

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,8 @@ define i1 @not_isnormalinf_or_inf(half %x) #0 {
990990
; -> subnormal | zero | nan
991991
define i1 @not_isnormalinf_or_uno(half %x) #0 {
992992
; CHECK-LABEL: @not_isnormalinf_or_uno(
993-
; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 243)
993+
; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
994+
; CHECK-NEXT: [[OR:%.*]] = fcmp ult half [[FABS]], 0xH0400
994995
; CHECK-NEXT: ret i1 [[OR]]
995996
;
996997
%fabs = call half @llvm.fabs.f16(half %x)
@@ -1003,7 +1004,8 @@ define i1 @not_isnormalinf_or_uno(half %x) #0 {
10031004
; -> subnormal | zero | nan
10041005
define i1 @not_isnormalinf_or_uno_nofabs(half %x) #0 {
10051006
; CHECK-LABEL: @not_isnormalinf_or_uno_nofabs(
1006-
; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 243)
1007+
; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
1008+
; CHECK-NEXT: [[OR:%.*]] = fcmp ult half [[FABS]], 0xH0400
10071009
; CHECK-NEXT: ret i1 [[OR]]
10081010
;
10091011
%fabs = call half @llvm.fabs.f16(half %x)

llvm/test/Transforms/InstSimplify/logic-of-fcmps.ll

+65
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,68 @@ define i1 @olt_implies_olt_fail(float %x, float %y) {
426426
%ret = and i1 %olt, %olt2
427427
ret i1 %ret
428428
}
429+
430+
define i1 @and_ord_olt_abs(float %x, float %y) {
431+
; CHECK-LABEL: @and_ord_olt_abs(
432+
; CHECK-NEXT: [[ABSX:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
433+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[ABSX]], [[Y:%.*]]
434+
; CHECK-NEXT: ret i1 [[CMP2]]
435+
;
436+
%cmp1 = fcmp ord float %x, 0.000000e+00
437+
%absx = call float @llvm.fabs.f32(float %x)
438+
%cmp2 = fcmp olt float %absx, %y
439+
%and = and i1 %cmp1, %cmp2
440+
ret i1 %and
441+
}
442+
443+
define i1 @and_ord_olt_abs_commuted1(float %x, float %y) {
444+
; CHECK-LABEL: @and_ord_olt_abs_commuted1(
445+
; CHECK-NEXT: [[ABSX:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
446+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[Y:%.*]], [[ABSX]]
447+
; CHECK-NEXT: ret i1 [[CMP2]]
448+
;
449+
%cmp1 = fcmp ord float %x, 0.000000e+00
450+
%absx = call float @llvm.fabs.f32(float %x)
451+
%cmp2 = fcmp olt float %y, %absx
452+
%and = and i1 %cmp1, %cmp2
453+
ret i1 %and
454+
}
455+
456+
define i1 @and_ord_olt_abs_commuted2(float %x, float %y) {
457+
; CHECK-LABEL: @and_ord_olt_abs_commuted2(
458+
; CHECK-NEXT: [[ABSX:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
459+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[ABSX]], [[Y:%.*]]
460+
; CHECK-NEXT: ret i1 [[CMP2]]
461+
;
462+
%cmp1 = fcmp ord float %x, 0.000000e+00
463+
%absx = call float @llvm.fabs.f32(float %x)
464+
%cmp2 = fcmp olt float %absx, %y
465+
%and = and i1 %cmp2, %cmp1
466+
ret i1 %and
467+
}
468+
469+
define i1 @or_ord_ult_abs(float %x, float %y) {
470+
; CHECK-LABEL: @or_ord_ult_abs(
471+
; CHECK-NEXT: ret i1 true
472+
;
473+
%cmp1 = fcmp ord float %x, 0.000000e+00
474+
%absx = call float @llvm.fabs.f32(float %x)
475+
%cmp2 = fcmp ult float %absx, %y
476+
%or = or i1 %cmp1, %cmp2
477+
ret i1 %or
478+
}
479+
480+
define i1 @and_ord_olt_absz(float %x, float %y, float %z) {
481+
; CHECK-LABEL: @and_ord_olt_absz(
482+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
483+
; CHECK-NEXT: [[ABSZ:%.*]] = call float @llvm.fabs.f32(float [[Z:%.*]])
484+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[ABSZ]], [[Y:%.*]]
485+
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
486+
; CHECK-NEXT: ret i1 [[AND]]
487+
;
488+
%cmp1 = fcmp ord float %x, 0.000000e+00
489+
%absz = call float @llvm.fabs.f32(float %z)
490+
%cmp2 = fcmp olt float %absz, %y
491+
%and = and i1 %cmp1, %cmp2
492+
ret i1 %and
493+
}

0 commit comments

Comments
 (0)