Skip to content

Commit c6e16a4

Browse files
committed
[TLI] Add support for inferring attr cold/noreturn on std::terminate and __cxa_throw
These functions are both inherently on the error path so `cold` seems appropriate. `noreturn` is definitional. Closes #101622
1 parent 70f3863 commit c6e16a4

File tree

5 files changed

+50
-4
lines changed

5 files changed

+50
-4
lines changed

llvm/include/llvm/Analysis/TargetLibraryInfo.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,16 @@ TLI_DEFINE_ENUM_INTERNAL(Exit)
517517
TLI_DEFINE_STRING_INTERNAL("_Exit")
518518
TLI_DEFINE_SIG_INTERNAL(Void, Int)
519519

520+
/// void std::terminate();
521+
TLI_DEFINE_ENUM_INTERNAL(terminate)
522+
TLI_DEFINE_STRING_INTERNAL("_ZSt9terminatev")
523+
TLI_DEFINE_SIG_INTERNAL(Void)
524+
525+
/// void __cxa_throw(void *, void *, void (*)(void *));
526+
TLI_DEFINE_ENUM_INTERNAL(cxa_throw)
527+
TLI_DEFINE_STRING_INTERNAL("__cxa_throw")
528+
TLI_DEFINE_SIG_INTERNAL(Void, Ptr, Ptr, Ptr)
529+
520530
/// void __cxa_guard_abort(guard_t *guard);
521531
/// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi.
522532
TLI_DEFINE_ENUM_INTERNAL(cxa_guard_abort)

llvm/lib/Transforms/Utils/BuildLibCalls.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ STATISTIC(NumNoUndef, "Number of function returns inferred as noundef returns");
5050
STATISTIC(NumReturnedArg, "Number of arguments inferred as returned");
5151
STATISTIC(NumWillReturn, "Number of functions inferred as willreturn");
5252
STATISTIC(NumCold, "Number of functions inferred as cold");
53+
STATISTIC(NumNoReturn, "Number of functions inferred as no return");
5354

