diff --git a/llvm/test/Transforms/FunctionAttrs/nosync.ll b/llvm/test/Transforms/FunctionAttrs/nosync.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -0,0 +1,116 @@ +; RUN: opt -functionattrs -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; Test cases designet 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 +; attribute readnone implies nosync. +%struct.RT = type { i8, [10 x [20 x i32]], i8 } +%struct.ST = type { i32, double, %struct.RT } + +; FIXME: nosync missing +; CHECK: define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp +define i32* @foo(%struct.ST* %s) #0 { +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; +; } + +; FIXME: nosync missing +; CHECK: define dso_local i32 @load_monotonic(i32* nocapture readonly) local_unnamed_addr norecurse nounwind uwtable +define dso_local i32 @load_monotonic(i32* nocapture readonly) local_unnamed_addr #2 { + %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); +; } + +; FIXME: nosync missing +; CHECK: define dso_local void @store_monotonic(i32* nocapture readonly) local_unnamed_addr norecurse nounwind uwtable +define dso_local void @store_monotonic(i32* nocapture) local_unnamed_addr #2 { + store atomic i32 10, i32* %0 monotonic, align 4 + ret void +} + +; TEST 4 +; atomic load with acquire ordering. +; int load_acquire(_Atomic int *num) { +; int n = atomic_load_explicit(num, memory_order_acquire); +; return n; +; } + +; CHECK: define dso_local i32 @load_acquire(i32* nocapture readonly) local_unnamed_addr norecurse nounwind uwtable +define dso_local i32 @bar(i32* nocapture readonly) local_unnamed_addr #2 { + %2 = load atomic i32, i32* %0 acquire, align 4 + ret i32 %2 +} + +; TEST 5 +; atomic load with release ordering +; void load_release(_Atomic int *num) { +; atomic_store_explicit(num, 10, memory_order_release); +; } + +; CHECK: define dso_local void @load_release(i32* nocapture) local_unnamed_addr norecurse nounwind uwtable +define dso_local void @test(i32* nocapture) local_unnamed_addr #2 { + store atomic i32 10, i32* %0 release, align 4 + ret void +} + +; TEST 6 +; volatile store. +; void volatile_store(volatile int *num) { +; *num = 14; +; } + +; CHECK: define dso_local void @volatile_store(i32*) local_unnamed_addr norecurse nounwind uwtable +define dso_local void @volatile_store(i32*) local_unnamed_addr #2 { + store volatile i32 14, i32* %0, align 4, !tbaa !2 + ret void +} + +; TEST 7 +; volatile load. +; int volatile_load(volatile int *num) { +; int n = *num; +; return n; +; } + +; CHECK: define dso_local i32 @volatile_load(i32*) local_unnamed_addr norecurse nounwind uwtable +define dso_local i32 @volatile_load(i32*) local_unnamed_addr #2 { + %2 = load volatile i32, i32* %0, align 4, !tbaa !2 + ret i32 %2 +} + + +attributes #0 = { nounwind uwtable readnone optsize ssp } +attributes #1 = { nounwind uwtable } +attributes #2 = { norecurse nounwind uwtable }