-
Notifications
You must be signed in to change notification settings - Fork 11.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fdim constant fold #109235
base: main
Are you sure you want to change the base?
Fdim constant fold #109235
Conversation
Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-llvm-transforms Author: None (braw-lee) Changes2nd PR to fix #108695 based on #108702 Full diff: https://github.com/llvm/llvm-project/pull/109235.diff 9 Files Affected:
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index 5914324b286c05..a18952f038cc31 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -2067,6 +2067,21 @@ TLI_DEFINE_ENUM_INTERNAL(remquol)
TLI_DEFINE_STRING_INTERNAL("remquol")
TLI_DEFINE_SIG_INTERNAL(LDbl, LDbl, LDbl, Ptr)
+/// double fdim(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fdim)
+TLI_DEFINE_STRING_INTERNAL("fdim")
+TLI_DEFINE_SIG_INTERNAL(Dbl, Dbl, Dbl)
+
+/// float fdimf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fdimf)
+TLI_DEFINE_STRING_INTERNAL("fdimf")
+TLI_DEFINE_SIG_INTERNAL(Flt, Flt, Flt)
+
+/// long double fdiml(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fdiml)
+TLI_DEFINE_STRING_INTERNAL("fdiml")
+TLI_DEFINE_SIG_INTERNAL(LDbl, LDbl, LDbl)
+
/// int remove(const char *path);
TLI_DEFINE_ENUM_INTERNAL(remove)
TLI_DEFINE_STRING_INTERNAL("remove")
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 2e7a0ec29ed999..467a8f25386b71 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -211,6 +211,7 @@ class LibCallSimplifier {
Value *optimizeTrigInversionPairs(CallInst *CI, IRBuilderBase &B);
Value *optimizeSymmetric(CallInst *CI, LibFunc Func, IRBuilderBase &B);
Value *optimizeRemquo(CallInst *CI, IRBuilderBase &B);
+ Value *optimizeFdim(CallInst *CI, IRBuilderBase &B);
// Wrapper for all floating point library call optimizations
Value *optimizeFloatingPointLibCall(CallInst *CI, LibFunc Func,
IRBuilderBase &B);
diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index 47413239f3c6cc..1785d77bca985c 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -306,6 +306,7 @@ static void initializeLibCalls(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_powf);
TLI.setUnavailable(LibFunc_remainderf);
TLI.setUnavailable(LibFunc_remquof);
+ TLI.setUnavailable(LibFunc_fdimf);
TLI.setUnavailable(LibFunc_sinf);
TLI.setUnavailable(LibFunc_sinhf);
TLI.setUnavailable(LibFunc_sqrtf);
@@ -337,6 +338,7 @@ static void initializeLibCalls(TargetLibraryInfoImpl &TLI, const Triple &T,
TLI.setUnavailable(LibFunc_powl);
TLI.setUnavailable(LibFunc_remainderl);
TLI.setUnavailable(LibFunc_remquol);
+ TLI.setUnavailable(LibFunc_fdiml);
TLI.setUnavailable(LibFunc_sinl);
TLI.setUnavailable(LibFunc_sinhl);
TLI.setUnavailable(LibFunc_sqrtl);
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index b0da19813f0a4b..abe0d8c3d2e999 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1191,6 +1191,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_fabs:
case LibFunc_fabsf:
case LibFunc_fabsl:
+ case LibFunc_fdim:
+ case LibFunc_fdiml:
+ case LibFunc_fdimf:
case LibFunc_ffs:
case LibFunc_ffsl:
case LibFunc_ffsll:
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 917f81863cf673..5f3bb5fa060729 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3080,6 +3080,41 @@ Value *LibCallSimplifier::optimizeRemquo(CallInst *CI, IRBuilderBase &B) {
return ConstantFP::get(CI->getType(), Rem);
}
+/// Constant folds fdim
+Value *LibCallSimplifier::optimizeFdim(CallInst *CI, IRBuilderBase &B) {
+ const APFloat *X, *Y;
+ // Check if both values are constants
+ if (!match(CI->getArgOperand(0), m_APFloat(X)) ||
+ !match(CI->getArgOperand(1), m_APFloat(Y)))
+ return nullptr;
+ // If either argument is NaN, NaN is returned
+ if (X->isNaN() || Y->isNaN())
+ return ConstantFP::getQNaN(CI->getType());
+
+ // If the difference if negative, return +0.0
+ if (*X <= *Y)
+ return ConstantFP::get(CI->getType(), 0.0);
+
+ APFloat ReturnVal = *X;
+ APFloat::opStatus Status =
+ ReturnVal.subtract(*Y, RoundingMode::NearestTiesToEven);
+ switch (Status) {
+ case APFloat::opStatus::opOK:
+ break;
+ case APFloat::opStatus::opOverflow:
+ return ConstantFP::get(
+ CI->getType(),
+ APFloat::getLargest(X->getSemantics(), /*Negative=*/false));
+ case APFloat::opStatus::opUnderflow:
+ return ConstantFP::get(
+ CI->getType(),
+ APFloat::getLargest(X->getSemantics(), /*Negative=*/true));
+ default:
+ return nullptr;
+ }
+ return ConstantFP::get(CI->getType(), ReturnVal);
+}
+
//===----------------------------------------------------------------------===//
// Integer Library Call Optimizations
//===----------------------------------------------------------------------===//
@@ -4009,6 +4044,10 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
if (hasFloatVersion(M, CI->getCalledFunction()->getName()))
return optimizeBinaryDoubleFP(CI, Builder, TLI);
return nullptr;
+ case LibFunc_fdim:
+ case LibFunc_fdimf:
+ case LibFunc_fdiml:
+ return optimizeFdim(CI, Builder);
case LibFunc_fminf:
case LibFunc_fmin:
case LibFunc_fminl:
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index bc0d7a509e1f5d..267a288345dc10 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -830,6 +830,16 @@ declare float @remquof(float, float, ptr)
; CHECK: declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr nocapture) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr)
+
+; CHECK: declare double @fdim(double, double) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+declare double @fdim(double, double)
+
+; CHECK: declare float @fdimf(float, float) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+declare float @fdimf(float, float)
+
+; CHECK: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+declare x86_fp80 @fdiml(x86_fp80, x86_fp80)
+
; CHECK: declare noundef i32 @rename(ptr nocapture noundef readonly, ptr nocapture noundef readonly) [[NOFREE_NOUNWIND]]
declare i32 @rename(ptr, ptr)
diff --git a/llvm/test/Transforms/InstCombine/fdim.ll b/llvm/test/Transforms/InstCombine/fdim.ll
new file mode 100644
index 00000000000000..6213262f1af1e7
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/fdim.ll
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define double @fdim_double() {
+; CHECK-LABEL: define double @fdim_double() {
+; CHECK-NEXT: ret double 2.500000e+00
+;
+ %dim = call double @fdim (double 10.5, double 8.0)
+ ret double %dim
+}
+
+define double @fdim_double1() {
+; CHECK-LABEL: define double @fdim_double1() {
+; CHECK-NEXT: ret double 0.000000e+00
+;
+ %dim = call double @fdim (double 7.0, double 8.0)
+ ret double %dim
+}
+
+define float @fdim_float() {
+; CHECK-LABEL: define float @fdim_float() {
+; CHECK-NEXT: ret float 2.500000e+00
+;
+ %dim = call float @fdimf (float 10.5, float 8.0)
+ ret float %dim
+}
+
+define float @fdim_float1() {
+; CHECK-LABEL: define float @fdim_float1() {
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %dim = call float @fdimf (float 7.0, float 8.0)
+ ret float %dim
+}
+
+declare double @fdim(double, double)
+declare float @fdimf(float, float)
diff --git a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
index 47aeb0ad8fdef9..767a962402b783 100644
--- a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
+++ b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
@@ -34,7 +34,7 @@
#
# CHECK: << Total TLI yes SDK no: 18
# CHECK: >> Total TLI no SDK yes: 0
-# CHECK: == Total TLI yes SDK yes: 250
+# CHECK: == Total TLI yes SDK yes: 253
#
# WRONG_DETAIL: << TLI yes SDK no : '_ZdaPv' aka operator delete[](void*)
# WRONG_DETAIL: >> TLI no SDK yes: '_ZdaPvj' aka operator delete[](void*, unsigned int)
@@ -48,14 +48,14 @@
# WRONG_DETAIL: << TLI yes SDK no : 'fminimum_numl'
# WRONG_SUMMARY: << Total TLI yes SDK no: 19{{$}}
# WRONG_SUMMARY: >> Total TLI no SDK yes: 1{{$}}
-# WRONG_SUMMARY: == Total TLI yes SDK yes: 249
+# WRONG_SUMMARY: == Total TLI yes SDK yes: 252
#
## The -COUNT suffix doesn't care if there are too many matches, so check
## the exact count first; the two directives should add up to that.
## Yes, this means additions to TLI will fail this test, but the argument
## to -COUNT can't be an expression.
-# AVAIL: TLI knows 501 symbols, 268 available
-# AVAIL-COUNT-268: {{^}} available
+# AVAIL: TLI knows 504 symbols, 271 available
+# AVAIL-COUNT-271: {{^}} available
# AVAIL-NOT: {{^}} available
# UNAVAIL-COUNT-233: not available
# UNAVAIL-NOT: not available
@@ -814,6 +814,18 @@ DynamicSymbols:
Type: STT_FUNC
Section: .text
Binding: STB_GLOBAL
+ - Name: fdim
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ - Name: fdimf
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ - Name: fdiml
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
- Name: rewind
Type: STT_FUNC
Section: .text
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index c081c44ed35d00..ed6a91ce611acf 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -317,6 +317,9 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"declare double @remquo(double, double, ptr)\n"
"declare float @remquof(float, float, ptr)\n"
"declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr)\n"
+ "declare double @fdim(double, double)\n"
+ "declare float @fdimf(float, float)\n"
+ "declare x86_fp80 @fdiml(x86_fp80, x86_fp80)\n"
"declare i32 @rename(i8*, i8*)\n"
"declare void @rewind(%struct*)\n"
"declare double @rint(double)\n"
|
case APFloat::opStatus::opOverflow: | ||
return ConstantFP::get( | ||
CI->getType(), | ||
APFloat::getLargest(X->getSemantics(), /*Negative=*/false)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The result should be inf
. Please add a tests for fdim(1e308, -1e308)
.
BTW, it would be better to use fmax(x - y, 0)
instead of handling all corner cases yourself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I read that on cppref but wasn't sure if it will handle all corner cases,
will change to that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The special cases also set errno, in which case we cannot perform the fold unless the call is memory(none)
case APFloat::opStatus::opUnderflow: | ||
return ConstantFP::get( | ||
CI->getType(), | ||
APFloat::getLargest(X->getSemantics(), /*Negative=*/true)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is incorrect. Underflow means the result is subnormal.
case APFloat::opStatus::opOverflow: | ||
return ConstantFP::get( | ||
CI->getType(), | ||
APFloat::getLargest(X->getSemantics(), /*Negative=*/false)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The special cases also set errno, in which case we cannot perform the fold unless the call is memory(none)
%dim = call float @fdimf (float 7.0, float 8.0) | ||
ret float %dim | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs tests for all the edge cases. Can you also test poison/undef arguments in each position
; CHECK-LABEL: define double @fdim_double1() { | ||
; CHECK-NEXT: ret double 0.000000e+00 | ||
; | ||
%dim = call double @fdim (double 7.0, double 8.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra space before ( in all functions
2nd PR to fix #108695
based on #108702