diff options
Diffstat (limited to 'llvm/test')
| -rw-r--r-- | llvm/test/Bitcode/attributes.ll | 13 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionAttrs/arg_returned.ll | 70 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll | 10 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionAttrs/nosync.ll | 352 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionAttrs/nounwind.ll | 6 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll | 16 |
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 # |

