summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test')
-rw-r--r--llvm/test/Bitcode/attributes.ll13
-rw-r--r--llvm/test/Transforms/FunctionAttrs/arg_returned.ll70
-rw-r--r--llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll10
-rw-r--r--llvm/test/Transforms/FunctionAttrs/nosync.ll352
-rw-r--r--llvm/test/Transforms/FunctionAttrs/nounwind.ll6
-rw-r--r--llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll16
6 files changed, 420 insertions, 47 deletions
diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll
index 84630cd4bf8..c6e146791d8 100644
--- a/llvm/test/Bitcode/attributes.ll
+++ b/llvm/test/Bitcode/attributes.ll
@@ -203,8 +203,8 @@ declare void @nobuiltin()
define void @f34()
; CHECK: define void @f34()
{
- call void @nobuiltin() nobuiltin
-; CHECK: call void @nobuiltin() #38
+ call void @nobuiltin() nobuiltin
+; CHECK: call void @nobuiltin() #39
ret void;
}
@@ -362,6 +362,12 @@ define void @f61() nofree {
ret void
}
+; CHECK: define void @f62() #38
+define void @f62() nosync
+{
+ ret void
+}
+
; CHECK: attributes #0 = { noreturn }
; CHECK: attributes #1 = { nounwind }
; CHECK: attributes #2 = { readnone }
@@ -400,4 +406,5 @@ define void @f61() nofree {
; CHECK: attributes #35 = { shadowcallstack }
; CHECK: attributes #36 = { willreturn }
; CHECK: attributes #37 = { nofree }
-; CHECK: attributes #38 = { nobuiltin }
+; CHECK: attributes #38 = { nosync }
+; CHECK: attributes #39 = { nobuiltin }
diff --git a/llvm/test/Transforms/FunctionAttrs/arg_returned.ll b/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
index 57d3d72b4c5..1cde270ced1 100644
--- a/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
+++ b/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
@@ -8,13 +8,13 @@
; TEST SCC test returning an integer value argument
;
-; BOTH: Function Attrs: noinline norecurse nounwind readnone uwtable
+; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define i32 @sink_r0(i32 returned %r)
-; BOTH: Function Attrs: noinline nounwind readnone uwtable
+; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define i32 @scc_r1(i32 %a, i32 returned %r, i32 %b)
-; BOTH: Function Attrs: noinline nounwind readnone uwtable
+; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define i32 @scc_r2(i32 %a, i32 %b, i32 returned %r)
-; BOTH: Function Attrs: noinline nounwind readnone uwtable
+; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define i32 @scc_rX(i32 %a, i32 %b, i32 %r)
;
; FNATTR: define i32 @sink_r0(i32 returned %r)
@@ -159,20 +159,23 @@ return: ; preds = %cond.end, %if.then3
; TEST SCC test returning a pointer value argument
;
-; BOTH: Function Attrs: noinline norecurse nounwind readnone uwtable
+; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ptr_sink_r0(double* readnone returned %r)
-; BOTH: Function Attrs: noinline nounwind readnone uwtable
+; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ptr_scc_r1(double* %a, double* readnone returned %r, double* nocapture readnone %b)
-; BOTH: Function Attrs: noinline nounwind readnone uwtable
+; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone returned %r)
;
; FNATTR: define double* @ptr_sink_r0(double* readnone returned %r)
; FNATTR: define double* @ptr_scc_r1(double* %a, double* readnone %r, double* nocapture readnone %b)
; FNATTR: define double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone %r)
;
-; ATTRIBUTOR: define double* @ptr_sink_r0(double* returned %r)
-; ATTRIBUTOR: define double* @ptr_scc_r1(double* %a, double* returned %r, double* %b)
-; ATTRIBUTOR: define double* @ptr_scc_r2(double* %a, double* %b, double* returned %r)
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double* @ptr_sink_r0(double* returned %r)
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double* @ptr_scc_r1(double* %a, double* returned %r, double* %b)
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double* @ptr_scc_r2(double* %a, double* %b, double* returned %r)
;
; double* ptr_scc_r1(double* a, double* b, double* r);
; double* ptr_scc_r2(double* a, double* b, double* r);
@@ -258,7 +261,7 @@ return: ; preds = %cond.end, %if.then3
;
; FIXME: no-return missing
; FNATTR: define i32* @rt0(i32* readonly %a)
-; BOTH: Function Attrs: noinline nounwind readonly uwtable
+; BOTH: Function Attrs: noinline nosync nounwind readonly uwtable
; BOTH-NEXT: define i32* @rt0(i32* readonly returned %a)
define i32* @rt0(i32* %a) #0 {
entry:
@@ -277,7 +280,7 @@ entry:
;
; FIXME: no-return missing
; FNATTR: define noalias i32* @rt1(i32* nocapture readonly %a)
-; BOTH: Function Attrs: noinline nounwind readonly uwtable
+; BOTH: Function Attrs: noinline nosync nounwind readonly uwtable
; BOTH-NEXT: define noalias i32* @rt1(i32* nocapture readonly %a)
define i32* @rt1(i32* %a) #0 {
entry:
@@ -438,11 +441,12 @@ entry:
; return b == 0? b : x;
; }
;
-; BOTH: Function Attrs: noinline norecurse nounwind readnone uwtable
+; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double @select_and_phi(double returned %b)
;
; FNATTR: define double @select_and_phi(double %b)
-; ATTRIBUTOR: define double @select_and_phi(double returned %b)
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double @select_and_phi(double returned %b)
define double @select_and_phi(double %b) #0 {
entry:
%cmp = fcmp ogt double %b, 0.000000e+00
@@ -468,11 +472,13 @@ if.end: ; preds = %if.then, %entry
; return b == 0? b : x;
; }
;
-; BOTH: Function Attrs: noinline nounwind readnone uwtable
+; BOTH: Function Attrs: noinline nosync nounwind readnone uwtable
; BOTH-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b)
;
; FNATTR: define double @recursion_select_and_phi(i32 %a, double %b)
-; ATTRIBUTOR: define double @recursion_select_and_phi(i32 %a, double returned %b)
+;
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b)
define double @recursion_select_and_phi(i32 %a, double %b) #0 {
entry:
%dec = add nsw i32 %a, -1
@@ -497,11 +503,13 @@ if.end: ; preds = %if.then, %entry
; return (double*)b;
; }
;
-; BOTH: Function Attrs: noinline norecurse nounwind readnone uwtable
+; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @bitcast(i32* readnone returned %b)
;
; FNATTR: define double* @bitcast(i32* readnone %b)
-; ATTRIBUTOR: define double* @bitcast(i32* returned %b)
+;
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double* @bitcast(i32* returned %b)
define double* @bitcast(i32* %b) #0 {
entry:
%bc0 = bitcast i32* %b to double*
@@ -518,11 +526,13 @@ entry:
; return b != 0 ? b : x;
; }
;
-; BOTH: Function Attrs: noinline norecurse nounwind readnone uwtable
+; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @bitcasts_select_and_phi(i32* readnone returned %b)
;
; FNATTR: define double* @bitcasts_select_and_phi(i32* readnone %b)
-; ATTRIBUTOR: define double* @bitcasts_select_and_phi(i32* returned %b)
+;
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double* @bitcasts_select_and_phi(i32* returned %b)
define double* @bitcasts_select_and_phi(i32* %b) #0 {
entry:
%bc0 = bitcast i32* %b to double*
@@ -554,11 +564,13 @@ if.end: ; preds = %if.then, %entry
; /* return undef */
; }
;
-; BOTH: Function Attrs: noinline norecurse nounwind readnone uwtable
+; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ret_arg_arg_undef(i32* readnone returned %b)
;
; FNATTR: define double* @ret_arg_arg_undef(i32* readnone %b)
-; ATTRIBUTOR: define double* @ret_arg_arg_undef(i32* returned %b)
+;
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double* @ret_arg_arg_undef(i32* returned %b)
define double* @ret_arg_arg_undef(i32* %b) #0 {
entry:
%bc0 = bitcast i32* %b to double*
@@ -590,11 +602,13 @@ ret_undef:
; /* return undef */
; }
;
-; BOTH: Function Attrs: noinline norecurse nounwind readnone uwtable
+; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ret_undef_arg_arg(i32* readnone returned %b)
;
; FNATTR: define double* @ret_undef_arg_arg(i32* readnone %b)
-; ATTRIBUTOR: define double* @ret_undef_arg_arg(i32* returned %b)
+;
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define double* @ret_undef_arg_arg(i32* returned %b)
define double* @ret_undef_arg_arg(i32* %b) #0 {
entry:
%bc0 = bitcast i32* %b to double*
@@ -626,7 +640,7 @@ ret_arg1:
; /* return undef */
; }
;
-; BOTH: Function Attrs: noinline norecurse nounwind readnone uwtable
+; BOTH: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; BOTH-NEXT: define double* @ret_undef_arg_undef(i32* readnone returned %b)
;
; FNATTR: define double* @ret_undef_arg_undef(i32* readnone %b)
@@ -730,8 +744,8 @@ unreachableblock2:
attributes #0 = { noinline nounwind uwtable }
; BOTH-NOT: attributes #
-; BOTH-DAG: attributes #{{[0-9]*}} = { noinline norecurse nounwind readnone uwtable }
-; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nounwind readnone uwtable }
-; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nounwind readonly uwtable }
+; BOTH-DAG: attributes #{{[0-9]*}} = { noinline norecurse nosync nounwind readnone uwtable }
+; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nosync nounwind readnone uwtable }
+; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nosync nounwind readonly uwtable }
; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nounwind uwtable }
; BOTH-NOT: attributes #
diff --git a/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll b/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll
index 2f58588c790..26a3c2863de 100644
--- a/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll
+++ b/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll
@@ -20,7 +20,7 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline nounwind readnone uwtable
+; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable
; CHECK: define void @srec0()
;
define void @srec0() #0 {
@@ -37,7 +37,7 @@ entry:
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline nounwind readnone uwtable
+; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable
; CHECK: define i32 @srec16(i32 %a)
;
define i32 @srec16(i32 %a) #0 {
@@ -69,7 +69,7 @@ entry:
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline norecurse nounwind readnone uwtable
+; CHECK: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; CHECK: define i32 @endless_loop(i32 %a)
;
define i32 @endless_loop(i32 %a) #0 {
@@ -89,7 +89,7 @@ while.body: ; preds = %entry, %while.body
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline norecurse nounwind readnone uwtable
+; CHECK: Function Attrs: noinline norecurse nosync nounwind readnone uwtable
; CHECK: define i32 @dead_return(i32 returned %a)
;
define i32 @dead_return(i32 %a) #0 {
@@ -111,7 +111,7 @@ return: ; No predecessors!
; }
;
; FIXME: no-return missing
-; CHECK: Function Attrs: noinline nounwind readnone uwtable
+; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable
; CHECK: define i32 @multiple_noreturn_calls(i32 %a)
;
define i32 @multiple_noreturn_calls(i32 %a) #0 {
diff --git a/llvm/test/Transforms/FunctionAttrs/nosync.ll b/llvm/test/Transforms/FunctionAttrs/nosync.ll
new file mode 100644
index 00000000000..10d929b3104
--- /dev/null
+++ b/llvm/test/Transforms/FunctionAttrs/nosync.ll
@@ -0,0 +1,352 @@
+; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
+; RUN: opt -attributor -attributor-disable=false -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Test cases designed for the nosync function attribute.
+; FIXME's are used to indicate problems and missing attributes.
+
+; struct RT {
+; char A;
+; int B[10][20];
+; char C;
+; };
+; struct ST {
+; int X;
+; double Y;
+; struct RT Z;
+; };
+;
+; int *foo(struct ST *s) {
+; return &s[1].Z.B[5][13];
+; }
+
+; TEST 1
+; non-convergent and readnone implies nosync
+%struct.RT = type { i8, [10 x [20 x i32]], i8 }
+%struct.ST = type { i32, double, %struct.RT }
+
+; FNATTR: Function Attrs: norecurse nounwind optsize readnone ssp uwtable
+; FNATTR-NEXT: define nonnull i32* @foo(%struct.ST* readnone %s)
+; ATTRIBUTOR: Function Attrs: nosync nounwind optsize readnone ssp uwtable
+; ATTRIBUTOR-NEXT: define i32* @foo(%struct.ST* %s)
+define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
+entry:
+ %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
+ ret i32* %arrayidx
+}
+
+; TEST 2
+; atomic load with monotonic ordering
+; int load_monotonic(_Atomic int *num) {
+; int n = atomic_load_explicit(num, memory_order_relaxed);
+; return n;
+; }
+
+; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
+; FNATTR-NEXT: define i32 @load_monotonic(i32* nocapture readonly)
+; ATTRIBUTOR: Function Attrs: norecurse nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define i32 @load_monotonic(i32* nocapture readonly)
+define i32 @load_monotonic(i32* nocapture readonly) norecurse nounwind uwtable {
+ %2 = load atomic i32, i32* %0 monotonic, align 4
+ ret i32 %2
+}
+
+
+; TEST 3
+; atomic store with monotonic ordering.
+; void store_monotonic(_Atomic int *num) {
+; atomic_load_explicit(num, memory_order_relaxed);
+; }
+
+; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
+; FNATTR-NEXT: define void @store_monotonic(i32* nocapture)
+; ATTRIBUTOR: Function Attrs: norecurse nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @store_monotonic(i32* nocapture)
+define void @store_monotonic(i32* nocapture) norecurse nounwind uwtable {
+ store atomic i32 10, i32* %0 monotonic, align 4
+ ret void
+}
+
+; TEST 4 - negative, should not deduce nosync
+; atomic load with acquire ordering.
+; int load_acquire(_Atomic int *num) {
+; int n = atomic_load_explicit(num, memory_order_acquire);
+; return n;
+; }
+
+; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
+; FNATTR-NEXT: define i32 @load_acquire(i32* nocapture readonly)
+; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define i32 @load_acquire(i32* nocapture readonly)
+define i32 @load_acquire(i32* nocapture readonly) norecurse nounwind uwtable {
+ %2 = load atomic i32, i32* %0 acquire, align 4
+ ret i32 %2
+}
+
+; TEST 5 - negative, should not deduce nosync
+; atomic load with release ordering
+; void load_release(_Atomic int *num) {
+; atomic_store_explicit(num, 10, memory_order_release);
+; }
+
+; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
+; FNATTR-NEXT: define void @load_release(i32* nocapture)
+; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define void @load_release(i32* nocapture)
+define void @load_release(i32* nocapture) norecurse nounwind uwtable {
+ store atomic volatile i32 10, i32* %0 release, align 4
+ ret void
+}
+
+; TEST 6 - negative volatile, relaxed atomic
+
+; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
+; FNATTR-NEXT: define void @load_volatile_release(i32* nocapture)
+; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define void @load_volatile_release(i32* nocapture)
+define void @load_volatile_release(i32* nocapture) norecurse nounwind uwtable {
+ store atomic volatile i32 10, i32* %0 release, align 4
+ ret void
+}
+
+; TEST 7 - negative, should not deduce nosync
+; volatile store.
+; void volatile_store(volatile int *num) {
+; *num = 14;
+; }
+
+; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
+; FNATTR-NEXT: define void @volatile_store(i32*)
+; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define void @volatile_store(i32*)
+define void @volatile_store(i32*) norecurse nounwind uwtable {
+ store volatile i32 14, i32* %0, align 4
+ ret void
+}
+
+; TEST 8 - negative, should not deduce nosync
+; volatile load.
+; int volatile_load(volatile int *num) {
+; int n = *num;
+; return n;
+; }
+
+; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
+; FNATTR-NEXT: define i32 @volatile_load(i32*)
+; ATTRIBUTOR: Function Attrs: norecurse nounwind uwtable
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define i32 @volatile_load(i32*)
+define i32 @volatile_load(i32*) norecurse nounwind uwtable {
+ %2 = load volatile i32, i32* %0, align 4
+ ret i32 %2
+}
+
+; TEST 9
+
+; FNATTR: Function Attrs: noinline nosync nounwind uwtable
+; FNATTR-NEXT: declare void @nosync_function()
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: declare void @nosync_function()
+declare void @nosync_function() noinline nounwind uwtable nosync
+
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: define void @call_nosync_function()
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-next: define void @call_nosync_function()
+define void @call_nosync_function() nounwind uwtable noinline {
+ tail call void @nosync_function() noinline nounwind uwtable
+ ret void
+}
+
+; TEST 10 - negative, should not deduce nosync
+
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: declare void @might_sync()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NEXT: declare void @might_sync()
+declare void @might_sync() noinline nounwind uwtable
+
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NEXT: define void @call_might_sync()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define void @call_might_sync()
+define void @call_might_sync() nounwind uwtable noinline {
+ tail call void @might_sync() noinline nounwind uwtable
+ ret void
+}
+
+; TEST 11 - negative, should not deduce nosync
+; volatile operation in same scc. Call volatile_load defined in TEST 8.
+
+; FNATTR: Function Attrs: nofree noinline nounwind uwtable
+; FNATTR-NEXT: define i32 @scc1(i32*)
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define i32 @scc1(i32*)
+define i32 @scc1(i32*) noinline nounwind uwtable {
+ tail call void @scc2(i32* %0);
+ %val = tail call i32 @volatile_load(i32* %0);
+ ret i32 %val;
+}
+
+; FNATTR: Function Attrs: nofree noinline nounwind uwtable
+; FNATTR-NEXT: define void @scc2(i32*)
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define void @scc2(i32*)
+define void @scc2(i32*) noinline nounwind uwtable {
+ tail call i32 @scc1(i32* %0);
+ ret void;
+}
+
+; TEST 12 - fences, negative
+;
+; void foo1(int *a, std::atomic<bool> flag){
+; *a = 100;
+; atomic_thread_fence(std::memory_order_release);
+; flag.store(true, std::memory_order_relaxed);
+; }
+;
+; void bar(int *a, std::atomic<bool> flag){
+; while(!flag.load(std::memory_order_relaxed))
+; ;
+;
+; atomic_thread_fence(std::memory_order_acquire);
+; int b = *a;
+; }
+
+%"struct.std::atomic" = type { %"struct.std::__atomic_base" }
+%"struct.std::__atomic_base" = type { i8 }
+
+; FNATTR: Function Attrs: nofree norecurse nounwind
+; FNATTR-NEXT: define void @foo1(i32* nocapture, %"struct.std::atomic"* nocapture)
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR: define void @foo1(i32*, %"struct.std::atomic"*)
+define void @foo1(i32*, %"struct.std::atomic"*) {
+ store i32 100, i32* %0, align 4
+ fence release
+ %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
+ store atomic i8 1, i8* %3 monotonic, align 1
+ ret void
+}
+
+; FNATTR: Function Attrs: nofree norecurse nounwind
+; FNATTR-NEXT: define void @bar(i32* nocapture readnone, %"struct.std::atomic"* nocapture readonly)
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR: define void @bar(i32*, %"struct.std::atomic"*)
+define void @bar(i32 *, %"struct.std::atomic"*) {
+ %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
+ br label %4
+
+4: ; preds = %4, %2
+ %5 = load atomic i8, i8* %3 monotonic, align 1
+ %6 = and i8 %5, 1
+ %7 = icmp eq i8 %6, 0
+ br i1 %7, label %4, label %8
+
+8: ; preds = %4
+ fence acquire
+ ret void
+}
+
+; TEST 13 - Fence syncscope("singlethread") seq_cst
+; FNATTR: Function Attrs: nofree norecurse nounwind
+; FNATTR-NEXT: define void @foo1_singlethread(i32* nocapture, %"struct.std::atomic"* nocapture)
+; ATTRIBUTOR: Function Attrs: nosync
+; ATTRIBUTOR: define void @foo1_singlethread(i32*, %"struct.std::atomic"*)
+define void @foo1_singlethread(i32*, %"struct.std::atomic"*) {
+ store i32 100, i32* %0, align 4
+ fence syncscope("singlethread") release
+ %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
+ store atomic i8 1, i8* %3 monotonic, align 1
+ ret void
+}
+
+; FNATTR: Function Attrs: nofree norecurse nounwind
+; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture readnone, %"struct.std::atomic"* nocapture readonly)
+; ATTRIBUTOR: Function Attrs: nosync
+; ATTRIBUTOR: define void @bar_singlethread(i32*, %"struct.std::atomic"*)
+define void @bar_singlethread(i32 *, %"struct.std::atomic"*) {
+ %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
+ br label %4
+
+4: ; preds = %4, %2
+ %5 = load atomic i8, i8* %3 monotonic, align 1
+ %6 = and i8 %5, 1
+ %7 = icmp eq i8 %6, 0
+ br i1 %7, label %4, label %8
+
+8: ; preds = %4
+ fence syncscope("singlethread") acquire
+ ret void
+}
+
+declare void @llvm.memcpy(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
+declare void @llvm.memset(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
+
+; TEST 14 - negative, checking volatile intrinsics.
+
+; ATTRIBUTOR: Function Attrs: nounwind
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2)
+define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) {
+ call void @llvm.memcpy(i8* %ptr1, i8* %ptr2, i32 8, i1 1)
+ ret i32 4
+}
+
+; TEST 15 - positive, non-volatile intrinsic.
+
+; ATTRIBUTOR: Function Attrs: nosync
+; ATTRIBUTOR-NEXT: define i32 @memset_non_volatile(i8* %ptr1, i8 %val)
+define i32 @memset_non_volatile(i8* %ptr1, i8 %val) {
+ call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0)
+ ret i32 4
+}
+
+; TEST 16 - negative, inline assembly.
+
+; ATTRIBUTOR: define i32 @inline_asm_test(i32 %x)
+define i32 @inline_asm_test(i32 %x) {
+ call i32 asm "bswap $0", "=r,r"(i32 %x)
+ ret i32 4
+}
+
+declare void @readnone_test() convergent readnone
+
+; ATTRIBUTOR: define void @convergent_readnone()
+; TEST 17 - negative. Convergent
+define void @convergent_readnone(){
+ call void @readnone_test()
+ ret void
+}
+
+; ATTRIBUTOR: Function Attrs: nounwind
+; ATTRIBUTOR-NEXT: declare void @llvm.x86.sse2.clflush(i8*)
+declare void @llvm.x86.sse2.clflush(i8*)
+@a = common global i32 0, align 4
+
+; TEST 18 - negative. Synchronizing intrinsic
+
+; ATTRIBUTOR: Function Attrs: nounwind
+; ATTRIBUTOR-NOT: nosync
+; ATTRIBUTOR-NEXT: define void @i_totally_sync()
+define void @i_totally_sync() {
+ tail call void @llvm.x86.sse2.clflush(i8* bitcast (i32* @a to i8*))
+ ret void
+}
+
+declare float @llvm.cos(float %val) readnone
+
+; TEST 19 - positive, readnone & non-convergent intrinsic.
+
+; ATTRIBUTOR: Function Attrs: nosync nounwind
+; ATTRIBUTOR-NEXT: define i32 @cos_test(float %x)
+define i32 @cos_test(float %x) {
+ call float @llvm.cos(float %x)
+ ret i32 4
+}
diff --git a/llvm/test/Transforms/FunctionAttrs/nounwind.ll b/llvm/test/Transforms/FunctionAttrs/nounwind.ll
index 219c10dcc6b..3aeb824bb06 100644
--- a/llvm/test/Transforms/FunctionAttrs/nounwind.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nounwind.ll
@@ -4,7 +4,7 @@
; TEST 1
; CHECK: Function Attrs: norecurse nounwind readnone
; CHECK-NEXT: define i32 @foo1()
-; ATTRIBUTOR: Function Attrs: nounwind
+; ATTRIBUTOR: Function Attrs: nosync nounwind
; ATTRIBUTOR-NEXT: define i32 @foo1()
define i32 @foo1() {
ret i32 1
@@ -13,7 +13,7 @@ define i32 @foo1() {
; TEST 2
; CHECK: Function Attrs: nounwind readnone
; CHECK-NEXT: define i32 @scc1_foo()
-; ATTRIBUTOR: Function Attrs: nounwind
+; ATTRIBUTOR: Function Attrs: nosync nounwind
; ATTRIBUTOR-NEXT: define i32 @scc1_foo()
define i32 @scc1_foo() {
%1 = call i32 @scc1_bar()
@@ -24,7 +24,7 @@ define i32 @scc1_foo() {
; TEST 3
; CHECK: Function Attrs: nounwind readnone
; CHECK-NEXT: define i32 @scc1_bar()
-; ATTRIBUTOR: Function Attrs: nounwind
+; ATTRIBUTOR: Function Attrs: nosync nounwind
; ATTRIBUTOR-NEXT: define i32 @scc1_bar()
define i32 @scc1_bar() {
%1 = call i32 @scc1_foo()
diff --git a/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll b/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll
index 162feaee0a3..de32a949381 100644
--- a/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll
+++ b/llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll
@@ -30,7 +30,7 @@
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-; CHECK: Function Attrs: nofree nounwind
+; CHECK: Function Attrs: nofree nosync nounwind
; CHECK-NEXT: define i32* @external_ret2_nrw(i32* %n0, i32* %r0, i32* returned %w0)
define i32* @external_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
entry:
@@ -41,7 +41,7 @@ entry:
ret i32* %call3
}
-; CHECK: Function Attrs: nofree nounwind
+; CHECK: Function Attrs: nofree nosync nounwind
; CHECK-NEXT: define internal i32* @internal_ret0_nw(i32* returned %n0, i32* %w0)
define internal i32* @internal_ret0_nw(i32* %n0, i32* %w0) {
entry:
@@ -70,7 +70,7 @@ return: ; preds = %if.end, %if.then
ret i32* %retval.0
}
-; CHECK: Function Attrs: nofree nounwind
+; CHECK: Function Attrs: nofree nosync nounwind
; CHECK-NEXT: define internal i32* @internal_ret1_rrw(i32* %r0, i32* returned %r1, i32* %w0)
define internal i32* @internal_ret1_rrw(i32* %r0, i32* %r1, i32* %w0) {
entry:
@@ -102,7 +102,7 @@ return: ; preds = %if.end, %if.then
ret i32* %retval.0
}
-; CHECK: Function Attrs: nofree norecurse nounwind
+; CHECK: Function Attrs: nofree norecurse nosync nounwind
; CHECK-NEXT: define i32* @external_sink_ret2_nrw(i32* readnone %n0, i32* nocapture readonly %r0, i32* returned %w0)
define i32* @external_sink_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
entry:
@@ -121,7 +121,7 @@ return: ; preds = %if.end, %if.then
ret i32* %w0
}
-; CHECK: Function Attrs: nofree nounwind
+; CHECK: Function Attrs: nofree nosync nounwind
; CHECK-NEXT: define internal i32* @internal_ret1_rw(i32* %r0, i32* returned %w0)
define internal i32* @internal_ret1_rw(i32* %r0, i32* %w0) {
entry:
@@ -147,7 +147,7 @@ return: ; preds = %if.end, %if.then
ret i32* %retval.0
}
-; CHECK: Function Attrs: nofree nounwind
+; CHECK: Function Attrs: nofree nosync nounwind
; CHECK-NEXT: define i32* @external_source_ret2_nrw(i32* %n0, i32* %r0, i32* returned %w0)
define i32* @external_source_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) {
entry:
@@ -160,6 +160,6 @@ entry:
; for a subset relation.
;
; CHECK-NOT: attributes #
-; CHECK: attributes #{{.*}} = { nofree nounwind }
-; CHECK: attributes #{{.*}} = { nofree norecurse nounwind }
+; CHECK: attributes #{{.*}} = { nofree nosync nounwind }
+; CHECK: attributes #{{.*}} = { nofree norecurse nosync nounwind }
; CHECK-NOT: attributes #
OpenPOWER on IntegriCloud