
This patch adds a lightweight instance of Attributor that only deduces attributes. This is just an initial version with the goal to have a version that only focuses on attributes to replace the function-attrs pass. The initial version has a few open issues pending until default enablement, the main one probably being compile time. The main additional functionality this will provide in general is propagating attributes to call sites. Open issues: * compile time The current version increase O3 +2.67% and ThinLTO +6.18% when replacing FunctionAttr https://llvm-compile-time-tracker.com/compare.php?from=c4bb3e073548cf436d5fa0406e3ae75e94684dec&to=d992630a69c79a2587d736e6a88f448850413bd1&stat=instructions%3Au Both are with an additional change to preserve more analysis, like FunctionAttrs CGSCC run. * some missed attribute inference Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D152081
379 lines
11 KiB
LLVM
379 lines
11 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
|
|
; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=COMMON,FNATTRS %s
|
|
; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s
|
|
|
|
; TEST 1
|
|
define i32 @foo1() {
|
|
; COMMON: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; COMMON-LABEL: define {{[^@]+}}@foo1
|
|
; COMMON-SAME: () #[[ATTR0:[0-9]+]] {
|
|
; COMMON-NEXT: ret i32 1
|
|
;
|
|
ret i32 1
|
|
}
|
|
|
|
; TEST 2
|
|
define i32 @scc1_foo() {
|
|
; FNATTRS: Function Attrs: nofree nosync nounwind memory(none)
|
|
; FNATTRS-LABEL: define {{[^@]+}}@scc1_foo
|
|
; FNATTRS-SAME: () #[[ATTR1:[0-9]+]] {
|
|
; FNATTRS-NEXT: [[TMP1:%.*]] = call i32 @scc1_bar()
|
|
; FNATTRS-NEXT: ret i32 1
|
|
;
|
|
; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none)
|
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@scc1_foo
|
|
; ATTRIBUTOR-SAME: () #[[ATTR1:[0-9]+]] {
|
|
; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i32 @scc1_bar() #[[ATTR1]]
|
|
; ATTRIBUTOR-NEXT: ret i32 1
|
|
;
|
|
%1 = call i32 @scc1_bar()
|
|
ret i32 1
|
|
}
|
|
|
|
|
|
; TEST 3
|
|
define i32 @scc1_bar() {
|
|
; FNATTRS: Function Attrs: nofree nosync nounwind memory(none)
|
|
; FNATTRS-LABEL: define {{[^@]+}}@scc1_bar
|
|
; FNATTRS-SAME: () #[[ATTR1]] {
|
|
; FNATTRS-NEXT: [[TMP1:%.*]] = call i32 @scc1_foo()
|
|
; FNATTRS-NEXT: ret i32 1
|
|
;
|
|
; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none)
|
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@scc1_bar
|
|
; ATTRIBUTOR-SAME: () #[[ATTR1]] {
|
|
; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i32 @scc1_foo() #[[ATTR1]]
|
|
; ATTRIBUTOR-NEXT: ret i32 1
|
|
;
|
|
%1 = call i32 @scc1_foo()
|
|
ret i32 1
|
|
}
|
|
|
|
declare i32 @non_nounwind()
|
|
|
|
; TEST 4
|
|
define void @call_non_nounwind(){
|
|
; COMMON-LABEL: define {{[^@]+}}@call_non_nounwind() {
|
|
; COMMON-NEXT: [[TMP1:%.*]] = tail call i32 @non_nounwind()
|
|
; COMMON-NEXT: ret void
|
|
;
|
|
tail call i32 @non_nounwind()
|
|
ret void
|
|
}
|
|
|
|
; TEST 5 - throw
|
|
; int maybe_throw(bool canThrow) {
|
|
; if (canThrow)
|
|
; throw;
|
|
; else
|
|
; return -1;
|
|
; }
|
|
|
|
define i32 @maybe_throw(i1 zeroext %0) {
|
|
; COMMON-LABEL: define {{[^@]+}}@maybe_throw
|
|
; COMMON-SAME: (i1 zeroext [[TMP0:%.*]]) {
|
|
; COMMON-NEXT: br i1 [[TMP0]], label [[TMP2:%.*]], label [[TMP3:%.*]]
|
|
; COMMON: 2:
|
|
; COMMON-NEXT: tail call void @__cxa_rethrow()
|
|
; COMMON-NEXT: unreachable
|
|
; COMMON: 3:
|
|
; COMMON-NEXT: ret i32 -1
|
|
;
|
|
br i1 %0, label %2, label %3
|
|
|
|
2: ; preds = %1
|
|
tail call void @__cxa_rethrow() #1
|
|
unreachable
|
|
|
|
3: ; preds = %1
|
|
ret i32 -1
|
|
}
|
|
|
|
declare void @__cxa_rethrow()
|
|
|
|
; TEST 6 - catch
|
|
; int catch_thing() {
|
|
; try {
|
|
; int a = doThing(true);
|
|
; }
|
|
; catch(...) { return -1; }
|
|
; return 1;
|
|
; }
|
|
|
|
define i32 @catch_thing() personality ptr @__gxx_personality_v0 {
|
|
; COMMON-LABEL: define {{[^@]+}}@catch_thing() personality ptr @__gxx_personality_v0 {
|
|
; COMMON-NEXT: invoke void @__cxa_rethrow()
|
|
; COMMON-NEXT: to label [[TMP1:%.*]] unwind label [[TMP2:%.*]]
|
|
; COMMON: 1:
|
|
; COMMON-NEXT: unreachable
|
|
; COMMON: 2:
|
|
; COMMON-NEXT: [[TMP3:%.*]] = landingpad { ptr, i32 }
|
|
; COMMON-NEXT: catch ptr null
|
|
; COMMON-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0
|
|
; COMMON-NEXT: [[TMP5:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[TMP4]])
|
|
; COMMON-NEXT: tail call void @__cxa_end_catch()
|
|
; COMMON-NEXT: ret i32 -1
|
|
;
|
|
invoke void @__cxa_rethrow() #1
|
|
to label %1 unwind label %2
|
|
|
|
1: ; preds = %0
|
|
unreachable
|
|
|
|
2: ; preds = %0
|
|
%3 = landingpad { ptr, i32 }
|
|
catch ptr null
|
|
%4 = extractvalue { ptr, i32 } %3, 0
|
|
%5 = tail call ptr @__cxa_begin_catch(ptr %4) #2
|
|
tail call void @__cxa_end_catch()
|
|
ret i32 -1
|
|
}
|
|
|
|
define i32 @catch_thing_user() {
|
|
; COMMON-LABEL: define {{[^@]+}}@catch_thing_user() {
|
|
; COMMON-NEXT: [[CATCH_THING_CALL:%.*]] = call i32 @catch_thing()
|
|
; COMMON-NEXT: ret i32 [[CATCH_THING_CALL]]
|
|
;
|
|
%catch_thing_call = call i32 @catch_thing()
|
|
ret i32 %catch_thing_call
|
|
}
|
|
|
|
declare void @do_throw()
|
|
declare void @abort() nounwind
|
|
@catch_ty = external global ptr
|
|
|
|
define void @catch_specific_landingpad() personality ptr @__gxx_personality_v0 {
|
|
; COMMON: Function Attrs: noreturn
|
|
; COMMON-LABEL: define {{[^@]+}}@catch_specific_landingpad
|
|
; COMMON-SAME: () #[[ATTR3:[0-9]+]] personality ptr @__gxx_personality_v0 {
|
|
; COMMON-NEXT: invoke void @do_throw()
|
|
; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
|
|
; COMMON: lpad:
|
|
; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
|
|
; COMMON-NEXT: catch ptr @catch_ty
|
|
; COMMON-NEXT: call void @abort()
|
|
; COMMON-NEXT: unreachable
|
|
; COMMON: unreachable:
|
|
; COMMON-NEXT: unreachable
|
|
;
|
|
invoke void @do_throw()
|
|
to label %unreachable unwind label %lpad
|
|
|
|
lpad:
|
|
%lp = landingpad { ptr, i32 }
|
|
catch ptr @catch_ty
|
|
call void @abort()
|
|
unreachable
|
|
|
|
unreachable:
|
|
unreachable
|
|
}
|
|
|
|
define void @catch_all_landingpad() personality ptr @__gxx_personality_v0 {
|
|
; COMMON: Function Attrs: noreturn nounwind
|
|
; COMMON-LABEL: define {{[^@]+}}@catch_all_landingpad
|
|
; COMMON-SAME: () #[[ATTR4:[0-9]+]] personality ptr @__gxx_personality_v0 {
|
|
; COMMON-NEXT: invoke void @do_throw()
|
|
; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
|
|
; COMMON: lpad:
|
|
; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
|
|
; COMMON-NEXT: catch ptr null
|
|
; COMMON-NEXT: call void @abort()
|
|
; COMMON-NEXT: unreachable
|
|
; COMMON: unreachable:
|
|
; COMMON-NEXT: unreachable
|
|
;
|
|
invoke void @do_throw()
|
|
to label %unreachable unwind label %lpad
|
|
|
|
lpad:
|
|
%lp = landingpad { ptr, i32 }
|
|
catch ptr null
|
|
call void @abort()
|
|
unreachable
|
|
|
|
unreachable:
|
|
unreachable
|
|
}
|
|
|
|
define void @filter_specific_landingpad() personality ptr @__gxx_personality_v0 {
|
|
; COMMON: Function Attrs: noreturn
|
|
; COMMON-LABEL: define {{[^@]+}}@filter_specific_landingpad
|
|
; COMMON-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 {
|
|
; COMMON-NEXT: invoke void @do_throw()
|
|
; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
|
|
; COMMON: lpad:
|
|
; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
|
|
; COMMON-NEXT: filter [1 x ptr] [ptr @catch_ty]
|
|
; COMMON-NEXT: call void @abort()
|
|
; COMMON-NEXT: unreachable
|
|
; COMMON: unreachable:
|
|
; COMMON-NEXT: unreachable
|
|
;
|
|
invoke void @do_throw()
|
|
to label %unreachable unwind label %lpad
|
|
|
|
lpad:
|
|
%lp = landingpad { ptr, i32 }
|
|
filter [1 x ptr] [ptr @catch_ty]
|
|
call void @abort()
|
|
unreachable
|
|
|
|
unreachable:
|
|
unreachable
|
|
}
|
|
|
|
define void @filter_none_landingpad() personality ptr @__gxx_personality_v0 {
|
|
; COMMON: Function Attrs: noreturn nounwind
|
|
; COMMON-LABEL: define {{[^@]+}}@filter_none_landingpad
|
|
; COMMON-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 {
|
|
; COMMON-NEXT: invoke void @do_throw()
|
|
; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
|
|
; COMMON: lpad:
|
|
; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
|
|
; COMMON-NEXT: filter [0 x ptr] zeroinitializer
|
|
; COMMON-NEXT: call void @abort()
|
|
; COMMON-NEXT: unreachable
|
|
; COMMON: unreachable:
|
|
; COMMON-NEXT: unreachable
|
|
;
|
|
invoke void @do_throw()
|
|
to label %unreachable unwind label %lpad
|
|
|
|
lpad:
|
|
%lp = landingpad { ptr, i32 }
|
|
filter [0 x ptr] zeroinitializer
|
|
call void @abort()
|
|
unreachable
|
|
|
|
unreachable:
|
|
unreachable
|
|
}
|
|
|
|
define void @cleanup_landingpad() personality ptr @__gxx_personality_v0 {
|
|
; COMMON: Function Attrs: noreturn
|
|
; COMMON-LABEL: define {{[^@]+}}@cleanup_landingpad
|
|
; COMMON-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 {
|
|
; COMMON-NEXT: invoke void @do_throw()
|
|
; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
|
|
; COMMON: lpad:
|
|
; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
|
|
; COMMON-NEXT: cleanup
|
|
; COMMON-NEXT: call void @abort()
|
|
; COMMON-NEXT: unreachable
|
|
; COMMON: unreachable:
|
|
; COMMON-NEXT: unreachable
|
|
;
|
|
invoke void @do_throw()
|
|
to label %unreachable unwind label %lpad
|
|
|
|
lpad:
|
|
%lp = landingpad { ptr, i32 }
|
|
cleanup
|
|
call void @abort()
|
|
unreachable
|
|
|
|
unreachable:
|
|
unreachable
|
|
}
|
|
|
|
define void @cleanuppad() personality ptr @__gxx_personality_v0 {
|
|
; FNATTRS: Function Attrs: noreturn
|
|
; FNATTRS-LABEL: define {{[^@]+}}@cleanuppad
|
|
; FNATTRS-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 {
|
|
; FNATTRS-NEXT: invoke void @do_throw()
|
|
; FNATTRS-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CPAD:%.*]]
|
|
; FNATTRS: cpad:
|
|
; FNATTRS-NEXT: [[CP:%.*]] = cleanuppad within none []
|
|
; FNATTRS-NEXT: call void @abort()
|
|
; FNATTRS-NEXT: unreachable
|
|
; FNATTRS: unreachable:
|
|
; FNATTRS-NEXT: unreachable
|
|
;
|
|
; ATTRIBUTOR: Function Attrs: noreturn nounwind
|
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@cleanuppad
|
|
; ATTRIBUTOR-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 {
|
|
; ATTRIBUTOR-NEXT: invoke void @do_throw()
|
|
; ATTRIBUTOR-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CPAD:%.*]]
|
|
; ATTRIBUTOR: cpad:
|
|
; ATTRIBUTOR-NEXT: [[CP:%.*]] = cleanuppad within none []
|
|
; ATTRIBUTOR-NEXT: call void @abort()
|
|
; ATTRIBUTOR-NEXT: unreachable
|
|
; ATTRIBUTOR: unreachable:
|
|
; ATTRIBUTOR-NEXT: unreachable
|
|
;
|
|
invoke void @do_throw()
|
|
to label %unreachable unwind label %cpad
|
|
|
|
cpad:
|
|
%cp = cleanuppad within none []
|
|
call void @abort()
|
|
unreachable
|
|
|
|
unreachable:
|
|
unreachable
|
|
}
|
|
|
|
define void @catchswitch_cleanuppad() personality ptr @__gxx_personality_v0 {
|
|
; FNATTRS: Function Attrs: noreturn
|
|
; FNATTRS-LABEL: define {{[^@]+}}@catchswitch_cleanuppad
|
|
; FNATTRS-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 {
|
|
; FNATTRS-NEXT: invoke void @do_throw()
|
|
; FNATTRS-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CS:%.*]]
|
|
; FNATTRS: cs:
|
|
; FNATTRS-NEXT: [[TOK:%.*]] = catchswitch within none [label %catch] unwind label [[CPAD:%.*]]
|
|
; FNATTRS: catch:
|
|
; FNATTRS-NEXT: [[C:%.*]] = catchpad within [[TOK]] [ptr @catch_ty, i32 0, ptr null]
|
|
; FNATTRS-NEXT: call void @abort()
|
|
; FNATTRS-NEXT: unreachable
|
|
; FNATTRS: cpad:
|
|
; FNATTRS-NEXT: [[CP:%.*]] = cleanuppad within none []
|
|
; FNATTRS-NEXT: call void @abort()
|
|
; FNATTRS-NEXT: unreachable
|
|
; FNATTRS: unreachable:
|
|
; FNATTRS-NEXT: unreachable
|
|
;
|
|
; ATTRIBUTOR: Function Attrs: noreturn nounwind
|
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@catchswitch_cleanuppad
|
|
; ATTRIBUTOR-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 {
|
|
; ATTRIBUTOR-NEXT: invoke void @do_throw()
|
|
; ATTRIBUTOR-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CS:%.*]]
|
|
; ATTRIBUTOR: cs:
|
|
; ATTRIBUTOR-NEXT: [[TOK:%.*]] = catchswitch within none [label %catch] unwind label [[CPAD:%.*]]
|
|
; ATTRIBUTOR: catch:
|
|
; ATTRIBUTOR-NEXT: [[C:%.*]] = catchpad within [[TOK]] [ptr @catch_ty, i32 0, ptr null]
|
|
; ATTRIBUTOR-NEXT: call void @abort()
|
|
; ATTRIBUTOR-NEXT: unreachable
|
|
; ATTRIBUTOR: cpad:
|
|
; ATTRIBUTOR-NEXT: [[CP:%.*]] = cleanuppad within none []
|
|
; ATTRIBUTOR-NEXT: call void @abort()
|
|
; ATTRIBUTOR-NEXT: unreachable
|
|
; ATTRIBUTOR: unreachable:
|
|
; ATTRIBUTOR-NEXT: unreachable
|
|
;
|
|
invoke void @do_throw()
|
|
to label %unreachable unwind label %cs
|
|
|
|
cs:
|
|
%tok = catchswitch within none [label %catch] unwind label %cpad
|
|
|
|
catch:
|
|
%c = catchpad within %tok [ptr @catch_ty, i32 0, ptr null]
|
|
call void @abort()
|
|
unreachable
|
|
|
|
cpad:
|
|
%cp = cleanuppad within none []
|
|
call void @abort()
|
|
unreachable
|
|
|
|
unreachable:
|
|
unreachable
|
|
}
|
|
|
|
declare i32 @__gxx_personality_v0(...)
|
|
|
|
declare ptr @__cxa_begin_catch(ptr)
|
|
|
|
declare void @__cxa_end_catch()
|