Skip to content

Commit ce1ce5d

Browse files
authored
InstCombine: Try to use exp10 intrinsic instead of libcall (#92287)
Addresses old TODO about the exp10 intrinsic not existing.
1 parent ca1f0d4 commit ce1ce5d

File tree

2 files changed

+140
-2
lines changed

2 files changed

+140
-2
lines changed

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,12 +2134,19 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) {
21342134
}
21352135

21362136
// pow(10.0, x) -> exp10(x)
2137-
// TODO: There is no exp10() intrinsic yet, but some day there shall be one.
21382137
if (match(Base, m_SpecificFP(10.0)) &&
2139-
hasFloatFn(M, TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l))
2138+
hasFloatFn(M, TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) {
2139+
2140+
if (Pow->doesNotAccessMemory()) {
2141+
CallInst *NewExp10 =
2142+
B.CreateIntrinsic(Intrinsic::exp10, {Ty}, {Expo}, Pow, "exp10");
2143+
return copyFlags(*Pow, NewExp10);
2144+
}
2145+
21402146
return copyFlags(*Pow, emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10,
21412147
LibFunc_exp10f, LibFunc_exp10l,
21422148
B, NoAttrs));
2149+
}
21432150

21442151
// pow(x, y) -> exp2(log2(x) * y)
21452152
if (Pow->hasApproxFunc() && Pow->hasNoNaNs() && BaseF->isFiniteNonZero() &&

llvm/test/Transforms/InstCombine/pow-1.ll

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,3 +893,134 @@ define double @test_simplify19(double %x) {
893893
%retval = call double @pow(double 10.0, double %x)
894894
ret double %retval
895895
}
896+
897+
define float @test_libcall_powf_10_f32_noerrno(float %x) {
898+
; CHECK-EXP10-LABEL: define float @test_libcall_powf_10_f32_noerrno(
899+
; CHECK-EXP10-SAME: float [[X:%.*]]) {
900+
; CHECK-EXP10-NEXT: [[__EXP10F:%.*]] = call float @llvm.exp10.f32(float [[X]])
901+
; CHECK-EXP10-NEXT: ret float [[__EXP10F]]
902+
;
903+
; CHECK-NO-EXP10-LABEL: define float @test_libcall_powf_10_f32_noerrno(
904+
; CHECK-NO-EXP10-SAME: float [[X:%.*]]) {
905+
; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call float @powf(float 1.000000e+01, float [[X]]) #[[ATTR3:[0-9]+]]
906+
; CHECK-NO-EXP10-NEXT: ret float [[RETVAL]]
907+
;
908+
%retval = call float @powf(float 10.0, float %x) memory(none)
909+
ret float %retval
910+
}
911+
912+
define double @test_libcall_pow_10_f64_noerrno(double %x) {
913+
; CHECK-EXP10-LABEL: define double @test_libcall_pow_10_f64_noerrno(
914+
; CHECK-EXP10-SAME: double [[X:%.*]]) {
915+
; CHECK-EXP10-NEXT: [[__EXP10:%.*]] = call double @llvm.exp10.f64(double [[X]])
916+
; CHECK-EXP10-NEXT: ret double [[__EXP10]]
917+
;
918+
; CHECK-NO-EXP10-LABEL: define double @test_libcall_pow_10_f64_noerrno(
919+
; CHECK-NO-EXP10-SAME: double [[X:%.*]]) {
920+
; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call double @pow(double 1.000000e+01, double [[X]]) #[[ATTR3]]
921+
; CHECK-NO-EXP10-NEXT: ret double [[RETVAL]]
922+
;
923+
%retval = call double @pow(double 10.0, double %x) memory(none)
924+
ret double %retval
925+
}
926+
927+
define half @test_pow_10_f16(half %x) {
928+
; CHECK-LABEL: define half @test_pow_10_f16(
929+
; CHECK-SAME: half [[X:%.*]]) {
930+
; CHECK-NEXT: [[RETVAL:%.*]] = call half @llvm.pow.f16(half 0xH4900, half [[X]])
931+
; CHECK-NEXT: ret half [[RETVAL]]
932+
;
933+
%retval = call half @llvm.pow.f16(half 10.0, half %x)
934+
ret half %retval
935+
}
936+
937+
define float @test_pow_10_f32(float %x) {
938+
; CHECK-EXP10-LABEL: define float @test_pow_10_f32(
939+
; CHECK-EXP10-SAME: float [[X:%.*]]) {
940+
; CHECK-EXP10-NEXT: [[__EXP10F:%.*]] = call float @llvm.exp10.f32(float [[X]])
941+
; CHECK-EXP10-NEXT: ret float [[__EXP10F]]
942+
;
943+
; CHECK-NO-EXP10-LABEL: define float @test_pow_10_f32(
944+
; CHECK-NO-EXP10-SAME: float [[X:%.*]]) {
945+
; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call float @llvm.pow.f32(float 1.000000e+01, float [[X]])
946+
; CHECK-NO-EXP10-NEXT: ret float [[RETVAL]]
947+
;
948+
%retval = call float @llvm.pow.f32(float 10.0, float %x)
949+
ret float %retval
950+
}
951+
952+
define double @test_pow_10_f64(double %x) {
953+
; CHECK-EXP10-LABEL: define double @test_pow_10_f64(
954+
; CHECK-EXP10-SAME: double [[X:%.*]]) {
955+
; CHECK-EXP10-NEXT: [[__EXP10:%.*]] = call double @llvm.exp10.f64(double [[X]])
956+
; CHECK-EXP10-NEXT: ret double [[__EXP10]]
957+
;
958+
; CHECK-NO-EXP10-LABEL: define double @test_pow_10_f64(
959+
; CHECK-NO-EXP10-SAME: double [[X:%.*]]) {
960+
; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call double @llvm.pow.f64(double 1.000000e+01, double [[X]])
961+
; CHECK-NO-EXP10-NEXT: ret double [[RETVAL]]
962+
;
963+
%retval = call double @llvm.pow.f64(double 10.0, double %x)
964+
ret double %retval
965+
}
966+
967+
define fp128 @test_pow_10_fp128(fp128 %x) {
968+
; CHECK-LABEL: define fp128 @test_pow_10_fp128(
969+
; CHECK-SAME: fp128 [[X:%.*]]) {
970+
; CHECK-NEXT: [[RETVAL:%.*]] = call fp128 @llvm.pow.f128(fp128 0xL00000000000000004002400000000000, fp128 [[X]])
971+
; CHECK-NEXT: ret fp128 [[RETVAL]]
972+
;
973+
%ten = fpext double 10.0 to fp128
974+
%retval = call fp128 @llvm.pow.fp128(fp128 %ten, fp128 %x)
975+
ret fp128 %retval
976+
}
977+
978+
define bfloat @test_pow_10_bf16(bfloat %x) {
979+
; CHECK-LABEL: define bfloat @test_pow_10_bf16(
980+
; CHECK-SAME: bfloat [[X:%.*]]) {
981+
; CHECK-NEXT: [[RETVAL:%.*]] = call bfloat @llvm.pow.bf16(bfloat 0xR4120, bfloat [[X]])
982+
; CHECK-NEXT: ret bfloat [[RETVAL]]
983+
;
984+
%retval = call bfloat @llvm.pow.bf16(bfloat 10.0, bfloat %x)
985+
ret bfloat %retval
986+
}
987+
988+
define <2 x half> @test_pow_10_v2f16(<2 x half> %x) {
989+
; CHECK-LABEL: define <2 x half> @test_pow_10_v2f16(
990+
; CHECK-SAME: <2 x half> [[X:%.*]]) {
991+
; CHECK-NEXT: [[RETVAL:%.*]] = call <2 x half> @llvm.pow.v2f16(<2 x half> <half 0xH4900, half 0xH4900>, <2 x half> [[X]])
992+
; CHECK-NEXT: ret <2 x half> [[RETVAL]]
993+
;
994+
%retval = call <2 x half> @llvm.pow.v2f16(<2 x half> <half 10.0, half 10.0>, <2 x half> %x)
995+
ret <2 x half> %retval
996+
}
997+
998+
define <2 x float> @test_pow_10_v2f32(<2 x float> %x) {
999+
; CHECK-LABEL: define <2 x float> @test_pow_10_v2f32(
1000+
; CHECK-SAME: <2 x float> [[X:%.*]]) {
1001+
; CHECK-NEXT: [[RETVAL:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> <float 1.000000e+01, float 1.000000e+01>, <2 x float> [[X]])
1002+
; CHECK-NEXT: ret <2 x float> [[RETVAL]]
1003+
;
1004+
%retval = call <2 x float> @llvm.pow.v2f32(<2 x float> <float 10.0, float 10.0>, <2 x float> %x)
1005+
ret <2 x float> %retval
1006+
}
1007+
1008+
define <2 x double> @test_pow_10_v2f64(<2 x double> %x) {
1009+
; CHECK-LABEL: define <2 x double> @test_pow_10_v2f64(
1010+
; CHECK-SAME: <2 x double> [[X:%.*]]) {
1011+
; CHECK-NEXT: [[RETVAL:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> <double 1.000000e+01, double 1.000000e+01>, <2 x double> [[X]])
1012+
; CHECK-NEXT: ret <2 x double> [[RETVAL]]
1013+
;
1014+
%retval = call <2 x double> @llvm.pow.v2f64(<2 x double> <double 10.0, double 10.0>, <2 x double> %x)
1015+
ret <2 x double> %retval
1016+
}
1017+
1018+
define <2 x bfloat> @test_pow_10_v2bf16(<2 x bfloat> %x) {
1019+
; CHECK-LABEL: define <2 x bfloat> @test_pow_10_v2bf16(
1020+
; CHECK-SAME: <2 x bfloat> [[X:%.*]]) {
1021+
; CHECK-NEXT: [[RETVAL:%.*]] = call <2 x bfloat> @llvm.pow.v2bf16(<2 x bfloat> <bfloat 0xR4120, bfloat 0xR4120>, <2 x bfloat> [[X]])
1022+
; CHECK-NEXT: ret <2 x bfloat> [[RETVAL]]
1023+
;
1024+
%retval = call <2 x bfloat> @llvm.pow.v2bf16(<2 x bfloat> <bfloat 10.0, bfloat 10.0>, <2 x bfloat> %x)
1025+
ret <2 x bfloat> %retval
1026+
}

0 commit comments

Comments
 (0)