aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/GVN
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/GVN')
-rw-r--r--test/Transforms/GVN/2009-03-10-PREOnVoid.ll56
-rw-r--r--test/Transforms/GVN/calloc-load-removal.ll25
-rw-r--r--test/Transforms/GVN/invariant-load.ll31
-rw-r--r--test/Transforms/GVN/load-pre-nonlocal.ll87
-rw-r--r--test/Transforms/GVN/rle.ll13
-rw-r--r--test/Transforms/GVN/unreachable_block_infinite_loop.ll2
6 files changed, 199 insertions, 15 deletions
diff --git a/test/Transforms/GVN/2009-03-10-PREOnVoid.ll b/test/Transforms/GVN/2009-03-10-PREOnVoid.ll
index 89d6a5f982b8..fd31fce59a84 100644
--- a/test/Transforms/GVN/2009-03-10-PREOnVoid.ll
+++ b/test/Transforms/GVN/2009-03-10-PREOnVoid.ll
@@ -53,30 +53,58 @@ bb11: ; preds = %bb7, %bb5
unreachable
}
-declare i32 @pthread_once(i32*, void ()*)
+define i32 @pthread_once(i32*, void ()*) {
+ ret i32 0
+}
-declare i8* @pthread_getspecific(i32)
+define i8* @pthread_getspecific(i32) {
+ ret i8* null
+}
-declare i32 @pthread_setspecific(i32, i8*)
+define i32 @pthread_setspecific(i32, i8*) {
+ ret i32 0
+}
-declare i32 @pthread_create(i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)
+define i32 @pthread_create(i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*) {
+ ret i32 0
+}
-declare i32 @pthread_cancel(i32)
+define i32 @pthread_cancel(i32) {
+ ret i32 0
+}
-declare i32 @pthread_mutex_lock(%struct.pthread_mutex_t*)
+define i32 @pthread_mutex_lock(%struct.pthread_mutex_t*) {
+ ret i32 0
+}
-declare i32 @pthread_mutex_trylock(%struct.pthread_mutex_t*)
+define i32 @pthread_mutex_trylock(%struct.pthread_mutex_t*) {
+ ret i32 0
+}
-declare i32 @pthread_mutex_unlock(%struct.pthread_mutex_t*)
+define i32 @pthread_mutex_unlock(%struct.pthread_mutex_t*) {
+ ret i32 0
+}
-declare i32 @pthread_mutex_init(%struct.pthread_mutex_t*, %struct.__sched_param*)
+define i32 @pthread_mutex_init(%struct.pthread_mutex_t*, %struct.__sched_param*) {
+ ret i32 0
+}
-declare i32 @pthread_key_create(i32*, void (i8*)*)
+define i32 @pthread_key_create(i32*, void (i8*)*) {
+ ret i32 0
+}
-declare i32 @pthread_key_delete(i32)
+define i32 @pthread_key_delete(i32) {
+ ret i32 0
+}
-declare i32 @pthread_mutexattr_init(%struct.__sched_param*)
+define i32 @pthread_mutexattr_init(%struct.__sched_param*) {
+ ret i32 0
+}
-declare i32 @pthread_mutexattr_settype(%struct.__sched_param*, i32)
+define i32 @pthread_mutexattr_settype(%struct.__sched_param*, i32) {
+ ret i32 0
+}
-declare i32 @pthread_mutexattr_destroy(%struct.__sched_param*)
+define i32 @pthread_mutexattr_destroy(%struct.__sched_param*) {
+ ret i32 0
+}
diff --git a/test/Transforms/GVN/calloc-load-removal.ll b/test/Transforms/GVN/calloc-load-removal.ll
new file mode 100644
index 000000000000..2dde5b7b4146
--- /dev/null
+++ b/test/Transforms/GVN/calloc-load-removal.ll
@@ -0,0 +1,25 @@
+; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
+; RUN: opt -S -basicaa -gvn -disable-simplify-libcalls < %s | FileCheck %s -check-prefix=CHECK_NO_LIBCALLS
+; Check that loads from calloc are recognized as being zero.
+
+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"
+
+; Function Attrs: nounwind uwtable
+define i32 @test1() {
+ %1 = tail call noalias i8* @calloc(i64 1, i64 4)
+ %2 = bitcast i8* %1 to i32*
+ ; This load is trivially constant zero
+ %3 = load i32* %2, align 4
+ ret i32 %3
+
+; CHECK-LABEL: @test1(
+; CHECK-NOT: %3 = load i32* %2, align 4
+; CHECK: ret i32 0
+
+; CHECK_NO_LIBCALLS-LABEL: @test1(
+; CHECK_NO_LIBCALLS: load
+; CHECK_NO_LIBCALLS: ret i32 %
+
+}
+
+declare noalias i8* @calloc(i64, i64)
diff --git a/test/Transforms/GVN/invariant-load.ll b/test/Transforms/GVN/invariant-load.ll
new file mode 100644
index 000000000000..80e2226b5fae
--- /dev/null
+++ b/test/Transforms/GVN/invariant-load.ll
@@ -0,0 +1,31 @@
+; Test if the !invariant.load metadata is maintained by GVN.
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+
+define i32 @test1(i32* nocapture %p, i8* nocapture %q) {
+; CHECK-LABEL: test1
+; CHECK: %x = load i32* %p, align 4, !invariant.load !0
+; CHECK-NOT: %y = load
+entry:
+ %x = load i32* %p, align 4, !invariant.load !0
+ %conv = trunc i32 %x to i8
+ store i8 %conv, i8* %q, align 1
+ %y = load i32* %p, align 4, !invariant.load !0
+ %add = add i32 %y, 1
+ ret i32 %add
+}
+
+define i32 @test2(i32* nocapture %p, i8* nocapture %q) {
+; CHECK-LABEL: test2
+; CHECK-NOT: !invariant.load
+; CHECK-NOT: %y = load
+entry:
+ %x = load i32* %p, align 4
+ %conv = trunc i32 %x to i8
+ store i8 %conv, i8* %q, align 1
+ %y = load i32* %p, align 4, !invariant.load !0
+ %add = add i32 %y, 1
+ ret i32 %add
+}
+
+!0 = metadata !{ }
+
diff --git a/test/Transforms/GVN/load-pre-nonlocal.ll b/test/Transforms/GVN/load-pre-nonlocal.ll
new file mode 100644
index 000000000000..7bac1b78e6a2
--- /dev/null
+++ b/test/Transforms/GVN/load-pre-nonlocal.ll
@@ -0,0 +1,87 @@
+; RUN: opt -S -o - -basicaa -domtree -gvn %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.S1 = type { i32, i32 }
+
+@a2 = common global i32* null, align 8
+@a = common global i32* null, align 8
+@s1 = common global %struct.S1 zeroinitializer, align 8
+
+; Check that GVN doesn't determine %2 is partially redundant.
+
+; CHECK-LABEL: define i32 @volatile_load
+; CHECK: for.body:
+; CHECK: %2 = load i32*
+; CHECK: %3 = load volatile i32*
+; CHECK: for.cond.for.end_crit_edge:
+
+define i32 @volatile_load(i32 %n) {
+entry:
+ %cmp6 = icmp sgt i32 %n, 0
+ br i1 %cmp6, label %for.body.lr.ph, label %for.end
+
+for.body.lr.ph:
+ %0 = load i32** @a2, align 8, !tbaa !1
+ %1 = load i32** @a, align 8, !tbaa !1
+ br label %for.body
+
+for.body:
+ %indvars.iv = phi i64 [ 0, %for.body.lr.ph ], [ %indvars.iv.next, %for.body ]
+ %s.09 = phi i32 [ 0, %for.body.lr.ph ], [ %add, %for.body ]
+ %p.08 = phi i32* [ %0, %for.body.lr.ph ], [ %incdec.ptr, %for.body ]
+ %2 = load i32* %p.08, align 4, !tbaa !5
+ %arrayidx = getelementptr inbounds i32* %1, i64 %indvars.iv
+ store i32 %2, i32* %arrayidx, align 4, !tbaa !5
+ %3 = load volatile i32* %p.08, align 4, !tbaa !5
+ %add = add nsw i32 %3, %s.09
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %incdec.ptr = getelementptr inbounds i32* %p.08, i64 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.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:
+ %add.lcssa = phi i32 [ %add, %for.body ]
+ br label %for.end
+
+for.end:
+ %s.0.lcssa = phi i32 [ %add.lcssa, %for.cond.for.end_crit_edge ], [ 0, %entry ]
+ ret i32 %s.0.lcssa
+}
+
+; %1 is partially redundant if %0 can be widened to a 64-bit load.
+
+; CHECK-LABEL: define i32 @overaligned_load
+; CHECK: if.end:
+; CHECK-NOT: %1 = load i32*
+
+define i32 @overaligned_load(i32 %a, i32* nocapture %b) {
+entry:
+ %cmp = icmp sgt i32 %a, 0
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %0 = load i32* getelementptr inbounds (%struct.S1* @s1, i64 0, i32 0), align 8, !tbaa !5
+ br label %if.end
+
+if.else:
+ %arrayidx = getelementptr inbounds i32* %b, i64 2
+ store i32 10, i32* %arrayidx, align 4, !tbaa !5
+ br label %if.end
+
+if.end:
+ %i.0 = phi i32 [ %0, %if.then ], [ 0, %if.else ]
+ %p.0 = phi i32* [ getelementptr inbounds (%struct.S1* @s1, i64 0, i32 0), %if.then ], [ %b, %if.else ]
+ %add.ptr = getelementptr inbounds i32* %p.0, i64 1
+ %1 = load i32* %add.ptr, align 4, !tbaa !5
+ %add1 = add nsw i32 %1, %i.0
+ ret i32 %add1
+}
+
+!1 = metadata !{metadata !2, metadata !2, i64 0}
+!2 = metadata !{metadata !"any pointer", metadata !3, i64 0}
+!3 = metadata !{metadata !"omnipotent char", metadata !4, i64 0}
+!4 = metadata !{metadata !"Simple C/C++ TBAA"}
+!5 = metadata !{metadata !6, metadata !6, i64 0}
+!6 = metadata !{metadata !"int", metadata !3, i64 0}
diff --git a/test/Transforms/GVN/rle.ll b/test/Transforms/GVN/rle.ll
index 8d289b06997c..6aac93e75a78 100644
--- a/test/Transforms/GVN/rle.ll
+++ b/test/Transforms/GVN/rle.ll
@@ -318,6 +318,19 @@ define i8 @coerce_offset0(i32 %V, i32* %P) {
; CHECK: ret i8
}
+define i8 @coerce_offset0_addrspacecast(i32 %V, i32* %P) {
+ store i32 %V, i32* %P
+
+ %P2 = addrspacecast i32* %P to i8 addrspace(1)*
+ %P3 = getelementptr i8 addrspace(1)* %P2, i32 2
+
+ %A = load i8 addrspace(1)* %P3
+ ret i8 %A
+; CHECK-LABEL: @coerce_offset0_addrspacecast(
+; CHECK-NOT: load
+; CHECK: ret i8
+}
+
;; non-local i32/float -> i8 load forwarding.
define i8 @coerce_offset_nonlocal0(i32* %P, i1 %cond) {
%P2 = bitcast i32* %P to float*
diff --git a/test/Transforms/GVN/unreachable_block_infinite_loop.ll b/test/Transforms/GVN/unreachable_block_infinite_loop.ll
index fe335ced5c37..fca5a28b38dd 100644
--- a/test/Transforms/GVN/unreachable_block_infinite_loop.ll
+++ b/test/Transforms/GVN/unreachable_block_infinite_loop.ll
@@ -1,4 +1,4 @@
-; RUN: opt -memdep -gvn -disable-output
+; RUN: opt -memdep -gvn -disable-output < %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"
target triple = "x86_64-apple-darwin10.0"