This revision was automatically updated to reflect the committed changes.
Closed by commit rGf549176ad976: [funcattrs] Add the maximal set of implied 
attributes to definitions (authored by reames).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100226/new/

https://reviews.llvm.org/D100226

Files:
  clang/test/CodeGenOpenCL/convergent.cl
  llvm/lib/Transforms/IPO/FunctionAttrs.cpp
  llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
  llvm/test/CodeGen/AMDGPU/inline-attr.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/2008-09-03-ReadOnly.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/nofree.ll
  llvm/test/Transforms/FunctionAttrs/nosync.ll
  llvm/test/Transforms/FunctionAttrs/nounwind.ll
  llvm/test/Transforms/FunctionAttrs/optnone.ll
  llvm/test/Transforms/FunctionAttrs/willreturn-callsites.ll
  llvm/test/Transforms/FunctionAttrs/writeonly.ll
  llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
  llvm/test/Transforms/Inline/cgscc-update.ll

Index: llvm/test/Transforms/Inline/cgscc-update.ll
===================================================================
--- llvm/test/Transforms/Inline/cgscc-update.ll
+++ llvm/test/Transforms/Inline/cgscc-update.ll
@@ -27,7 +27,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline nosync nounwind readnone
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
 ; CHECK-NEXT: define void @test1_g()
 define void @test1_g() noinline {
 entry:
@@ -36,7 +36,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline nosync nounwind readnone
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
 ; CHECK-NEXT: define void @test1_h()
 define void @test1_h() noinline {
 entry:
@@ -59,7 +59,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline nosync nounwind readnone
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
 ; CHECK-NEXT: define void @test2_g()
 define void @test2_g() noinline {
 entry:
@@ -69,7 +69,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline nosync nounwind readnone
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
 ; CHECK-NEXT: define void @test2_h()
 define void @test2_h() noinline {
 entry:
@@ -152,7 +152,7 @@
 ; 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 nosync nounwind readnone
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
 ; CHECK-NEXT: define void @test4_f1()
 define void @test4_f1() noinline {
 entry:
@@ -175,7 +175,7 @@
 }
 
 ; This function should have had 'readnone' deduced for its SCC.
-; CHECK: Function Attrs: noinline nosync nounwind readnone
+; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
 ; CHECK-NEXT: define void @test4_h()
 define void @test4_h() noinline {
 entry:
Index: llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
===================================================================
--- llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
+++ llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
@@ -52,5 +52,5 @@
 !28 = !DILocation(line: 9, column: 18, scope: !2)
 !29 = !DILocation(line: 10, column: 1, scope: !2)
 
-; CHECK: attributes #0 = { nofree norecurse nosync nounwind willreturn }
+; CHECK: attributes #0 = { nofree norecurse nosync nounwind willreturn mustprogress }
 ; CHECK-NOT: foo.coefficient1
Index: llvm/test/Transforms/FunctionAttrs/writeonly.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/writeonly.ll
+++ llvm/test/Transforms/FunctionAttrs/writeonly.ll
@@ -27,4 +27,4 @@
 
 ; CHECK: attributes #0 = { {{.*}} readnone {{.*}} }
 ; CHECK: attributes #1 = { {{.*}} readonly {{.*}} }
-; CHECK: attributes #2 = { {{.*}} writeonly }
+; CHECK: attributes #2 = { {{.*}} writeonly {{.*}} }
Index: llvm/test/Transforms/FunctionAttrs/willreturn-callsites.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/willreturn-callsites.ll
+++ llvm/test/Transforms/FunctionAttrs/willreturn-callsites.ll
@@ -38,7 +38,7 @@
 }
 
 define void @test_fn_mustprogress_readonly_calls(i32* %ptr) mustprogress {
-; CHECK: Function Attrs: readonly willreturn mustprogress
+; CHECK: Function Attrs: nofree readonly willreturn mustprogress
 ; CHECK-LABEL: @test_fn_mustprogress_readonly_calls(
 ; CHECK-NOT:     call void @decl_readonly() #
 ; CHECK-NOT:     call void @decl_readnone() #
Index: llvm/test/Transforms/FunctionAttrs/optnone.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/optnone.ll
+++ llvm/test/Transforms/FunctionAttrs/optnone.ll
@@ -20,6 +20,6 @@
 ; CHECK: (i8*) #1
 
 ; CHECK-LABEL: attributes #0
-; CHECK: = { norecurse nosync nounwind readnone willreturn }
+; CHECK: = { nofree norecurse nosync nounwind readnone willreturn mustprogress }
 ; CHECK-LABEL: attributes #1
 ; CHECK: = { noinline optnone }
Index: llvm/test/Transforms/FunctionAttrs/nounwind.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/nounwind.ll
+++ llvm/test/Transforms/FunctionAttrs/nounwind.ll
@@ -1,14 +1,14 @@
 ; RUN: opt < %s -function-attrs -S | FileCheck %s
 
 ; TEST 1
-; CHECK: Function Attrs: norecurse nosync nounwind readnone
+; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone
 ; CHECK-NEXT: define i32 @foo1()
 define i32 @foo1() {
   ret i32 1
 }
 
 ; TEST 2
-; CHECK: Function Attrs: nosync nounwind readnone
+; CHECK: Function Attrs: nofree nosync nounwind readnone
 ; CHECK-NEXT: define i32 @scc1_foo()
 define i32 @scc1_foo() {
   %1 = call i32 @scc1_bar()
@@ -17,7 +17,7 @@
 
 
 ; TEST 3
-; CHECK: Function Attrs: nosync nounwind readnone
+; CHECK: Function Attrs: nofree nosync nounwind readnone
 ; CHECK-NEXT: define i32 @scc1_bar()
 define i32 @scc1_bar() {
   %1 = call i32 @scc1_foo()
Index: llvm/test/Transforms/FunctionAttrs/nosync.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/nosync.ll
+++ llvm/test/Transforms/FunctionAttrs/nosync.ll
@@ -6,7 +6,7 @@
 
 ; Base case, empty function
 define void @test1() {
-; CHECK: Function Attrs: norecurse nosync nounwind readnone willreturn
+; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
 ; CHECK-LABEL: @test1(
 ; CHECK-NEXT:    ret void
 ;
@@ -15,7 +15,7 @@
 
 ; Show the bottom up walk
 define void @test2() {
-; CHECK: Function Attrs: norecurse nosync nounwind readnone willreturn
+; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
 ; CHECK-LABEL: @test2(
 ; CHECK-NEXT:    call void @test1()
 ; CHECK-NEXT:    ret void
@@ -38,7 +38,7 @@
 }
 
 define i32 @test4(i32 %a, i32 %b) {
-; CHECK: Function Attrs: norecurse nosync nounwind readnone willreturn
+; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
 ; CHECK-LABEL: @test4(
 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    ret i32 [[A]]
@@ -137,7 +137,7 @@
 }
 
 define i32 @load_unordered(i32* nocapture readonly %0) norecurse nounwind uwtable {
-; CHECK: Function Attrs: norecurse nosync nounwind readonly uwtable willreturn
+; CHECK: Function Attrs: nofree norecurse nosync nounwind readonly uwtable willreturn
 ; CHECK-LABEL: @load_unordered(
 ; CHECK-NEXT:    [[TMP2:%.*]] = load atomic i32, i32* [[TMP0:%.*]] unordered, align 4
 ; CHECK-NEXT:    ret i32 [[TMP2]]
@@ -271,7 +271,7 @@
 
 ; negative. Convergent
 define void @convergent_readnone(){
-; CHECK: Function Attrs: nosync readnone
+; CHECK: Function Attrs: nofree nosync readnone
 ; CHECK-LABEL: @convergent_readnone(
 ; CHECK-NEXT:    call void @readnone_test()
 ; CHECK-NEXT:    ret void
@@ -299,7 +299,7 @@
 declare float @llvm.cos(float %val) readnone
 
 define float @cos_test(float %x) {
-; CHECK: Function Attrs: nosync nounwind readnone willreturn
+; CHECK: Function Attrs: nofree nosync nounwind readnone willreturn
 ; CHECK-LABEL: @cos_test(
 ; CHECK-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X:%.*]])
 ; CHECK-NEXT:    ret float [[C]]
Index: llvm/test/Transforms/FunctionAttrs/nofree.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/nofree.ll
+++ llvm/test/Transforms/FunctionAttrs/nofree.ll
@@ -36,7 +36,7 @@
 declare void @free(i8* nocapture) local_unnamed_addr #2
 
 define i32 @_Z4foo3Pi(i32* nocapture readonly %a) local_unnamed_addr #3 {
-; CHECK: Function Attrs: norecurse nosync nounwind readonly uwtable willreturn
+; CHECK: Function Attrs: nofree norecurse nosync nounwind readonly uwtable willreturn
 ; CHECK-LABEL: @_Z4foo3Pi(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4
Index: llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
+++ llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
@@ -12,7 +12,7 @@
 
 
 ; TEST 1 (positive case)
-; FNATTR: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
+; FNATTR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
 ; FNATTR-NEXT: define void @only_return()
 define void @only_return() #0 {
     ret void
@@ -78,14 +78,14 @@
 ; }
 
 
-; FNATTR: Function Attrs: noinline nosync nounwind readnone uwtable
+; FNATTR: Function Attrs: nofree 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 nosync nounwind readnone uwtable
+; FNATTR: Function Attrs: nofree noinline nosync nounwind readnone uwtable
 ; FNATTR-NEXT: define void @mutual_recursion2()
 define void @mutual_recursion2() #0 {
   call void @mutual_recursion1()
@@ -132,7 +132,7 @@
 ; FNATTR-NEXT: declare void @nofree_function()
 declare void @nofree_function() nofree readnone #0
 
-; FNATTR: Function Attrs: noinline nosync nounwind readnone uwtable
+; FNATTR: Function Attrs: nofree 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 @@
 
 ; TEST 10 (positive case)
 ; Call intrinsic function
-; FNATTRS: Function Attrs: noinline nosync readnone speculatable
+; FNATTRS: Function Attrs: nofree noinline nosync readnone speculatable
 ; FNATTRS-NEXT: declare float @llvm.floor.f32(float %0)
 declare float @llvm.floor.f32(float)
 
Index: llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
+++ llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
@@ -28,5 +28,5 @@
 attributes #0 = { argmemonly }
 attributes #1 = { inaccessiblememonly }
 attributes #2 = { inaccessiblemem_or_argmemonly }
-; CHECK: attributes #0 = { norecurse nosync nounwind readnone willreturn }
+; CHECK: attributes #0 = { nofree norecurse nosync nounwind readnone willreturn mustprogress }
 ; CHECK-NOT: attributes
Index: llvm/test/Transforms/FunctionAttrs/atomic.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/atomic.ll
+++ llvm/test/Transforms/FunctionAttrs/atomic.ll
@@ -20,5 +20,5 @@
   ret i32 %r
 }
 
-; CHECK: attributes #0 = { norecurse nosync nounwind readnone ssp uwtable willreturn }
-; CHECK: attributes #1 = { nofree norecurse nounwind ssp uwtable willreturn }
+; CHECK: attributes #0 = { nofree norecurse nosync nounwind readnone ssp uwtable willreturn mustprogress }
+; CHECK: attributes #1 = { nofree norecurse nounwind ssp uwtable willreturn mustprogress }
Index: llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
+++ llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
@@ -8,7 +8,8 @@
   ret i32 %tmp
 }
 
-; CHECK: declare i32 @e() #0
+; CHECK: declare i32 @e() #1
 declare i32 @e() readonly
 
-; CHECK: attributes #0 = { readonly }
+; CHECK: attributes #0 = { nofree readonly }
+; CHECK: attributes #1 = { readonly }
Index: llvm/test/Other/cgscc-observe-devirt.ll
===================================================================
--- llvm/test/Other/cgscc-observe-devirt.ll
+++ 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() nosync readnone
+declare void @readnone() nofree nosync readnone
 declare void @unknown()
 
 ; The @test1_* checks that if we refine an indirect call to a direct call and
@@ -103,4 +103,4 @@
   ret void
 }
 
-; CHECK: attributes #0 = { nosync readnone }
+; CHECK: attributes #0 = { nofree nosync readnone }
Index: llvm/test/Other/cgscc-iterate-function-mutation.ll
===================================================================
--- llvm/test/Other/cgscc-iterate-function-mutation.ll
+++ 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() nosync readnone
+declare void @readnone() nofree nosync readnone
 declare void @unknown()
-declare void @reference_function_pointer(void()*) nosync readnone
+declare void @reference_function_pointer(void()*) nofree 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 @@
   ret void
 }
 
-; CHECK: attributes #0 = { nosync readnone }
+; CHECK: attributes #0 = { nofree nosync readnone }
Index: llvm/test/Other/cgscc-devirt-iteration.ll
===================================================================
--- llvm/test/Other/cgscc-devirt-iteration.ll
+++ llvm/test/Other/cgscc-devirt-iteration.ll
@@ -28,7 +28,7 @@
 
 define void @test1() {
 ; BEFORE-NOT: Function Attrs
-; AFTER: Function Attrs: nosync readnone
+; AFTER: Function Attrs: nofree nosync readnone
 ; CHECK-LABEL: define void @test1()
 entry:
   %fptr = alloca void ()*
@@ -56,8 +56,8 @@
 
 define void @test2_a(void ()** %ignore) {
 ; BEFORE-NOT: Function Attrs
-; AFTER1: Function Attrs: readonly
-; AFTER2: Function Attrs: nosync readnone
+; AFTER1: Function Attrs: nofree readonly
+; AFTER2: Function Attrs: nofree nosync readnone
 ; BEFORE: define void @test2_a(void ()** %ignore)
 ; AFTER: define void @test2_a(void ()** readnone %ignore)
 entry:
@@ -77,8 +77,8 @@
 
 define void @test2_b() {
 ; BEFORE-NOT: Function Attrs
-; AFTER1: Function Attrs: readonly
-; AFTER2: Function Attrs: nosync readnone
+; AFTER1: Function Attrs: nofree readonly
+; AFTER2: Function Attrs: nofree nosync readnone
 ; CHECK-LABEL: define void @test2_b()
 entry:
   %f2ptr = alloca void ()*
Index: llvm/test/CodeGen/AMDGPU/inline-attr.ll
===================================================================
--- llvm/test/CodeGen/AMDGPU/inline-attr.ll
+++ llvm/test/CodeGen/AMDGPU/inline-attr.ll
@@ -6,14 +6,14 @@
 ; GCN: define amdgpu_kernel void @caller(float addrspace(1)* nocapture %p) local_unnamed_addr #1 {
 ; GCN: %mul.i = fmul float %load, 1.500000e+01
 
-; UNSAFE: attributes #0 = { norecurse nosync nounwind readnone willreturn "unsafe-fp-math"="true" }
-; UNSAFE: attributes #1 = { nofree norecurse nosync nounwind willreturn "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="true" }
+; UNSAFE: attributes #0 = { nofree norecurse nosync nounwind readnone willreturn mustprogress "unsafe-fp-math"="true" }
+; UNSAFE: attributes #1 = { nofree norecurse nosync nounwind willreturn mustprogress "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="true" }
 
-; NOINFS: attributes #0 = { norecurse nosync nounwind readnone willreturn "no-infs-fp-math"="true" }
-; NOINFS: attributes #1 = { nofree norecurse nosync nounwind willreturn "less-precise-fpmad"="false" "no-infs-fp-math"="true" "no-nans-fp-math"="false" "unsafe-fp-math"="false" }
+; NOINFS: attributes #0 = { nofree norecurse nosync nounwind readnone willreturn mustprogress "no-infs-fp-math"="true" }
+; NOINFS: attributes #1 = { nofree norecurse nosync nounwind willreturn mustprogress "less-precise-fpmad"="false" "no-infs-fp-math"="true" "no-nans-fp-math"="false" "unsafe-fp-math"="false" }
 
-; NONANS: attributes #0 = { norecurse nosync nounwind readnone willreturn "no-nans-fp-math"="true" }
-; NONANS: attributes #1 = { nofree norecurse nosync nounwind willreturn "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="true" "unsafe-fp-math"="false" }
+; NONANS: attributes #0 = { nofree norecurse nosync nounwind readnone willreturn mustprogress "no-nans-fp-math"="true" }
+; NONANS: attributes #1 = { nofree norecurse nosync nounwind willreturn mustprogress "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="true" "unsafe-fp-math"="false" }
 
 define float @foo(float %x) #0 {
 entry:
Index: llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
===================================================================
--- llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
+++ llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
@@ -72,13 +72,13 @@
 declare void @callee(i32* %p) nounwind
 declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1) nounwind
 
-; CHECK: attributes #0 = { norecurse nosync nounwind readnone willreturn }
-; CHECK: attributes #1 = { nofree norecurse nosync nounwind willreturn writeonly }
-; CHECK: attributes #2 = { nounwind readonly }
+; CHECK: attributes #0 = { nofree norecurse nosync nounwind readnone willreturn mustprogress }
+; CHECK: attributes #1 = { nofree norecurse nosync nounwind willreturn  writeonly mustprogress }
+; CHECK: attributes #2 = { nofree nounwind readonly }
 ; CHECK: attributes #3 = { nounwind }
-; CHECK: attributes #4 = { nosync nounwind readnone willreturn }
-; CHECK: attributes #5 = { nofree nosync nounwind willreturn }
-; CHECK: attributes #6 = { nofree norecurse nosync nounwind willreturn }
+; CHECK: attributes #4 = { nofree nosync nounwind readnone willreturn mustprogress }
+; CHECK: attributes #5 = { nofree nosync nounwind willreturn mustprogress }
+; CHECK: attributes #6 = { nofree norecurse nosync nounwind willreturn mustprogress }
 ; CHECK: attributes #7 = { argmemonly nofree nosync nounwind willreturn }
 
 ; Root note.
Index: llvm/lib/Transforms/IPO/FunctionAttrs.cpp
===================================================================
--- llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -57,6 +57,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Utils/Local.h"
 #include <cassert>
 #include <iterator>
 #include <map>
@@ -1556,21 +1557,7 @@
         ++NumNoSync;
       },
       /* RequiresExactDefinition= */ true});
-  bool Changed = AI.run(SCCNodes);
-
-  // readnone + not convergent implies nosync
-  // (This is here so that we don't have to duplicate the function local
-  //  memory reasoning of the readnone analysis.)
-  for (Function *F : SCCNodes) {
-    if (!F || F->hasNoSync())
-      continue;
-    if (!F->doesNotAccessMemory() || F->isConvergent())
-      continue;
-    F->setNoSync();
-    NumNoSync++;
-    Changed = true;
-  }
-  return Changed;
+  return AI.run(SCCNodes);
 }
 
 static SCCNodesResult createSCCNodeSet(ArrayRef<Function *> Functions) {
@@ -1630,6 +1617,14 @@
 
   Changed |= addNoSyncAttr(Nodes.SCCNodes);
 
+  // Finally, infer the maximal set of attributes from the ones we've inferred
+  // above.  This is handling the cases where one attribute on a signature
+  // implies another, but for implementation reasons the inference rule for
+  // the later is missing (or simply less sophisticated).
+  for (Function *F : Nodes.SCCNodes)
+    if (F)
+      Changed |= inferAttributesFromOthers(*F);
+
   return Changed;
 }
 
Index: clang/test/CodeGenOpenCL/convergent.cl
===================================================================
--- clang/test/CodeGenOpenCL/convergent.cl
+++ clang/test/CodeGenOpenCL/convergent.cl
@@ -134,7 +134,7 @@
   __asm__ volatile("s_barrier");
 }
 
-// CHECK: attributes #0 = { nofree noinline norecurse nounwind willreturn "
+// CHECK: attributes #0 = { nofree noinline norecurse nounwind willreturn mustprogress "
 // CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} }
 // CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} }
 // CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to