Skip to content

Commit 282a065

Browse files
authored
InstCombine: Handle multiple uses fabs in SimplifyDemandedFPClass (llvm#176035)
1 parent a866030 commit 282a065

3 files changed

Lines changed: 119 additions & 0 deletions

File tree

llvm/include/llvm/Support/KnownFPClass.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ struct KnownFPClass {
192192
signBitMustBeZero();
193193
}
194194

195+
static KnownFPClass fabs(const KnownFPClass &Src) {
196+
KnownFPClass Known = Src;
197+
Known.fabs();
198+
return Known;
199+
}
200+
195201
// Enum of min/max intrinsics to avoid dependency on IR.
196202
enum class MinMaxKind {
197203
minimum,

llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2955,6 +2955,16 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
29552955
Value *InstCombinerImpl::SimplifyMultipleUseDemandedFPClass(
29562956
Instruction *I, FPClassTest DemandedMask, KnownFPClass &Known,
29572957
Instruction *CxtI, unsigned Depth) {
2958+
FastMathFlags FMF;
2959+
if (auto *FPOp = dyn_cast<FPMathOperator>(I)) {
2960+
FMF = FPOp->getFastMathFlags();
2961+
if (FMF.noNaNs())
2962+
DemandedMask &= ~fcNan;
2963+
2964+
if (FMF.noInfs())
2965+
DemandedMask &= ~fcInf;
2966+
}
2967+
29582968
switch (I->getOpcode()) {
29592969
case Instruction::Select: {
29602970
// TODO: Can we infer which side it came from based on adjusted result
@@ -2981,6 +2991,24 @@ Value *InstCombinerImpl::SimplifyMultipleUseDemandedFPClass(
29812991
const CallInst *CI = cast<CallInst>(I);
29822992
const Intrinsic::ID IID = CI->getIntrinsicID();
29832993
switch (IID) {
2994+
case Intrinsic::fabs: {
2995+
Value *Src = CI->getArgOperand(0);
2996+
KnownFPClass KnownSrc =
2997+
computeKnownFPClass(Src, fcAllFlags, CxtI, Depth + 1);
2998+
2999+
if ((DemandedMask & fcNan) == fcNone)
3000+
KnownSrc.knownNot(fcNan);
3001+
if ((DemandedMask & fcInf) == fcNone)
3002+
KnownSrc.knownNot(fcInf);
3003+
3004+
// TODO: If the only sign bit difference is due to -0, look at source if
3005+
// nsz.
3006+
if (KnownSrc.SignBit == false || ((DemandedMask & fcNan) == fcNone &&
3007+
KnownSrc.isKnownNever(fcNegative)))
3008+
return Src;
3009+
Known = KnownFPClass::fabs(KnownSrc);
3010+
break;
3011+
}
29843012
case Intrinsic::maximum:
29853013
case Intrinsic::minimum:
29863014
case Intrinsic::maximumnum:

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

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,91 @@ define nofpclass(nan) float @ret_nonan_fabs_src_known_positive_or_nan(float nofp
682682
ret float %fabs
683683
}
684684

685+
define nofpclass(snan) float @fabs_src_known_positive_multiple_uses(float nofpclass(nan ninf nnorm nsub nzero) %always.positive, ptr %ptr) {
686+
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_positive_multiple_uses
687+
; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ALWAYS_POSITIVE:%.*]], ptr [[PTR:%.*]]) {
688+
; CHECK-NEXT: store float [[ALWAYS_POSITIVE]], ptr [[PTR]], align 4
689+
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE]]
690+
;
691+
%fabs = call float @llvm.fabs.f32(float %always.positive)
692+
store float %fabs, ptr %ptr
693+
ret float %fabs
694+
}
695+
696+
define nofpclass(snan) float @fabs_src_known_positive_except_negzero_multiple_uses(float nofpclass(nan ninf nnorm nsub) %always.positive.or.nzero, ptr %ptr) {
697+
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_positive_except_negzero_multiple_uses
698+
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_NZERO:%.*]], ptr [[PTR:%.*]]) {
699+
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NZERO]])
700+
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
701+
; CHECK-NEXT: ret float [[FABS]]
702+
;
703+
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nzero)
704+
store float %fabs, ptr %ptr
705+
ret float %fabs
706+
}
707+
708+
define nofpclass(snan) float @fabs_nsz_src_known_positive_except_negzero_multiple_uses(float nofpclass(nan ninf nnorm nsub) %always.positive.or.nzero, ptr %ptr) {
709+
; CHECK-LABEL: define nofpclass(snan) float @fabs_nsz_src_known_positive_except_negzero_multiple_uses
710+
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_NZERO:%.*]], ptr [[PTR:%.*]]) {
711+
; CHECK-NEXT: [[FABS:%.*]] = call nsz float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NZERO]])
712+
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
713+
; CHECK-NEXT: ret float [[FABS]]
714+
;
715+
%fabs = call nsz float @llvm.fabs.f32(float %always.positive.or.nzero)
716+
store float %fabs, ptr %ptr
717+
ret float %fabs
718+
}
719+
720+
define nofpclass(snan) float @fabs_src_known_positive_or_nan_multiple_uses(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, ptr %ptr) {
721+
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_positive_or_nan_multiple_uses
722+
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
723+
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NAN]])
724+
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
725+
; CHECK-NEXT: ret float [[FABS]]
726+
;
727+
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nan)
728+
store float %fabs, ptr %ptr
729+
ret float %fabs
730+
}
731+
732+
define nofpclass(nan) float @ret_nonan_fabs_src_known_positive_or_nan_multiple_uses(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, ptr %ptr) {
733+
; CHECK-LABEL: define nofpclass(nan) float @ret_nonan_fabs_src_known_positive_or_nan_multiple_uses
734+
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
735+
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NAN]])
736+
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
737+
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NAN]]
738+
;
739+
%fabs = call float @llvm.fabs.f32(float %always.positive.or.nan)
740+
store float %fabs, ptr %ptr
741+
ret float %fabs
742+
}
743+
744+
; Take no-nan from flag
745+
define nofpclass(nsub) float @ret_fabs_nnan_src_known_positive_or_nan_multiple_uses(float nofpclass(ninf nnorm nsub nzero) %always.positive.or.nan, ptr %ptr) {
746+
; CHECK-LABEL: define nofpclass(nsub) float @ret_fabs_nnan_src_known_positive_or_nan_multiple_uses
747+
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NAN:%.*]], ptr [[PTR:%.*]]) {
748+
; CHECK-NEXT: [[FABS:%.*]] = call nnan float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NAN]])
749+
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
750+
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NAN]]
751+
;
752+
%fabs = call nnan float @llvm.fabs.f32(float %always.positive.or.nan)
753+
store float %fabs, ptr %ptr
754+
ret float %fabs
755+
}
756+
757+
; Take no-infs from flag, which will then imply no neg
758+
define nofpclass(nsub) float @ret_fabs_ninf_src_known_positive_or_ninf_or_nan_multiple_uses(float nofpclass(nan nnorm nsub nzero) %always.positive.or.ninf, ptr %ptr) {
759+
; CHECK-LABEL: define nofpclass(nsub) float @ret_fabs_ninf_src_known_positive_or_ninf_or_nan_multiple_uses
760+
; CHECK-SAME: (float nofpclass(nan nzero nsub nnorm) [[ALWAYS_POSITIVE_OR_NINF:%.*]], ptr [[PTR:%.*]]) {
761+
; CHECK-NEXT: [[FABS:%.*]] = call ninf float @llvm.fabs.f32(float [[ALWAYS_POSITIVE_OR_NINF]])
762+
; CHECK-NEXT: store float [[FABS]], ptr [[PTR]], align 4
763+
; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_NINF]]
764+
;
765+
%fabs = call ninf float @llvm.fabs.f32(float %always.positive.or.ninf)
766+
store float %fabs, ptr %ptr
767+
ret float %fabs
768+
}
769+
685770
define nofpclass(snan) float @fabs_src_known_negative(float nofpclass(nan pinf pnorm psub pzero) %always.negative) {
686771
; CHECK-LABEL: define nofpclass(snan) float @fabs_src_known_negative
687772
; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ALWAYS_NEGATIVE:%.*]]) {

0 commit comments

Comments
 (0)