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,147 @@ +; 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) 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; +; } + +; FIXME: nosync missing +; CHECK: define i32 @load_monotonic(i32* nocapture readonly) norecurse nounwind uwtable +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); +; } + +; FIXME: nosync missing +; CHECK: define void @store_monotonic(i32* nocapture readonly) norecurse nounwind uwtable +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; +; } + +; CHECK: define i32 @load_acquire(i32* nocapture readonly) norecurse nounwind uwtable +define i32 @bar(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); +; } + +; CHECK: define void @load_release(i32* nocapture) norecurse nounwind uwtable +define void @test(i32* nocapture) norecurse nounwind uwtable { + store atomic i32 10, i32* %0 release, align 4 + ret void +} + +; TEST 6 - negative, should not deduce nosync +; volatile store. +; void volatile_store(volatile int *num) { +; *num = 14; +; } + +; CHECK: define void @volatile_store(i32*) norecurse nounwind uwtable +define void @volatile_store(i32*) norecurse nounwind uwtable { + store volatile i32 14, i32* %0, align 4, !tbaa !2 + ret void +} + +; TEST 7 - negative, should not deduce nosync +; volatile load. +; int volatile_load(volatile int *num) { +; int n = *num; +; return n; +; } + +; CHECK: define i32 @volatile_load(i32*) norecurse nounwind uwtable +define i32 @volatile_load(i32*) norecurse nounwind uwtable { + %2 = load volatile i32, i32* %0, align 4, !tbaa !2 + ret i32 %2 +} + +; TEST 8 +declare void @nosync_function() readnone noinline nounwind uwtable nosync + +; CHECK: define void @call_nosync_function() noinline nounwind readnone uwtable nosync +define void @call_nosync_function() nounwind uwtable noinline { + tail call void @nosync_function() + ret void +} + +; TEST 9 - negative, should not deduce nosync +declare void @might_sync() readnone noinline nounwind uwtable + +; CHECK: define void @call_might_sync() noinline nounwind readnone uwtable +define void @call_might_sync() nounwind uwtable noinline { + tail call void @might_sync() + ret void +} + +; TEST 10 - negative, should not deduce nosync +; volatile operation in same scc. Call volatile_load defined in TEST 7. + +; CHECK: define i32 @scc1(i32*) noinline nounwind uwtable +define i32 @scc1(i32*) noinline nowunwidn uwtable { + tail call void scc2(%0); + %val = tail call i32 @volatile_load(%0); + ret %val; +} + +; CHECK: define i32 @scc2(i32*) noinline nounwind uwtable +define void @scc2(i32*) noinline nounwind uwtable { + tail call i32 scc1(%0); + ret void; +} + +