Johannes Doerfert b51b83f68e [Attributor] Introduce the concept of query AAs
D106720 introduced features that did not work properly as we could add
new queries after a fixpoint was reached and which could not be answered
by the information gathered up to the fixpoint alone.

As an alternative to D110078, which forced eager computation where we
want to continue to be lazy, this patch fixes the problem.

QueryAAs are AAs that allow lazy queries during their lifetime. They are
never fixed if they have no outstanding dependences and always run as
part of the updates in an iteration. To determine if we are done, all
query AAs are asked if they received new queries, if not, we only need
to consider updated AAs, as before. If new queries are present we go for
another iteration.

Differential Revision: https://reviews.llvm.org/D118669
2022-02-01 01:40:44 -06:00

104 lines
4.0 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
;
; When a function is marked `alwaysinline` and is able to be inlined,
; we can IPO its boundaries
; the function is not exactly defined, and marked alwaysinline and can be inlined,
; so the function can be analyzed
define linkonce void @inner1() alwaysinline {
; CHECK: Function Attrs: alwaysinline nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@inner1
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret void
;
entry:
ret void
}
define void @outer1() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@outer1
; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret void
;
entry:
call void @inner1()
ret void
}
; The function is not alwaysinline and is not exactly defined
; so it will not be analyzed
define linkonce i32 @inner2() {
; CHECK-LABEL: define {{[^@]+}}@inner2() {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 1
;
entry:
ret i32 1
}
; CHECK-NOT: Function Attrs
define i32 @outer2() {
; CHECK: Function Attrs: norecurse
; CHECK-LABEL: define {{[^@]+}}@outer2
; CHECK-SAME: () #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[R:%.*]] = call i32 @inner2() #[[ATTR3:[0-9]+]]
; CHECK-NEXT: ret i32 [[R]]
;
entry:
%r = call i32 @inner2() alwaysinline
ret i32 %r
}
; This function cannot be inlined although it is marked alwaysinline
; it is `unexactly defined` and alwaysinline but cannot be inlined.
; so it will not be analyzed
define linkonce i32 @inner3(i8* %addr) alwaysinline {
; CHECK: Function Attrs: alwaysinline
; CHECK-LABEL: define {{[^@]+}}@inner3
; CHECK-SAME: (i8* [[ADDR:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: indirectbr i8* [[ADDR]], [label [[ONE:%.*]], label %two]
; CHECK: one:
; CHECK-NEXT: ret i32 42
; CHECK: two:
; CHECK-NEXT: ret i32 44
;
entry:
indirectbr i8* %addr, [ label %one, label %two ]
one:
ret i32 42
two:
ret i32 44
}
define i32 @outer3(i32 %x) {
; CHECK: Function Attrs: norecurse
; CHECK-LABEL: define {{[^@]+}}@outer3
; CHECK-SAME: (i32 [[X:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 42
; CHECK-NEXT: [[ADDR:%.*]] = select i1 [[CMP]], i8* blockaddress(@inner3, [[ONE:%.*]]), i8* blockaddress(@inner3, [[TWO:%.*]])
; CHECK-NEXT: [[CALL:%.*]] = call i32 @inner3(i8* [[ADDR]])
; CHECK-NEXT: ret i32 [[CALL]]
;
%cmp = icmp slt i32 %x, 42
%addr = select i1 %cmp, i8* blockaddress(@inner3, %one), i8* blockaddress(@inner3, %two)
%call = call i32 @inner3(i8* %addr)
ret i32 %call
}
;.
; CHECK: attributes #[[ATTR0]] = { alwaysinline nofree norecurse nosync nounwind readnone willreturn }
; CHECK: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
; CHECK: attributes #[[ATTR2]] = { norecurse }
; CHECK: attributes #[[ATTR3]] = { alwaysinline }
;.