5455
static bool setDoesNotAccessMemory(Function &F) {
5556
if (F.doesNotAccessMemory())
@@ -67,6 +68,14 @@ static bool setIsCold(Function &F) {
6768
return true;
6869
}
6970

71+
static bool setNoReturn(Function &F) {
72+
if (F.hasFnAttribute(Attribute::NoReturn))
73+
return false;
74+
F.addFnAttr(Attribute::NoReturn);
75+
++NumNoReturn;
76+
return true;
77+
}
78+
7079
static bool setOnlyAccessesInaccessibleMemory(Function &F) {
7180
if (F.onlyAccessesInaccessibleMemory())
7281
return false;
@@ -1103,6 +1112,15 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
11031112
case LibFunc_abort:
11041113
Changed |= setIsCold(F);
11051114
break;
1115+
case LibFunc_terminate:
1116+
Changed |= setIsCold(F);
1117+
Changed |= setNoReturn(F);
1118+
break;
1119+
case LibFunc_cxa_throw:
1120+
Changed |= setIsCold(F);
1121+
Changed |= setNoReturn(F);
1122+
// Don't add `nofree` on `__cxa_throw`
1123+
return Changed;
11061124
// int __nvvm_reflect(const char *)
11071125
case LibFunc_nvvm_reflect:
11081126
Changed |= setRetAndArgsNoUndef(F);

llvm/test/Transforms/InferFunctionAttrs/annotate.ll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,12 @@ declare i64 @write(i32, ptr, i64)
11001100
; CHECK: declare void @abort() [[NOFREE_COLD:#[0-9]+]]
11011101
declare void @abort()
11021102

1103+
; CHECK: declare void @__cxa_throw(ptr, ptr, ptr) [[COLD_NORETURN:#[0-9]+]]
1104+
declare void @__cxa_throw(ptr, ptr, ptr)
1105+
1106+
; CHECK: declare void @_ZSt9terminatev() [[NOFREE_COLD_NORETURN:#[0-9]+]]
1107+
declare void @_ZSt9terminatev()
1108+
11031109
; memset_pattern{4,8,16} aren't available everywhere.
11041110
; CHECK-DARWIN: declare void @memset_pattern4(ptr nocapture writeonly, ptr nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
11051111
declare void @memset_pattern4(ptr, ptr, i64)
@@ -1126,6 +1132,8 @@ declare void @memset_pattern16(ptr, ptr, i64)
11261132
; 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" }
11271133
; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
11281134
; CHECK-DAG: attributes [[NOFREE_COLD]] = { cold nofree }
1135+
; CHECK-DAG: attributes [[NOFREE_COLD_NORETURN]] = { cold nofree noreturn }
1136+
; CHECK-DAG: attributes [[COLD_NORETURN]] = { cold noreturn }
11291137

11301138
; CHECK-NVPTX-DAG: attributes [[NOFREE_NOUNWIND_READNONE]] = { nofree nosync nounwind memory(none) }
11311139

llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#
3535
# CHECK: << Total TLI yes SDK no: 18
3636
# CHECK: >> Total TLI no SDK yes: 0
37-
# CHECK: == Total TLI yes SDK yes: 248
37+
# CHECK: == Total TLI yes SDK yes: 250
3838
#
3939
# WRONG_DETAIL: << TLI yes SDK no : '_ZdaPv' aka operator delete[](void*)
4040
# WRONG_DETAIL: >> TLI no SDK yes: '_ZdaPvj' aka operator delete[](void*, unsigned int)
@@ -48,14 +48,14 @@
4848
# WRONG_DETAIL: << TLI yes SDK no : 'fminimum_numl'
4949
# WRONG_SUMMARY: << Total TLI yes SDK no: 19{{$}}
5050
# WRONG_SUMMARY: >> Total TLI no SDK yes: 1{{$}}
51-
# WRONG_SUMMARY: == Total TLI yes SDK yes: 247
51+
# WRONG_SUMMARY: == Total TLI yes SDK yes: 249
5252
#
5353
## The -COUNT suffix doesn't care if there are too many matches, so check
5454
## the exact count first; the two directives should add up to that.
5555
## Yes, this means additions to TLI will fail this test, but the argument
5656
## to -COUNT can't be an expression.
57-
# AVAIL: TLI knows 499 symbols, 266 available
58-
# AVAIL-COUNT-266: {{^}} available
57+
# AVAIL: TLI knows 501 symbols, 268 available
58+
# AVAIL-COUNT-268: {{^}} available
5959
# AVAIL-NOT: {{^}} available
6060
# UNAVAIL-COUNT-233: not available
6161
# UNAVAIL-NOT: not available
@@ -174,6 +174,10 @@ DynamicSymbols:
174174
Type: STT_FUNC
175175
Section: .text
176176
Binding: STB_GLOBAL
177+
- Name: __cxa_throw
178+
Type: STT_FUNC
179+
Section: .text
180+
Binding: STB_GLOBAL
177181
- Name: __cxa_guard_release
178182
Type: STT_FUNC
179183
Section: .text
@@ -286,6 +290,10 @@ DynamicSymbols:
286290
Type: STT_FUNC
287291
Section: .text
288292
Binding: STB_GLOBAL
293+
- Name: _ZSt9terminatev
294+
Type: STT_FUNC
295+
Section: .text
296+
Binding: STB_GLOBAL
289297
- Name: atof
290298
Type: STT_FUNC
291299
Section: .text

llvm/unittests/Analysis/TargetLibraryInfoTest.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,12 +535,14 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
535535
"declare void @__cxa_guard_abort(%struct*)\n"
536536
"declare i32 @__cxa_guard_acquire(%struct*)\n"
537537
"declare void @__cxa_guard_release(%struct*)\n"
538+
"declare void @__cxa_throw(ptr, ptr, ptr)\n"
538539

539540
"declare i32 @atexit(void ()*)\n"
540541

541542
"declare void @abort()\n"
542543
"declare void @exit(i32)\n"
543544
"declare void @_Exit(i32)\n"
545+
"declare void @_ZSt9terminatev()\n"
544546

545547
"declare i32 @__nvvm_reflect(i8*)\n"
546548

0 commit comments

Comments
 (0)