[llvm] 6ef4505 - [funcattrs] Infer nosync from readnone and non-convergent
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 1 12:17:45 PDT 2021
Fixed in a8ac881.
On 4/1/21 12:01 PM, Philip Reames via llvm-commits wrote:
> This appears to have broken a bunch of bots. I missed updating some
> target specific tests.
>
> I'll have that fixed shortly.
>
> Philip
>
> On 4/1/21 11:37 AM, Philip Reames via llvm-commits wrote:
>> Author: Philip Reames
>> Date: 2021-04-01T11:37:34-07:00
>> New Revision: 6ef4505298be08b8cb4243c7d28751e0e315370a
>>
>> URL:
>> https://github.com/llvm/llvm-project/commit/6ef4505298be08b8cb4243c7d28751e0e315370a
>> DIFF:
>> https://github.com/llvm/llvm-project/commit/6ef4505298be08b8cb4243c7d28751e0e315370a.diff
>>
>> LOG: [funcattrs] Infer nosync from readnone and non-convergent
>>
>> This implements the most basic possible nosync inference. The choice
>> of inference rule is taken from the comments in attributor and the
>> discussion on the review of the change which introduced the nosync
>> attribute (0626367202c).
>>
>> This is deliberately minimal. As noted in code comments, I do plan to
>> add a more robust inference which actually scans the function IR
>> directly, but a) I need to do some refactoring of the attributor code
>> to use common interfaces, and b) I wanted to get something in. I also
>> wanted to minimize the "interesting" analysis discussion since that's
>> time intensive.
>>
>> Context: This combines with existing nofree attribute inference to
>> help prove dereferenceability in the ongoing deref-at-point semantics
>> work.
>>
>> Differential Revision: https://reviews.llvm.org/D99749
>>
>> Added:
>>
>> Modified:
>> llvm/lib/Transforms/IPO/FunctionAttrs.cpp
>> llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
>> llvm/test/Other/cgscc-devirt-iteration.ll
>> llvm/test/Other/cgscc-iterate-function-mutation.ll
>> llvm/test/Other/cgscc-observe-devirt.ll
>> llvm/test/Transforms/FunctionAttrs/atomic.ll
>> llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
>> llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
>> llvm/test/Transforms/FunctionAttrs/norecurse.ll
>> llvm/test/Transforms/FunctionAttrs/nosync.ll
>> llvm/test/Transforms/FunctionAttrs/nounwind.ll
>> llvm/test/Transforms/FunctionAttrs/optnone.ll
>> llvm/test/Transforms/Inline/cgscc-update.ll
>>
>> Removed:
>>
>>
>> ################################################################################
>>
>> diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
>> b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
>> index 6730824e860ac..87eaf2dd2fdf4 100644
>> --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
>> +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
>> @@ -79,6 +79,7 @@ STATISTIC(NumNoRecurse, "Number of functions marked
>> as norecurse");
>> STATISTIC(NumNoUnwind, "Number of functions marked as nounwind");
>> STATISTIC(NumNoFree, "Number of functions marked as nofree");
>> STATISTIC(NumWillReturn, "Number of functions marked as willreturn");
>> +STATISTIC(NumNoSync, "Number of functions marked as nosync");
>> static cl::opt<bool> EnableNonnullArgPropagation(
>> "enable-nonnull-arg-prop", cl::init(true), cl::Hidden,
>> @@ -1472,6 +1473,28 @@ static bool addWillReturn(const SCCNodeSet
>> &SCCNodes) {
>> return Changed;
>> }
>> +// Infer the nosync attribute. For the moment, the inference is
>> trivial
>> +// and relies on the readnone attribute already being infered. This
>> will
>> +// be replaced with a more robust implementation in the near future.
>> +static bool addNoSyncAttr(const SCCNodeSet &SCCNodes) {
>> + bool Changed = false;
>> +
>> + for (Function *F : SCCNodes) {
>> + if (!F || F->hasNoSync())
>> + continue;
>> +
>> + // readnone + not convergent implies nosync
>> + if (!F->doesNotAccessMemory() || F->isConvergent())
>> + continue;
>> +
>> + F->setNoSync();
>> + NumNoSync++;
>> + Changed = true;
>> + }
>> +
>> + return Changed;
>> +}
>> +
>> static SCCNodesResult createSCCNodeSet(ArrayRef<Function *>
>> Functions) {
>> SCCNodesResult Res;
>> Res.HasUnknownCall = false;
>> @@ -1527,6 +1550,8 @@ static bool
>> deriveAttrsInPostOrder(ArrayRef<Function *> Functions,
>> Changed |= addNoRecurseAttrs(Nodes.SCCNodes);
>> }
>> + Changed |= addNoSyncAttr(Nodes.SCCNodes);
>> +
>> return Changed;
>> }
>>
>> diff --git
>> a/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
>> b/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
>> index 5bbc86bb69ed2..d0f142b1cef52 100644
>> --- a/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
>> +++ b/llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
>> @@ -72,11 +72,11 @@ define i32 @test3_no(i8* %p) nounwind {
>> declare void @callee(i32* %p) nounwind
>> declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1) nounwind
>> -; CHECK: attributes #0 = { norecurse nounwind readnone willreturn }
>> +; CHECK: attributes #0 = { norecurse nosync nounwind readnone
>> willreturn }
>> ; CHECK: attributes #1 = { nofree norecurse nounwind willreturn
>> writeonly }
>> ; CHECK: attributes #2 = { nounwind readonly }
>> ; CHECK: attributes #3 = { nounwind }
>> -; CHECK: attributes #4 = { nounwind readnone willreturn }
>> +; CHECK: attributes #4 = { nosync nounwind readnone willreturn }
>> ; CHECK: attributes #5 = { nofree nounwind willreturn }
>> ; CHECK: attributes #6 = { nofree norecurse nounwind willreturn }
>> ; CHECK: attributes #7 = { argmemonly nofree nosync nounwind
>> willreturn }
>>
>> diff --git a/llvm/test/Other/cgscc-devirt-iteration.ll
>> b/llvm/test/Other/cgscc-devirt-iteration.ll
>> index 9a5a2a79d65fb..651b7f3b28539 100644
>> --- a/llvm/test/Other/cgscc-devirt-iteration.ll
>> +++ b/llvm/test/Other/cgscc-devirt-iteration.ll
>> @@ -28,7 +28,7 @@ declare void @unknown()
>> define void @test1() {
>> ; BEFORE-NOT: Function Attrs
>> -; AFTER: Function Attrs: readnone
>> +; AFTER: Function Attrs: nosync readnone
>> ; CHECK-LABEL: define void @test1()
>> entry:
>> %fptr = alloca void ()*
>> @@ -57,7 +57,7 @@ declare void @readnone_with_arg(void ()**) readnone
>> define void @test2_a(void ()** %ignore) {
>> ; BEFORE-NOT: Function Attrs
>> ; AFTER1: Function Attrs: readonly
>> -; AFTER2: Function Attrs: readnone
>> +; AFTER2: Function Attrs: nosync readnone
>> ; BEFORE: define void @test2_a(void ()** %ignore)
>> ; AFTER: define void @test2_a(void ()** readnone %ignore)
>> entry:
>> @@ -78,7 +78,7 @@ entry:
>> define void @test2_b() {
>> ; BEFORE-NOT: Function Attrs
>> ; AFTER1: Function Attrs: readonly
>> -; AFTER2: Function Attrs: readnone
>> +; AFTER2: Function Attrs: nosync readnone
>> ; CHECK-LABEL: define void @test2_b()
>> entry:
>> %f2ptr = alloca void ()*
>>
>> diff --git a/llvm/test/Other/cgscc-iterate-function-mutation.ll
>> b/llvm/test/Other/cgscc-iterate-function-mutation.ll
>> index 6689639311bd0..470f9055ced70 100644
>> --- a/llvm/test/Other/cgscc-iterate-function-mutation.ll
>> +++ b/llvm/test/Other/cgscc-iterate-function-mutation.ll
>> @@ -1,8 +1,8 @@
>> ; RUN: opt -aa-pipeline=basic-aa
>> -passes='cgscc(function-attrs,function(simplify-cfg))' -S < %s |
>> FileCheck %s
>> -declare void @readnone() readnone
>> +declare void @readnone() nosync readnone
>> declare void @unknown()
>> -declare void @reference_function_pointer(void()*) readnone
>> +declare void @reference_function_pointer(void()*) nosync readnone
>> ; The @test1_* set of functions checks that when we mutate
>> functions with
>> ; simplify-cfg to delete call edges and this ends up splitting both
>> the SCCs
>> @@ -338,4 +338,4 @@ exit:
>> ret void
>> }
>> -; CHECK: attributes #0 = { readnone }
>> +; CHECK: attributes #0 = { nosync readnone }
>>
>> diff --git a/llvm/test/Other/cgscc-observe-devirt.ll
>> b/llvm/test/Other/cgscc-observe-devirt.ll
>> index 3b35f0edc1206..67d630b23a332 100644
>> --- a/llvm/test/Other/cgscc-observe-devirt.ll
>> +++ b/llvm/test/Other/cgscc-observe-devirt.ll
>> @@ -10,7 +10,7 @@
>> ; without requiring the outer manager to iterate doesn't break any
>> invariant.
>> ; RUN: opt -aa-pipeline=basic-aa
>> -passes='cgscc(function-attrs,function(gvn),function-attrs)' -S < %s
>> | FileCheck %s --check-prefix=AFTER
>> -declare void @readnone() readnone
>> +declare void @readnone() nosync readnone
>> declare void @unknown()
>> ; The @test1_* checks that if we refine an indirect call to a
>> direct call and
>> @@ -103,4 +103,4 @@ define void @test2_b3() {
>> ret void
>> }
>> -; CHECK: attributes #0 = { readnone }
>> +; CHECK: attributes #0 = { nosync readnone }
>>
>> diff --git a/llvm/test/Transforms/FunctionAttrs/atomic.ll
>> b/llvm/test/Transforms/FunctionAttrs/atomic.ll
>> index 313c54b5ed3ef..3208595684fc7 100644
>> --- a/llvm/test/Transforms/FunctionAttrs/atomic.ll
>> +++ b/llvm/test/Transforms/FunctionAttrs/atomic.ll
>> @@ -20,5 +20,5 @@ entry:
>> ret i32 %r
>> }
>> -; CHECK: attributes #0 = { norecurse nounwind readnone ssp uwtable
>> willreturn }
>> +; CHECK: attributes #0 = { norecurse nosync nounwind readnone ssp
>> uwtable willreturn }
>> ; CHECK: attributes #1 = { nofree norecurse nounwind ssp uwtable
>> willreturn }
>>
>> diff --git
>> a/llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
>> b/llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
>> index 4701de3f2e54b..e913aca20c58e 100644
>> --- a/llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
>> +++ b/llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
>> @@ -28,5 +28,5 @@ entry:
>> attributes #0 = { argmemonly }
>> attributes #1 = { inaccessiblememonly }
>> attributes #2 = { inaccessiblemem_or_argmemonly }
>> -; CHECK: attributes #0 = { norecurse nounwind readnone willreturn }
>> +; CHECK: attributes #0 = { norecurse nosync nounwind readnone
>> willreturn }
>> ; CHECK-NOT: attributes
>>
>> diff --git a/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
>> b/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
>> index ef9d086f8f17a..ce33b4c3738cc 100644
>> --- a/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
>> +++ b/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
>> @@ -12,7 +12,7 @@ declare void @_ZdaPv(i8*) local_unnamed_addr #2
>> ; TEST 1 (positive case)
>> -; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
>> +; FNATTR: Function Attrs: noinline norecurse nosync nounwind
>> readnone uwtable
>> ; FNATTR-NEXT: define void @only_return()
>> define void @only_return() #0 {
>> ret void
>> @@ -78,14 +78,14 @@ end:
>> ; }
>> -; FNATTR: Function Attrs: noinline nounwind readnone uwtable
>> +; FNATTR: Function Attrs: noinline nosync nounwind readnone uwtable
>> ; FNATTR-NEXT: define void @mutual_recursion1()
>> define void @mutual_recursion1() #0 {
>> call void @mutual_recursion2()
>> ret void
>> }
>> -; FNATTR: Function Attrs: noinline nounwind readnone uwtable
>> +; FNATTR: Function Attrs: noinline nosync nounwind readnone uwtable
>> ; FNATTR-NEXT: define void @mutual_recursion2()
>> define void @mutual_recursion2() #0 {
>> call void @mutual_recursion1()
>> @@ -132,7 +132,7 @@ define noalias i8* @call_realloc(i8* nocapture
>> %0, i64 %1) local_unnamed_addr #0
>> ; FNATTR-NEXT: declare void @nofree_function()
>> declare void @nofree_function() nofree readnone #0
>> -; FNATTR: Function Attrs: noinline nounwind readnone uwtable
>> +; FNATTR: Function Attrs: noinline nosync nounwind readnone uwtable
>> ; FNATTR-NEXT: define void @call_nofree_function()
>> define void @call_nofree_function() #0 {
>> tail call void @nofree_function()
>> @@ -168,7 +168,7 @@ define void @call_both() #0 {
>> ; TEST 10 (positive case)
>> ; Call intrinsic function
>> -; FNATTRS: Function Attrs: noinline readnone speculatable
>> +; FNATTRS: Function Attrs: noinline nosync readnone speculatable
>> ; FNATTRS-NEXT: declare float @llvm.floor.f32(float %0)
>> declare float @llvm.floor.f32(float)
>>
>> diff --git a/llvm/test/Transforms/FunctionAttrs/norecurse.ll
>> b/llvm/test/Transforms/FunctionAttrs/norecurse.ll
>> index cc48dda663c5e..f5af6406e2a43 100644
>> --- a/llvm/test/Transforms/FunctionAttrs/norecurse.ll
>> +++ b/llvm/test/Transforms/FunctionAttrs/norecurse.ll
>> @@ -2,7 +2,7 @@
>> ; RUN: opt < %s -aa-pipeline=basic-aa
>> -passes='cgscc(function-attrs),rpo-function-attrs' -S | FileCheck %s
>> ; CHECK: Function Attrs
>> -; CHECK-SAME: norecurse nounwind readnone
>> +; CHECK-SAME: norecurse nosync nounwind readnone
>> ; CHECK-NEXT: define i32 @leaf()
>> define i32 @leaf() {
>> ret i32 1
>> @@ -61,7 +61,7 @@ define void @intrinsic(i8* %dest, i8* %src, i32
>> %len) {
>> declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)
>> ; CHECK: Function Attrs
>> -; CHECK-SAME: norecurse readnone
>> +; CHECK-SAME: norecurse nosync readnone
>> ; FIXME: missing "norecurse"
>> ; CHECK-NEXT: define internal i32 @called_by_norecurse()
>> define internal i32 @called_by_norecurse() {
>> @@ -76,7 +76,7 @@ define void @m() norecurse {
>> }
>> ; CHECK: Function Attrs
>> -; CHECK-SAME: norecurse readnone
>> +; CHECK-SAME: norecurse nosync readnone
>> ; FIXME: missing "norecurse"
>> ; CHECK-NEXT: define internal i32 @called_by_norecurse_indirectly()
>> define internal i32 @called_by_norecurse_indirectly() {
>>
>> diff --git a/llvm/test/Transforms/FunctionAttrs/nosync.ll
>> b/llvm/test/Transforms/FunctionAttrs/nosync.ll
>> index 8d578e6b67fc7..28eb51e9df0cd 100644
>> --- a/llvm/test/Transforms/FunctionAttrs/nosync.ll
>> +++ b/llvm/test/Transforms/FunctionAttrs/nosync.ll
>> @@ -4,7 +4,7 @@
>> ; Base case, empty function
>> define void @test1() {
>> -; CHECK: Function Attrs: norecurse nounwind readnone willreturn
>> +; CHECK: Function Attrs: norecurse nosync nounwind readnone willreturn
>> ; CHECK-LABEL: @test1(
>> ; CHECK-NEXT: ret void
>> ;
>> @@ -13,7 +13,7 @@ define void @test1() {
>> ; Show the bottom up walk
>> define void @test2() {
>> -; CHECK: Function Attrs: norecurse nounwind readnone willreturn
>> +; CHECK: Function Attrs: norecurse nosync nounwind readnone willreturn
>> ; CHECK-LABEL: @test2(
>> ; CHECK-NEXT: call void @test1()
>> ; CHECK-NEXT: ret void
>> @@ -36,7 +36,7 @@ define void @test3() convergent {
>> }
>> define i32 @test4(i32 %a, i32 %b) {
>> -; CHECK: Function Attrs: norecurse nounwind readnone willreturn
>> +; CHECK: Function Attrs: norecurse nosync nounwind readnone willreturn
>> ; CHECK-LABEL: @test4(
>> ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
>> ; CHECK-NEXT: ret i32 [[A]]
>>
>> diff --git a/llvm/test/Transforms/FunctionAttrs/nounwind.ll
>> b/llvm/test/Transforms/FunctionAttrs/nounwind.ll
>> index 57518f4870cc6..6a667cf73b1e7 100644
>> --- a/llvm/test/Transforms/FunctionAttrs/nounwind.ll
>> +++ b/llvm/test/Transforms/FunctionAttrs/nounwind.ll
>> @@ -1,14 +1,14 @@
>> ; RUN: opt < %s -function-attrs -S | FileCheck %s
>> ; TEST 1
>> -; CHECK: Function Attrs: norecurse nounwind readnone
>> +; CHECK: Function Attrs: norecurse nosync nounwind readnone
>> ; CHECK-NEXT: define i32 @foo1()
>> define i32 @foo1() {
>> ret i32 1
>> }
>> ; TEST 2
>> -; CHECK: Function Attrs: nounwind readnone
>> +; CHECK: Function Attrs: nosync nounwind readnone
>> ; CHECK-NEXT: define i32 @scc1_foo()
>> define i32 @scc1_foo() {
>> %1 = call i32 @scc1_bar()
>> @@ -17,7 +17,7 @@ define i32 @scc1_foo() {
>> ; TEST 3
>> -; CHECK: Function Attrs: nounwind readnone
>> +; CHECK: Function Attrs: nosync nounwind readnone
>> ; CHECK-NEXT: define i32 @scc1_bar()
>> define i32 @scc1_bar() {
>> %1 = call i32 @scc1_foo()
>>
>> diff --git a/llvm/test/Transforms/FunctionAttrs/optnone.ll
>> b/llvm/test/Transforms/FunctionAttrs/optnone.ll
>> index 9455a2ae40a01..850142762140a 100644
>> --- a/llvm/test/Transforms/FunctionAttrs/optnone.ll
>> +++ b/llvm/test/Transforms/FunctionAttrs/optnone.ll
>> @@ -20,6 +20,6 @@ declare i8 @strlen(i8*) noinline optnone
>> ; CHECK: (i8*) #1
>> ; CHECK-LABEL: attributes #0
>> -; CHECK: = { norecurse nounwind readnone willreturn }
>> +; CHECK: = { norecurse nosync nounwind readnone willreturn }
>> ; CHECK-LABEL: attributes #1
>> ; CHECK: = { noinline optnone }
>>
>> diff --git a/llvm/test/Transforms/Inline/cgscc-update.ll
>> b/llvm/test/Transforms/Inline/cgscc-update.ll
>> index b251a5d070c6e..024d57a13d8fc 100644
>> --- a/llvm/test/Transforms/Inline/cgscc-update.ll
>> +++ b/llvm/test/Transforms/Inline/cgscc-update.ll
>> @@ -27,7 +27,7 @@ entry:
>> }
>> ; This function should have had 'readnone' deduced for its SCC.
>> -; CHECK: Function Attrs: noinline nounwind readnone
>> +; CHECK: Function Attrs: noinline nosync nounwind readnone
>> ; CHECK-NEXT: define void @test1_g()
>> define void @test1_g() noinline {
>> entry:
>> @@ -36,7 +36,7 @@ entry:
>> }
>> ; This function should have had 'readnone' deduced for its SCC.
>> -; CHECK: Function Attrs: noinline nounwind readnone
>> +; CHECK: Function Attrs: noinline nosync nounwind readnone
>> ; CHECK-NEXT: define void @test1_h()
>> define void @test1_h() noinline {
>> entry:
>> @@ -59,7 +59,7 @@ entry:
>> }
>> ; This function should have had 'readnone' deduced for its SCC.
>> -; CHECK: Function Attrs: noinline nounwind readnone
>> +; CHECK: Function Attrs: noinline nosync nounwind readnone
>> ; CHECK-NEXT: define void @test2_g()
>> define void @test2_g() noinline {
>> entry:
>> @@ -69,7 +69,7 @@ entry:
>> }
>> ; This function should have had 'readnone' deduced for its SCC.
>> -; CHECK: Function Attrs: noinline nounwind readnone
>> +; CHECK: Function Attrs: noinline nosync nounwind readnone
>> ; CHECK-NEXT: define void @test2_h()
>> define void @test2_h() noinline {
>> entry:
>> @@ -152,7 +152,7 @@ exit:
>> ; form a new SCC and should use that can deduce precise function
>> attrs.
>> ; This function should have had 'readnone' deduced for its SCC.
>> -; CHECK: Function Attrs: noinline nounwind readnone
>> +; CHECK: Function Attrs: noinline nosync nounwind readnone
>> ; CHECK-NEXT: define void @test4_f1()
>> define void @test4_f1() noinline {
>> entry:
>> @@ -175,7 +175,7 @@ entry:
>> }
>> ; This function should have had 'readnone' deduced for its SCC.
>> -; CHECK: Function Attrs: noinline nounwind readnone
>> +; CHECK: Function Attrs: noinline nosync nounwind readnone
>> ; CHECK-NEXT: define void @test4_h()
>> define void @test4_h() noinline {
>> entry:
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list