Skip to content

Commit 1f69d63

Browse files
authored
[InstCombine] Preserve the sign bit of NaN in SimplifyDemandedUseFPClass (#137287)
Alive2: https://alive2.llvm.org/ce/z/uiUzEf Closes #137196. Note: To avoid regression in `ret_nofpclass_nopositives_copysign_nnan_flag`, the second commit takes FMF into account.
1 parent be7cf63 commit 1f69d63

File tree

2 files changed

+35
-19
lines changed

2 files changed

+35
-19
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,9 +1959,11 @@ static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
19591959
}
19601960
}
19611961

1962-
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
1963-
Value *V, const FPClassTest DemandedMask, KnownFPClass &Known,
1964-
unsigned Depth, Instruction *CxtI) {
1962+
Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
1963+
FPClassTest DemandedMask,
1964+
KnownFPClass &Known,
1965+
unsigned Depth,
1966+
Instruction *CxtI) {
19651967
assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
19661968
Type *VTy = V->getType();
19671969

@@ -1985,7 +1987,12 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
19851987
if (!I->hasOneUse())
19861988
return nullptr;
19871989

1988-
// TODO: Should account for nofpclass/FastMathFlags on current instruction
1990+
if (auto *FPOp = dyn_cast<FPMathOperator>(I)) {
1991+
if (FPOp->hasNoNaNs())
1992+
DemandedMask &= ~fcNan;
1993+
if (FPOp->hasNoInfs())
1994+
DemandedMask &= ~fcInf;
1995+
}
19891996
switch (I->getOpcode()) {
19901997
case Instruction::FNeg: {
19911998
if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
@@ -2013,13 +2020,13 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
20132020
if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
20142021
return I;
20152022

2016-
if ((DemandedMask & fcPositive) == fcNone) {
2023+
if ((DemandedMask & fcNegative) == DemandedMask) {
20172024
// Roundabout way of replacing with fneg(fabs)
20182025
I->setOperand(1, ConstantFP::get(VTy, -1.0));
20192026
return I;
20202027
}
20212028

2022-
if ((DemandedMask & fcNegative) == fcNone) {
2029+
if ((DemandedMask & fcPositive) == DemandedMask) {
20232030
// Roundabout way of replacing with fabs
20242031
I->setOperand(1, ConstantFP::getZero(VTy));
20252032
return I;

llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -678,12 +678,11 @@ define nofpclass(inf) float @ret_nofpclass_inf__copysign_negative_select_pinf_rh
678678
ret float %copysign
679679
}
680680

681-
; can fold to fneg(fabs(x))
681+
; can't fold to fneg(fabs(x))
682682
define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives_copysign(float %x, float %unknown.sign) {
683683
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives_copysign
684684
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
685-
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
686-
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
685+
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
687686
; CHECK-NEXT: ret float [[COPYSIGN]]
688687
;
689688
%copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
@@ -703,6 +702,18 @@ define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives_copysig
703702
}
704703

705704
; can fold to fneg(fabs(x))
705+
define nofpclass(pnorm psub pzero) float @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag(float %x, float %unknown.sign) {
706+
; CHECK-LABEL: define nofpclass(pzero psub pnorm) float @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag
707+
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
708+
; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf float @llvm.fabs.f32(float [[X]])
709+
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan ninf float [[TMP1]]
710+
; CHECK-NEXT: ret float [[COPYSIGN]]
711+
;
712+
%copysign = call nnan ninf float @llvm.copysign.f32(float %x, float %unknown.sign)
713+
ret float %copysign
714+
}
715+
716+
; can't fold to fneg(fabs(x))
706717
define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_nopositives_nonan_copysign(float %x, float %unknown.sign) {
707718
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_nopositives_nonan_copysign
708719
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
@@ -714,11 +725,11 @@ define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_nopositives_non
714725
ret float %copysign
715726
}
716727

717-
; can fold to fabs(x)
728+
; can't fold to fabs(x)
718729
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_copysign(float %x, float %unknown.sign) {
719730
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_copysign
720731
; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
721-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]])
732+
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
722733
; CHECK-NEXT: ret float [[COPYSIGN]]
723734
;
724735
%copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
@@ -763,7 +774,7 @@ define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives__copysi
763774
define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
764775
; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs
765776
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
766-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]])
777+
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
767778
; CHECK-NEXT: ret float [[COPYSIGN]]
768779
;
769780
%select = select i1 %cond, float %x, float 0x7FF0000000000000
@@ -775,8 +786,7 @@ define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_no_negatives_noinf__
775786
define nofpclass(inf pnorm psub pzero) float @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
776787
; CHECK-LABEL: define nofpclass(inf pzero psub pnorm) float @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs
777788
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
778-
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
779-
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
789+
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
780790
; CHECK-NEXT: ret float [[COPYSIGN]]
781791
;
782792
%select = select i1 %cond, float %x, float 0x7FF0000000000000
@@ -788,8 +798,8 @@ define nofpclass(inf pnorm psub pzero) float @ret_nofpclass_no_positives_noinf__
788798
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
789799
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs
790800
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
791-
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
792-
; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
801+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
802+
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[SELECT]], float [[UNKNOWN_SIGN]])
793803
; CHECK-NEXT: ret float [[COPYSIGN]]
794804
;
795805
%select = select i1 %cond, float %x, float 0x7FF0000000000000
@@ -801,9 +811,8 @@ define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copys
801811
define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
802812
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs
803813
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
804-
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
805-
; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]]
806-
; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[DOTNEG]], float 0xFFF0000000000000
814+
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
815+
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[SELECT]], float [[UNKNOWN_SIGN]])
807816
; CHECK-NEXT: ret float [[COPYSIGN]]
808817
;
809818
%select = select i1 %cond, float %x, float 0x7FF0000000000000

0 commit comments

Comments
 (0)