Skip to content

Commit 5eb2ec2

Browse files
authored
InstCombine: Fold ldexp with constant exponent to fmul (#171731)
If we can represent this with an fmul, prefer it as a canonical form. More optimizations will understand fmul, and allows contract to fma.
1 parent 4c21e46 commit 5eb2ec2

File tree

3 files changed

+51
-34
lines changed

3 files changed

+51
-34
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3089,6 +3089,19 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
30893089
// exponent. Also could broaden sign check to cover == 0 case.
30903090
Value *Src = II->getArgOperand(0);
30913091
Value *Exp = II->getArgOperand(1);
3092+
3093+
uint64_t ConstExp;
3094+
if (match(Exp, m_ConstantInt(ConstExp))) {
3095+
// ldexp(x, K) -> fmul x, 2^K
3096+
const fltSemantics &FPTy =
3097+
Src->getType()->getScalarType()->getFltSemantics();
3098+
Constant *FPConst =
3099+
ConstantFP::get(Src->getType(), scalbn(APFloat::getOne(FPTy),
3100+
static_cast<int>(ConstExp),
3101+
APFloat::rmNearestTiesToEven));
3102+
return BinaryOperator::CreateFMulFMF(Src, FPConst, II);
3103+
}
3104+
30923105
Value *InnerSrc;
30933106
Value *InnerExp;
30943107
if (match(Src, m_OneUse(m_Intrinsic<Intrinsic::ldexp>(

llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,7 @@ define float @fmul_by_32_if_0_oeq_zero_f32(float %x) {
4949

5050
define float @ldexp_by_5_if_0_oeq_zero_f32(float %x) {
5151
; CHECK-LABEL: @ldexp_by_5_if_0_oeq_zero_f32(
52-
; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
53-
; CHECK-NEXT: [[SCALED_X:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 5)
54-
; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = select i1 [[X_IS_ZERO]], float [[SCALED_X]], float [[X]]
55-
; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]]
52+
; CHECK-NEXT: ret float [[X:%.*]]
5653
;
5754
%x.is.zero = fcmp oeq float %x, 0.0
5855
%scaled.x = call float @llvm.ldexp.f32.i32(float %x, i32 5)
@@ -62,10 +59,7 @@ define float @ldexp_by_5_if_0_oeq_zero_f32(float %x) {
6259

6360
define <2 x float> @ldexp_by_5_if_0_oeq_zero_v2f32(<2 x float> %x) {
6461
; CHECK-LABEL: @ldexp_by_5_if_0_oeq_zero_v2f32(
65-
; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq <2 x float> [[X:%.*]], zeroinitializer
66-
; CHECK-NEXT: [[SCALED_X:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> splat (i32 5))
67-
; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = select <2 x i1> [[X_IS_ZERO]], <2 x float> [[SCALED_X]], <2 x float> [[X]]
68-
; CHECK-NEXT: ret <2 x float> [[SCALED_IF_DENORMAL]]
62+
; CHECK-NEXT: ret <2 x float> [[SCALED_IF_DENORMAL:%.*]]
6963
;
7064
%x.is.zero = fcmp oeq <2 x float> %x, zeroinitializer
7165
%scaled.x = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> <i32 5, i32 5>)

llvm/test/Transforms/InstCombine/ldexp.ll

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ define float @ldexp_ldexp_different_exp_type(float %x, i32 %a, i64 %b) {
444444
define float @ldexp_ldexp_constants(float %x) {
445445
; CHECK-LABEL: define float @ldexp_ldexp_constants
446446
; CHECK-SAME: (float [[X:%.*]]) {
447-
; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 32)
447+
; CHECK-NEXT: [[LDEXP1:%.*]] = fmul reassoc float [[X]], 0x41F0000000000000
448448
; CHECK-NEXT: ret float [[LDEXP1]]
449449
;
450450
%ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 8)
@@ -455,7 +455,7 @@ define float @ldexp_ldexp_constants(float %x) {
455455
define float @ldexp_ldexp_constants_nsz(float %x) {
456456
; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz
457457
; CHECK-SAME: (float [[X:%.*]]) {
458-
; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc nsz float @llvm.ldexp.f32.i32(float [[X]], i32 32)
458+
; CHECK-NEXT: [[LDEXP1:%.*]] = fmul reassoc nsz float [[X]], 0x41F0000000000000
459459
; CHECK-NEXT: ret float [[LDEXP1]]
460460
;
461461
%ldexp0 = call reassoc nsz float @llvm.ldexp.f32.i32(float %x, i32 8)
@@ -466,7 +466,7 @@ define float @ldexp_ldexp_constants_nsz(float %x) {
466466
define float @ldexp_ldexp_constants_nsz0(float %x) {
467467
; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz0
468468
; CHECK-SAME: (float [[X:%.*]]) {
469-
; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc nsz float @llvm.ldexp.f32.i32(float [[X]], i32 32)
469+
; CHECK-NEXT: [[LDEXP1:%.*]] = fmul reassoc float [[X]], 0x41F0000000000000
470470
; CHECK-NEXT: ret float [[LDEXP1]]
471471
;
472472
%ldexp0 = call reassoc nsz float @llvm.ldexp.f32.i32(float %x, i32 8)
@@ -477,7 +477,7 @@ define float @ldexp_ldexp_constants_nsz0(float %x) {
477477
define float @ldexp_ldexp_constants_nsz1(float %x) {
478478
; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz1
479479
; CHECK-SAME: (float [[X:%.*]]) {
480-
; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc nsz float @llvm.ldexp.f32.i32(float [[X]], i32 32)
480+
; CHECK-NEXT: [[LDEXP1:%.*]] = fmul reassoc nsz float [[X]], 0x41F0000000000000
481481
; CHECK-NEXT: ret float [[LDEXP1]]
482482
;
483483
%ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 8)
@@ -641,7 +641,7 @@ define float @ldexp_ldexp_0(float %x, i32 %y) {
641641
define float @ldexp_neg150(float %x) {
642642
; CHECK-LABEL: define float @ldexp_neg150
643643
; CHECK-SAME: (float [[X:%.*]]) {
644-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -150)
644+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0.000000e+00
645645
; CHECK-NEXT: ret float [[LDEXP]]
646646
;
647647
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -150)
@@ -651,7 +651,7 @@ define float @ldexp_neg150(float %x) {
651651
define float @ldexp_neg149(float %x) {
652652
; CHECK-LABEL: define float @ldexp_neg149
653653
; CHECK-SAME: (float [[X:%.*]]) {
654-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -149)
654+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x36A0000000000000
655655
; CHECK-NEXT: ret float [[LDEXP]]
656656
;
657657
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -149)
@@ -661,7 +661,7 @@ define float @ldexp_neg149(float %x) {
661661
define float @ldexp_neg148(float %x) {
662662
; CHECK-LABEL: define float @ldexp_neg148
663663
; CHECK-SAME: (float [[X:%.*]]) {
664-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -148)
664+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x36B0000000000000
665665
; CHECK-NEXT: ret float [[LDEXP]]
666666
;
667667
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -148)
@@ -671,7 +671,7 @@ define float @ldexp_neg148(float %x) {
671671
define float @ldexp_neg127(float %x) {
672672
; CHECK-LABEL: define float @ldexp_neg127
673673
; CHECK-SAME: (float [[X:%.*]]) {
674-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -127)
674+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x3800000000000000
675675
; CHECK-NEXT: ret float [[LDEXP]]
676676
;
677677
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -127)
@@ -681,7 +681,7 @@ define float @ldexp_neg127(float %x) {
681681
define float @ldexp_neg126(float %x) {
682682
; CHECK-LABEL: define float @ldexp_neg126
683683
; CHECK-SAME: (float [[X:%.*]]) {
684-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -126)
684+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x3810000000000000
685685
; CHECK-NEXT: ret float [[LDEXP]]
686686
;
687687
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -126)
@@ -691,7 +691,7 @@ define float @ldexp_neg126(float %x) {
691691
define float @ldexp_neg125(float %x) {
692692
; CHECK-LABEL: define float @ldexp_neg125
693693
; CHECK-SAME: (float [[X:%.*]]) {
694-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -125)
694+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x3820000000000000
695695
; CHECK-NEXT: ret float [[LDEXP]]
696696
;
697697
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -125)
@@ -701,7 +701,7 @@ define float @ldexp_neg125(float %x) {
701701
define float @ldexp_neg16(float %x) {
702702
; CHECK-LABEL: define float @ldexp_neg16
703703
; CHECK-SAME: (float [[X:%.*]]) {
704-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -16)
704+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x3EF0000000000000
705705
; CHECK-NEXT: ret float [[LDEXP]]
706706
;
707707
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -16)
@@ -711,7 +711,7 @@ define float @ldexp_neg16(float %x) {
711711
define float @ldexp_neg8(float %x) {
712712
; CHECK-LABEL: define float @ldexp_neg8
713713
; CHECK-SAME: (float [[X:%.*]]) {
714-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -8)
714+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 3.906250e-03
715715
; CHECK-NEXT: ret float [[LDEXP]]
716716
;
717717
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -8)
@@ -721,7 +721,7 @@ define float @ldexp_neg8(float %x) {
721721
define float @ldexp_neg4(float %x) {
722722
; CHECK-LABEL: define float @ldexp_neg4
723723
; CHECK-SAME: (float [[X:%.*]]) {
724-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -4)
724+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 6.250000e-02
725725
; CHECK-NEXT: ret float [[LDEXP]]
726726
;
727727
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -4)
@@ -731,7 +731,7 @@ define float @ldexp_neg4(float %x) {
731731
define float @ldexp_neg2(float %x) {
732732
; CHECK-LABEL: define float @ldexp_neg2
733733
; CHECK-SAME: (float [[X:%.*]]) {
734-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -2)
734+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 2.500000e-01
735735
; CHECK-NEXT: ret float [[LDEXP]]
736736
;
737737
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -2)
@@ -741,7 +741,7 @@ define float @ldexp_neg2(float %x) {
741741
define float @ldexp_neg1(float %x) {
742742
; CHECK-LABEL: define float @ldexp_neg1
743743
; CHECK-SAME: (float [[X:%.*]]) {
744-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -1)
744+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 5.000000e-01
745745
; CHECK-NEXT: ret float [[LDEXP]]
746746
;
747747
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -1)
@@ -760,7 +760,7 @@ define float @ldexp_0(float %x) {
760760
define float @ldexp_1(float %x) {
761761
; CHECK-LABEL: define float @ldexp_1
762762
; CHECK-SAME: (float [[X:%.*]]) {
763-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 1)
763+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 2.000000e+00
764764
; CHECK-NEXT: ret float [[LDEXP]]
765765
;
766766
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 1)
@@ -770,7 +770,7 @@ define float @ldexp_1(float %x) {
770770
define float @ldexp_2(float %x) {
771771
; CHECK-LABEL: define float @ldexp_2
772772
; CHECK-SAME: (float [[X:%.*]]) {
773-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 2)
773+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 4.000000e+00
774774
; CHECK-NEXT: ret float [[LDEXP]]
775775
;
776776
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 2)
@@ -780,7 +780,7 @@ define float @ldexp_2(float %x) {
780780
define float @ldexp_3(float %x) {
781781
; CHECK-LABEL: define float @ldexp_3
782782
; CHECK-SAME: (float [[X:%.*]]) {
783-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 3)
783+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 8.000000e+00
784784
; CHECK-NEXT: ret float [[LDEXP]]
785785
;
786786
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 3)
@@ -790,7 +790,7 @@ define float @ldexp_3(float %x) {
790790
define float @ldexp_10(float %x) {
791791
; CHECK-LABEL: define float @ldexp_10
792792
; CHECK-SAME: (float [[X:%.*]]) {
793-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 10)
793+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 1.024000e+03
794794
; CHECK-NEXT: ret float [[LDEXP]]
795795
;
796796
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 10)
@@ -800,7 +800,7 @@ define float @ldexp_10(float %x) {
800800
define float @ldexp_125(float %x) {
801801
; CHECK-LABEL: define float @ldexp_125
802802
; CHECK-SAME: (float [[X:%.*]]) {
803-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 125)
803+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x47C0000000000000
804804
; CHECK-NEXT: ret float [[LDEXP]]
805805
;
806806
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 125)
@@ -810,7 +810,7 @@ define float @ldexp_125(float %x) {
810810
define float @ldexp_126(float %x) {
811811
; CHECK-LABEL: define float @ldexp_126
812812
; CHECK-SAME: (float [[X:%.*]]) {
813-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 126)
813+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x47D0000000000000
814814
; CHECK-NEXT: ret float [[LDEXP]]
815815
;
816816
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 126)
@@ -820,17 +820,27 @@ define float @ldexp_126(float %x) {
820820
define float @ldexp_127(float %x) {
821821
; CHECK-LABEL: define float @ldexp_127
822822
; CHECK-SAME: (float [[X:%.*]]) {
823-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 127)
823+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x47E0000000000000
824824
; CHECK-NEXT: ret float [[LDEXP]]
825825
;
826826
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 127)
827827
ret float %ldexp
828828
}
829829

830+
define float @ldexp_128(float %x) {
831+
; CHECK-LABEL: define float @ldexp_128
832+
; CHECK-SAME: (float [[X:%.*]]) {
833+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 0x7FF0000000000000
834+
; CHECK-NEXT: ret float [[LDEXP]]
835+
;
836+
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 128)
837+
ret float %ldexp
838+
}
839+
830840
define <2 x float> @ldexp_3_vector(<2 x float> %x) {
831841
; CHECK-LABEL: define <2 x float> @ldexp_3_vector
832842
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
833-
; CHECK-NEXT: [[LDEXP:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> splat (i32 3))
843+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul <2 x float> [[X]], splat (float 8.000000e+00)
834844
; CHECK-NEXT: ret <2 x float> [[LDEXP]]
835845
;
836846
%ldexp = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> <i32 3, i32 3>)
@@ -860,7 +870,7 @@ define <2 x float> @ldexp_3_4_vector(<2 x float> %x) {
860870
define float @ldexp_2_flags(float %x) {
861871
; CHECK-LABEL: define float @ldexp_2_flags
862872
; CHECK-SAME: (float [[X:%.*]]) {
863-
; CHECK-NEXT: [[LDEXP:%.*]] = call nsz contract float @llvm.ldexp.f32.i32(float [[X]], i32 2)
873+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul nsz contract float [[X]], 4.000000e+00
864874
; CHECK-NEXT: ret float [[LDEXP]]
865875
;
866876
%ldexp = call contract nsz float @llvm.ldexp.f32.i32(float %x, i32 2)
@@ -870,7 +880,7 @@ define float @ldexp_2_flags(float %x) {
870880
define float @ldexp_metadata(float %x) {
871881
; CHECK-LABEL: define float @ldexp_metadata
872882
; CHECK-SAME: (float [[X:%.*]]) {
873-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 2), !foo [[META2:![0-9]+]]
883+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 4.000000e+00
874884
; CHECK-NEXT: ret float [[LDEXP]]
875885
;
876886
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 2), !foo !2
@@ -880,7 +890,7 @@ define float @ldexp_metadata(float %x) {
880890
define float @ldexp_8_contractable(float %x, float %y) {
881891
; CHECK-LABEL: define float @ldexp_8_contractable
882892
; CHECK-SAME: (float [[X:%.*]], float [[Y:%.*]]) {
883-
; CHECK-NEXT: [[LDEXP:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[X]], i32 2)
893+
; CHECK-NEXT: [[LDEXP:%.*]] = fmul contract float [[X]], 4.000000e+00
884894
; CHECK-NEXT: [[FADD:%.*]] = fadd contract float [[LDEXP]], [[Y]]
885895
; CHECK-NEXT: ret float [[FADD]]
886896
;

0 commit comments

Comments
 (0)