diff options
Diffstat (limited to 'test/Transforms')
-rw-r--r-- | test/Transforms/GlobalOpt/atexit.ll | 6 | ||||
-rw-r--r-- | test/Transforms/LoopVectorize/hoist-loads.ll | 69 | ||||
-rw-r--r-- | test/Transforms/LoopVectorize/induction.ll | 30 | ||||
-rw-r--r-- | test/Transforms/ObjCARC/allocas.ll | 203 | ||||
-rw-r--r-- | test/Transforms/SLPVectorizer/X86/diamond.ll | 32 |
5 files changed, 338 insertions, 2 deletions
diff --git a/test/Transforms/GlobalOpt/atexit.ll b/test/Transforms/GlobalOpt/atexit.ll new file mode 100644 index 0000000000..dbcd0d7b00 --- /dev/null +++ b/test/Transforms/GlobalOpt/atexit.ll @@ -0,0 +1,6 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +; CHECK: ModuleID +define internal hidden i32 @__cxa_atexit(void (i8*)* nocapture %func, i8* nocapture %arg, i8* nocapture %dso_handle) nounwind readnone optsize noimplicitfloat { + unreachable +} diff --git a/test/Transforms/LoopVectorize/hoist-loads.ll b/test/Transforms/LoopVectorize/hoist-loads.ll new file mode 100644 index 0000000000..fad17350cd --- /dev/null +++ b/test/Transforms/LoopVectorize/hoist-loads.ll @@ -0,0 +1,69 @@ +; RUN: opt -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +@A = common global [1024 x float] zeroinitializer, align 16 +@B = common global [1024 x float] zeroinitializer, align 16 + +; Make sure we can vectorize in the presence of hoistable conditional loads. +; CHECK: hoist_cond_load +; CHECK: load <2 x float> + +define void @hoist_cond_load() { +entry: + br label %for.body +for.body: + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %if.end9 ] + %arrayidx = getelementptr inbounds [1024 x float]* @A, i64 0, i64 %indvars.iv + %arrayidx2 = getelementptr inbounds [1024 x float]* @B, i64 0, i64 %indvars.iv + %0 = load float* %arrayidx2, align 4 + %cmp3 = fcmp oeq float %0, 0.000000e+00 + br i1 %cmp3, label %if.end9, label %if.else + +if.else: + %1 = load float* %arrayidx, align 4 + br label %if.end9 + +if.end9: + %tmp.0 = phi float [ %1, %if.else ], [ 0.000000e+00, %for.body ] + store float %tmp.0, float* %arrayidx, align 4 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp ne i32 %lftr.wideiv, 1024 + br i1 %exitcond, label %for.body, label %for.end + +for.end: + ret void +} + +; However, we can't hoist loads whose address we have not seen unconditionally +; accessed. +; CHECK: dont_hoist_cond_load +; CHECK-NOT: load <2 x float> + +define void @dont_hoist_cond_load() { +entry: + br label %for.body +for.body: + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %if.end9 ] + %arrayidx = getelementptr inbounds [1024 x float]* @A, i64 0, i64 %indvars.iv + %arrayidx2 = getelementptr inbounds [1024 x float]* @B, i64 0, i64 %indvars.iv + %0 = load float* %arrayidx2, align 4 + %cmp3 = fcmp oeq float %0, 0.000000e+00 + br i1 %cmp3, label %if.end9, label %if.else + +if.else: + %1 = load float* %arrayidx, align 4 + br label %if.end9 + +if.end9: + %tmp.0 = phi float [ %1, %if.else ], [ 0.000000e+00, %for.body ] + store float %tmp.0, float* %arrayidx2, align 4 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp ne i32 %lftr.wideiv, 1024 + br i1 %exitcond, label %for.body, label %for.end + +for.end: + ret void +} diff --git a/test/Transforms/LoopVectorize/induction.ll b/test/Transforms/LoopVectorize/induction.ll new file mode 100644 index 0000000000..48bb438a86 --- /dev/null +++ b/test/Transforms/LoopVectorize/induction.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +; Make sure that we can handle multiple integer induction variables. +; CHECK: multi_int_induction +; CHECK: vector.body: +; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ] +; CHECK: %normalized.idx = sub i64 %index, 0 +; CHECK: %[[VAR:.*]] = trunc i64 %normalized.idx to i32 +; CHECK: %offset.idx = add i32 190, %[[VAR]] +define void @multi_int_induction(i32* %A, i32 %N) { +for.body.lr.ph: + br label %for.body + +for.body: + %indvars.iv = phi i64 [ 0, %for.body.lr.ph ], [ %indvars.iv.next, %for.body ] + %count.09 = phi i32 [ 190, %for.body.lr.ph ], [ %inc, %for.body ] + %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv + store i32 %count.09, i32* %arrayidx2, align 4 + %inc = add nsw i32 %count.09, 1 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp ne i32 %lftr.wideiv, %N + br i1 %exitcond, label %for.body, label %for.end + +for.end: + ret void +} + diff --git a/test/Transforms/ObjCARC/allocas.ll b/test/Transforms/ObjCARC/allocas.ll new file mode 100644 index 0000000000..eabd54deb7 --- /dev/null +++ b/test/Transforms/ObjCARC/allocas.ll @@ -0,0 +1,203 @@ +; RUN: opt -objc-arc -S < %s | FileCheck %s + +declare i8* @objc_retain(i8*) +declare i8* @objc_retainAutoreleasedReturnValue(i8*) +declare void @objc_release(i8*) +declare i8* @objc_autorelease(i8*) +declare i8* @objc_autoreleaseReturnValue(i8*) +declare void @objc_autoreleasePoolPop(i8*) +declare i8* @objc_autoreleasePoolPush() +declare i8* @objc_retainBlock(i8*) + +declare i8* @objc_retainedObject(i8*) +declare i8* @objc_unretainedObject(i8*) +declare i8* @objc_unretainedPointer(i8*) + +declare void @use_pointer(i8*) +declare void @callee() +declare void @callee_fnptr(void ()*) +declare void @invokee() +declare i8* @returner() +declare void @bar(i32 ()*) +declare void @use_alloca(i8**) + +declare void @llvm.dbg.value(metadata, i64, metadata) + +declare i8* @objc_msgSend(i8*, i8*, ...) + + +; In the presense of allocas, unconditionally remove retain/release pairs only +; if they are known safe in both directions. This prevents matching up an inner +; retain with the boundary guarding release in the following situation: +; +; %A = alloca +; retain(%x) +; retain(%x) <--- Inner Retain +; store %x, %A +; %y = load %A +; ... DO STUFF ... +; release(%y) +; release(%x) <--- Guarding Release +; +; rdar://13750319 + +; CHECK: define void @test1a(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test1a(i8* %x) { +entry: + %A = alloca i8* + tail call i8* @objc_retain(i8* %x) + tail call i8* @objc_retain(i8* %x) + store i8* %x, i8** %A, align 8 + %y = load i8** %A + call void @use_alloca(i8** %A) + call void @objc_release(i8* %y), !clang.imprecise_release !0 + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x), !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test1b(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test1b(i8* %x) { +entry: + %A = alloca i8* + %gep = getelementptr i8** %A, i32 0 + tail call i8* @objc_retain(i8* %x) + tail call i8* @objc_retain(i8* %x) + store i8* %x, i8** %gep, align 8 + %y = load i8** %A + call void @use_alloca(i8** %A) + call void @objc_release(i8* %y), !clang.imprecise_release !0 + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x), !clang.imprecise_release !0 + ret void +} + + +; CHECK: define void @test1c(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test1c(i8* %x) { +entry: + %A = alloca i8*, i32 3 + %gep = getelementptr i8** %A, i32 2 + tail call i8* @objc_retain(i8* %x) + tail call i8* @objc_retain(i8* %x) + store i8* %x, i8** %gep, align 8 + %y = load i8** %gep + call void @use_alloca(i8** %A) + call void @objc_release(i8* %y), !clang.imprecise_release !0 + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x), !clang.imprecise_release !0 + ret void +} + + +; CHECK: define void @test1d(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test1d(i8* %x) { +entry: + br i1 undef, label %use_allocaA, label %use_allocaB + +use_allocaA: + %allocaA = alloca i8* + br label %exit + +use_allocaB: + %allocaB = alloca i8* + br label %exit + +exit: + %A = phi i8** [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ] + %gep = getelementptr i8** %A, i32 0 + tail call i8* @objc_retain(i8* %x) + tail call i8* @objc_retain(i8* %x) + store i8* %x, i8** %gep, align 8 + %y = load i8** %gep + call void @use_alloca(i8** %A) + call void @objc_release(i8* %y), !clang.imprecise_release !0 + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x), !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test1e(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test1e(i8* %x) { +entry: + br i1 undef, label %use_allocaA, label %use_allocaB + +use_allocaA: + %allocaA = alloca i8*, i32 4 + br label %exit + +use_allocaB: + %allocaB = alloca i8*, i32 4 + br label %exit + +exit: + %A = phi i8** [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ] + %gep = getelementptr i8** %A, i32 2 + tail call i8* @objc_retain(i8* %x) + tail call i8* @objc_retain(i8* %x) + store i8* %x, i8** %gep, align 8 + %y = load i8** %gep + call void @use_alloca(i8** %A) + call void @objc_release(i8* %y), !clang.imprecise_release !0 + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x), !clang.imprecise_release !0 + ret void +} + +; CHECK: define void @test1f(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_retain(i8* %x) +; CHECK: @objc_release(i8* %y) +; CHECK: @objc_release(i8* %x) +; CHECK: ret void +; CHECK: } +define void @test1f(i8* %x) { +entry: + %allocaOne = alloca i8* + %allocaTwo = alloca i8* + %A = select i1 undef, i8** %allocaOne, i8** %allocaTwo + tail call i8* @objc_retain(i8* %x) + tail call i8* @objc_retain(i8* %x) + store i8* %x, i8** %A, align 8 + %y = load i8** %A + call void @use_alloca(i8** %A) + call void @objc_release(i8* %y), !clang.imprecise_release !0 + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x), !clang.imprecise_release !0 + ret void +} + + +!0 = metadata !{} + +declare i32 @__gxx_personality_v0(...) diff --git a/test/Transforms/SLPVectorizer/X86/diamond.ll b/test/Transforms/SLPVectorizer/X86/diamond.ll index 49c8712d20..8959b0d9ee 100644 --- a/test/Transforms/SLPVectorizer/X86/diamond.ll +++ b/test/Transforms/SLPVectorizer/X86/diamond.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basicaa -slp-vectorizer -dce -S -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s +; RUN: opt < %s -basicaa -slp-vectorizer -S -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.8.0" @@ -74,6 +74,34 @@ entry: %add20 = mul i32 %3, %mul238 %arrayidx21 = getelementptr inbounds i32* %B, i64 3 store i32 %add20, i32* %arrayidx21, align 4 - ret i32 %0 ;<--------- This value has multiple users and can't be vectorized. + ret i32 %0 ;<--------- This value has multiple users } +; In this example we have an external user that is not the first element in the vector. +; CHECK: @extr_user1 +; CHECK: store <4 x i32> +; CHECK-NEXT: extractelement <4 x i32> +; CHECK: ret +define i32 @extr_user1(i32* noalias nocapture %B, i32* noalias nocapture %A, i32 %n, i32 %m) { +entry: + %0 = load i32* %A, align 4 + %mul238 = add i32 %m, %n + %add = mul i32 %0, %mul238 + store i32 %add, i32* %B, align 4 + %arrayidx4 = getelementptr inbounds i32* %A, i64 1 + %1 = load i32* %arrayidx4, align 4 + %add8 = mul i32 %1, %mul238 + %arrayidx9 = getelementptr inbounds i32* %B, i64 1 + store i32 %add8, i32* %arrayidx9, align 4 + %arrayidx10 = getelementptr inbounds i32* %A, i64 2 + %2 = load i32* %arrayidx10, align 4 + %add14 = mul i32 %2, %mul238 + %arrayidx15 = getelementptr inbounds i32* %B, i64 2 + store i32 %add14, i32* %arrayidx15, align 4 + %arrayidx16 = getelementptr inbounds i32* %A, i64 3 + %3 = load i32* %arrayidx16, align 4 + %add20 = mul i32 %3, %mul238 + %arrayidx21 = getelementptr inbounds i32* %B, i64 3 + store i32 %add20, i32* %arrayidx21, align 4 + ret i32 %1 ;<--------- This value has multiple users +} |