Florian Hahn 400fde9296
[Attributor] Add lightweight version for attribute deduction only.
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
2023-08-05 11:47:28 +01:00

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()