Skip to content

Commit cb419c7

Browse files
committed
[InstCombine] Enable more fabs fold when the user ignores sign bit of zero/NaN
1 parent 7add1bc commit cb419c7

File tree

3 files changed

+50
-17
lines changed

3 files changed

+50
-17
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,6 +2773,47 @@ Instruction *InstCombinerImpl::foldAndOrOfSelectUsingImpliedCond(Value *Op,
27732773
return nullptr;
27742774
}
27752775

2776+
/// Return true if the sign bit of result can be ignored when the result is
2777+
/// zero.
2778+
static bool ignoreSignBitOfZero(Instruction &I) {
2779+
if (I.hasNoSignedZeros())
2780+
return true;
2781+
2782+
// Check if the sign bit is ignored by the only user.
2783+
if (!I.hasOneUse())
2784+
return false;
2785+
Instruction *User = I.user_back();
2786+
2787+
// fcmp treats both positive and negative zero as equal.
2788+
if (User->getOpcode() == Instruction::FCmp)
2789+
return true;
2790+
2791+
if (auto *FPOp = dyn_cast<FPMathOperator>(User))
2792+
return FPOp->hasNoSignedZeros();
2793+
2794+
return false;
2795+
}
2796+
2797+
/// Return true if the sign bit of result can be ignored when the result is NaN.
2798+
static bool ignoreSignBitOfNaN(Instruction &I) {
2799+
if (I.hasNoNaNs())
2800+
return true;
2801+
2802+
// Check if the sign bit is ignored by the only user.
2803+
if (!I.hasOneUse())
2804+
return false;
2805+
Instruction *User = I.user_back();
2806+
2807+
// fcmp ignores the sign bit of NaN.
2808+
if (User->getOpcode() == Instruction::FCmp)
2809+
return true;
2810+
2811+
if (auto *FPOp = dyn_cast<FPMathOperator>(User))
2812+
return FPOp->hasNoNaNs();
2813+
2814+
return false;
2815+
}
2816+
27762817
// Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need
27772818
// fast-math-flags (nsz) or fsub with +0.0 (not fneg) for this to work.
27782819
static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
@@ -2797,7 +2838,7 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
27972838
// of NAN, but IEEE-754 specifies the signbit of NAN values with
27982839
// fneg/fabs operations.
27992840
if (match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(X))) &&
2800-
(cast<FPMathOperator>(CondVal)->hasNoNaNs() || SI.hasNoNaNs() ||
2841+
(cast<FPMathOperator>(CondVal)->hasNoNaNs() || ignoreSignBitOfNaN(SI) ||
28012842
isKnownNeverNaN(X, /*Depth=*/0,
28022843
IC.getSimplifyQuery().getWithInstruction(
28032844
cast<Instruction>(CondVal))))) {
@@ -2844,7 +2885,7 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
28442885
// Note: We require "nnan" for this fold because fcmp ignores the signbit
28452886
// of NAN, but IEEE-754 specifies the signbit of NAN values with
28462887
// fneg/fabs operations.
2847-
if (!SI.hasNoSignedZeros() || !SI.hasNoNaNs())
2888+
if (!ignoreSignBitOfZero(SI) || !ignoreSignBitOfNaN(SI))
28482889
return nullptr;
28492890

28502891
if (Swap)

llvm/test/Transforms/InstCombine/fabs.ll

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,9 +1279,7 @@ define <2 x float> @test_select_neg_negx_x_wrong_type(<2 x float> %value) {
12791279

12801280
define i1 @test_fabs_used_by_fcmp(float %x, float %y) {
12811281
; CHECK-LABEL: @test_fabs_used_by_fcmp(
1282-
; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
1283-
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
1284-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
1282+
; CHECK-NEXT: [[SEL:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
12851283
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[SEL]], [[Y:%.*]]
12861284
; CHECK-NEXT: ret i1 [[CMP2]]
12871285
;
@@ -1294,9 +1292,7 @@ define i1 @test_fabs_used_by_fcmp(float %x, float %y) {
12941292

12951293
define float @test_fabs_used_by_fpop_nnan_nsz(float %x, float %y) {
12961294
; CHECK-LABEL: @test_fabs_used_by_fpop_nnan_nsz(
1297-
; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
1298-
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X]]
1299-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
1295+
; CHECK-NEXT: [[SEL:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
13001296
; CHECK-NEXT: [[ADD:%.*]] = fadd nnan nsz float [[SEL]], [[Y:%.*]]
13011297
; CHECK-NEXT: ret float [[ADD]]
13021298
;
@@ -1309,9 +1305,7 @@ define float @test_fabs_used_by_fpop_nnan_nsz(float %x, float %y) {
13091305

13101306
define i1 @test_fabs_fsub_used_by_fcmp(float %x, float %y) {
13111307
; CHECK-LABEL: @test_fabs_fsub_used_by_fcmp(
1312-
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00
1313-
; CHECK-NEXT: [[NEG:%.*]] = fsub float 0.000000e+00, [[X]]
1314-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
1308+
; CHECK-NEXT: [[SEL:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
13151309
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[SEL]], [[Y:%.*]]
13161310
; CHECK-NEXT: ret i1 [[CMP2]]
13171311
;
@@ -1324,9 +1318,7 @@ define i1 @test_fabs_fsub_used_by_fcmp(float %x, float %y) {
13241318

13251319
define float @test_fabs_fsub_used_by_fpop_nnan(float %x, float %y) {
13261320
; CHECK-LABEL: @test_fabs_fsub_used_by_fpop_nnan(
1327-
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00
1328-
; CHECK-NEXT: [[NEG:%.*]] = fsub float 0.000000e+00, [[X]]
1329-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float [[X]], float [[NEG]]
1321+
; CHECK-NEXT: [[SEL:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
13301322
; CHECK-NEXT: [[ADD:%.*]] = fadd nnan float [[SEL]], [[Y:%.*]]
13311323
; CHECK-NEXT: ret float [[ADD]]
13321324
;

llvm/test/Transforms/InstCombine/fneg.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ define float @select_common_op_fneg_false(float %x, i1 %b) {
709709

710710
define float @fabs(float %a) {
711711
; CHECK-LABEL: @fabs(
712-
; CHECK-NEXT: [[FNEG1:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[A:%.*]])
712+
; CHECK-NEXT: [[FNEG1:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
713713
; CHECK-NEXT: ret float [[FNEG1]]
714714
;
715715
%fneg = fneg float %a
@@ -721,7 +721,7 @@ define float @fabs(float %a) {
721721

722722
define float @fnabs(float %a) {
723723
; CHECK-LABEL: @fnabs(
724-
; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.fabs.f32(float [[A:%.*]])
724+
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
725725
; CHECK-NEXT: [[FNEG1:%.*]] = fneg fast float [[TMP1]]
726726
; CHECK-NEXT: ret float [[FNEG1]]
727727
;
@@ -734,7 +734,7 @@ define float @fnabs(float %a) {
734734

735735
define float @fnabs_1(float %a) {
736736
; CHECK-LABEL: @fnabs_1(
737-
; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.fabs.f32(float [[A:%.*]])
737+
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
738738
; CHECK-NEXT: [[FNEG1:%.*]] = fneg fast float [[TMP1]]
739739
; CHECK-NEXT: ret float [[FNEG1]]
740740
;

0 commit comments

Comments
 (0)