[llvm] 67fb7c3 - [TLI] Add support for inferring attr `cold` on `exit`/`abort`
Noah Goldstein via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 29 09:57:08 PDT 2024
Author: Noah Goldstein
Date: 2024-07-30T00:56:53+08:00
New Revision: 67fb7c34f11df03ac359571dd4d503a36e06275e
URL: https://github.com/llvm/llvm-project/commit/67fb7c34f11df03ac359571dd4d503a36e06275e
DIFF: https://github.com/llvm/llvm-project/commit/67fb7c34f11df03ac359571dd4d503a36e06275e.diff
LOG: [TLI] Add support for inferring attr `cold` on `exit`/`abort`
`abort` can be assumed always cold and assume non-zero `exit` status
as a `cold` path as well.
Closes #101003
Added:
Modified:
llvm/include/llvm/Analysis/TargetLibraryInfo.def
llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
llvm/lib/Transforms/Utils/BuildLibCalls.cpp
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
llvm/test/Transforms/InferFunctionAttrs/annotate.ll
llvm/test/Transforms/InstCombine/lib-call-exit.ll
llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index 623cdb4b6e0b7..e9f3b7fcd99eb 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -476,6 +476,21 @@ TLI_DEFINE_ENUM_INTERNAL(atexit)
TLI_DEFINE_STRING_INTERNAL("atexit")
TLI_DEFINE_SIG_INTERNAL(Int, Ptr)
+/// void abort(void)
+TLI_DEFINE_ENUM_INTERNAL(abort)
+TLI_DEFINE_STRING_INTERNAL("abort")
+TLI_DEFINE_SIG_INTERNAL(Void)
+
+/// void exit(int)
+TLI_DEFINE_ENUM_INTERNAL(exit)
+TLI_DEFINE_STRING_INTERNAL("exit")
+TLI_DEFINE_SIG_INTERNAL(Void, Int)
+
+/// void _Exit(int)
+TLI_DEFINE_ENUM_INTERNAL(Exit)
+TLI_DEFINE_STRING_INTERNAL("_Exit")
+TLI_DEFINE_SIG_INTERNAL(Void, Int)
+
/// void __cxa_guard_abort(guard_t *guard);
/// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi.
TLI_DEFINE_ENUM_INTERNAL(cxa_guard_abort)
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 770da12e01233..43b5c9250a890 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -245,6 +245,9 @@ class LibCallSimplifier {
Value *optimizeSnPrintFString(CallInst *CI, IRBuilderBase &B);
Value *optimizeFPrintFString(CallInst *CI, IRBuilderBase &B);
+ /// Exit functions
+ Value *optimizeExit(CallInst *CI);
+
/// hasFloatVersion - Checks if there is a float version of the specified
/// function by checking for an existing function with name FuncName + f
bool hasFloatVersion(const Module *M, StringRef FuncName);
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 0c45bd886af9d..898e5b0f41812 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -48,6 +48,7 @@ STATISTIC(NumNoAlias, "Number of function returns inferred as noalias");
STATISTIC(NumNoUndef, "Number of function returns inferred as noundef returns");
STATISTIC(NumReturnedArg, "Number of arguments inferred as returned");
STATISTIC(NumWillReturn, "Number of functions inferred as willreturn");
+STATISTIC(NumCold, "Number of functions inferred as cold");
static bool setDoesNotAccessMemory(Function &F) {
if (F.doesNotAccessMemory())
@@ -57,6 +58,14 @@ static bool setDoesNotAccessMemory(Function &F) {
return true;
}
+static bool setIsCold(Function &F) {
+ if (F.hasFnAttribute(Attribute::Cold))
+ return false;
+ F.addFnAttr(Attribute::Cold);
+ ++NumCold;
+ return true;
+}
+
static bool setOnlyAccessesInaccessibleMemory(Function &F) {
if (F.onlyAccessesInaccessibleMemory())
return false;
@@ -1087,6 +1096,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyWritesMemory(F, 0);
Changed |= setDoesNotThrow(F);
break;
+ case LibFunc_abort:
+ Changed |= setIsCold(F);
+ break;
// int __nvvm_reflect(const char *)
case LibFunc_nvvm_reflect:
Changed |= setRetAndArgsNoUndef(F);
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 92c44265ce8b6..4100471eaaa1d 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3729,6 +3729,17 @@ Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilderBase &B) {
return nullptr;
}
+Value *LibCallSimplifier::optimizeExit(CallInst *CI) {
+
+ // Mark 'exit' as cold if its not exit(0) (success).
+ const APInt *C;
+ if (!CI->hasFnAttr(Attribute::Cold) &&
+ match(CI->getArgOperand(0), m_APInt(C)) && !C->isZero()) {
+ CI->addFnAttr(Attribute::Cold);
+ }
+ return nullptr;
+}
+
Value *LibCallSimplifier::optimizeBCopy(CallInst *CI, IRBuilderBase &B) {
// bcopy(src, dst, n) -> llvm.memmove(dst, src, n)
return copyFlags(*CI, B.CreateMemMove(CI->getArgOperand(1), Align(1),
@@ -4084,6 +4095,9 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) {
case LibFunc_vfprintf:
case LibFunc_fiprintf:
return optimizeErrorReporting(CI, Builder, 0);
+ case LibFunc_exit:
+ case LibFunc_Exit:
+ return optimizeExit(CI);
default:
return nullptr;
}
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index 9a5b902210009..d54290fd3869c 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -1088,7 +1088,7 @@ declare i32 @vsscanf(ptr, ptr, ptr)
; CHECK: declare noundef i64 @write(i32 noundef, ptr nocapture noundef readonly, i64 noundef) [[NOFREE]]
declare i64 @write(i32, ptr, i64)
-; CHECK: declare void @abort()
+; CHECK: declare void @abort() [[NOFREE_COLD:#[0-9]+]]
declare void @abort()
; memset_pattern{4,8,16} aren't available everywhere.
@@ -1116,6 +1116,7 @@ declare void @memset_pattern16(ptr, ptr, i64)
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { nofree nounwind memory(argmem: readwrite) }
; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
+; CHECK-DAG: attributes [[NOFREE_COLD]] = { cold nofree }
; CHECK-NVPTX-DAG: attributes [[NOFREE_NOUNWIND_READNONE]] = { nofree nosync nounwind memory(none) }
diff --git a/llvm/test/Transforms/InstCombine/lib-call-exit.ll b/llvm/test/Transforms/InstCombine/lib-call-exit.ll
index fcdec9b9fe093..ad133af5ea366 100644
--- a/llvm/test/Transforms/InstCombine/lib-call-exit.ll
+++ b/llvm/test/Transforms/InstCombine/lib-call-exit.ll
@@ -15,7 +15,7 @@ define void @call_exit_0() {
define void @call_exit_1() {
; CHECK-LABEL: define void @call_exit_1() {
-; CHECK-NEXT: call void @exit(i32 1)
+; CHECK-NEXT: call void @exit(i32 1) #[[ATTR0:[0-9]+]]
; CHECK-NEXT: ret void
;
call void @exit(i32 1)
@@ -24,7 +24,7 @@ define void @call_exit_1() {
define void @call__Exit_m1() {
; CHECK-LABEL: define void @call__Exit_m1() {
-; CHECK-NEXT: call void @_Exit(i32 -1)
+; CHECK-NEXT: call void @_Exit(i32 -1) #[[ATTR0]]
; CHECK-NEXT: ret void
;
call void @_Exit(i32 -1)
@@ -40,3 +40,7 @@ define void @call__Exit_N(i32 %N) {
call void @_Exit(i32 %N)
ret void
}
+
+;.
+; CHECK: attributes #[[ATTR0]] = { cold }
+;.
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 5840e024e9786..19e18e09b76d0 100644
--- a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
+++ b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
@@ -34,21 +34,21 @@
#
# CHECK: << Total TLI yes SDK no: 8
# CHECK: >> Total TLI no SDK yes: 0
-# CHECK: == Total TLI yes SDK yes: 242
+# CHECK: == Total TLI yes SDK yes: 245
#
# WRONG_DETAIL: << TLI yes SDK no : '_ZdaPv' aka operator delete[](void*)
# WRONG_DETAIL: >> TLI no SDK yes: '_ZdaPvj' aka operator delete[](void*, unsigned int)
# WRONG_DETAIL-COUNT-8: << TLI yes SDK no : {{.*}}__hot_cold_t
# WRONG_SUMMARY: << Total TLI yes SDK no: 9{{$}}
# WRONG_SUMMARY: >> Total TLI no SDK yes: 1{{$}}
-# WRONG_SUMMARY: == Total TLI yes SDK yes: 241
+# WRONG_SUMMARY: == Total TLI yes SDK yes: 244
#
## 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 483 symbols, 250 available
-# AVAIL-COUNT-250: {{^}} available
+# AVAIL: TLI knows 486 symbols, 253 available
+# AVAIL-COUNT-253: {{^}} available
# AVAIL-NOT: {{^}} available
# UNAVAIL-COUNT-233: not available
# UNAVAIL-NOT: not available
@@ -267,6 +267,18 @@ DynamicSymbols:
Type: STT_FUNC
Section: .text
Binding: STB_GLOBAL
+ - Name: abort
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ - Name: exit
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ - Name: _Exit
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
- Name: atof
Type: STT_FUNC
Section: .text
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index 1447291844dd2..b8125b099343b 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -500,6 +500,10 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"declare i32 @atexit(void ()*)\n"
+ "declare void @abort()\n"
+ "declare void @exit(i32)\n"
+ "declare void @_Exit(i32)\n"
+
"declare i32 @__nvvm_reflect(i8*)\n"
"declare i8* @__memcpy_chk(i8*, i8*, i64, i64)\n"
@@ -663,4 +667,4 @@ class TLITestAarch64 : public ::testing::Test {
TEST_F(TLITestAarch64, TestFrem) {
EXPECT_EQ(getScalarName(Instruction::FRem, Type::getDoubleTy(Ctx)), "fmod");
EXPECT_EQ(getScalarName(Instruction::FRem, Type::getFloatTy(Ctx)), "fmodf");
-}
\ No newline at end of file
+}
More information about the llvm-commits
mailing list