summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/GlobalOpt
diff options
context:
space:
mode:
authorManoj Gupta <manojgupta@google.com>2018-07-09 22:27:23 +0000
committerManoj Gupta <manojgupta@google.com>2018-07-09 22:27:23 +0000
commit77eeac3d9e9418ac0aea131d20ac84b656977814 (patch)
tree0ca98362b1ae59875a26b0df269bf09a1854d982 /llvm/test/Transforms/GlobalOpt
parent0230f7c763c5b5f988f629506f0ce050fbacaed4 (diff)
downloadbcm5719-llvm-77eeac3d9e9418ac0aea131d20ac84b656977814.tar.gz
bcm5719-llvm-77eeac3d9e9418ac0aea131d20ac84b656977814.zip
llvm: Add support for "-fno-delete-null-pointer-checks"
Summary: Support for this option is needed for building Linux kernel. This is a very frequently requested feature by kernel developers. More details : https://lkml.org/lkml/2018/4/4/601 GCC option description for -fdelete-null-pointer-checks: This Assume that programs cannot safely dereference null pointers, and that no code or data element resides at address zero. -fno-delete-null-pointer-checks is the inverse of this implying that null pointer dereferencing is not undefined. This feature is implemented in LLVM IR in this CL as the function attribute "null-pointer-is-valid"="true" in IR (Under review at D47894). The CL updates several passes that assumed null pointer dereferencing is undefined to not optimize when the "null-pointer-is-valid"="true" attribute is present. Reviewers: t.p.northover, efriedma, jyknight, chandlerc, rnk, srhines, void, george.burgess.iv Reviewed By: efriedma, george.burgess.iv Subscribers: eraman, haicheng, george.burgess.iv, drinkcat, theraven, reames, sanjoy, xbolva00, llvm-commits Differential Revision: https://reviews.llvm.org/D47895 llvm-svn: 336613
Diffstat (limited to 'llvm/test/Transforms/GlobalOpt')
-rw-r--r--llvm/test/Transforms/GlobalOpt/MallocSROA-section-no-null-opt.ll34
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-1-no-null-opt.ll40
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-1.ll7
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll39
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-2.ll7
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-3-no-null-opt.ll41
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-3.ll7
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-4-no-null-opt.ll44
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-4.ll8
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll54
-rw-r--r--llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll8
-rw-r--r--llvm/test/Transforms/GlobalOpt/load-store-global-no-null-opt.ll28
-rw-r--r--llvm/test/Transforms/GlobalOpt/malloc-promote-1-no-null-opt.ll31
-rw-r--r--llvm/test/Transforms/GlobalOpt/malloc-promote-1.ll10
-rw-r--r--llvm/test/Transforms/GlobalOpt/malloc-promote-2-no-null-opt.ll24
-rw-r--r--llvm/test/Transforms/GlobalOpt/malloc-promote-2.ll8
-rw-r--r--llvm/test/Transforms/GlobalOpt/storepointer-compare-no-null-opt.ll40
-rw-r--r--llvm/test/Transforms/GlobalOpt/storepointer-no-null-opt.ll27
18 files changed, 456 insertions, 1 deletions
diff --git a/llvm/test/Transforms/GlobalOpt/MallocSROA-section-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/MallocSROA-section-no-null-opt.ll
new file mode 100644
index 00000000000..c9b3f6fc1cd
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/MallocSROA-section-no-null-opt.ll
@@ -0,0 +1,34 @@
+; RUN: opt -globalopt -S < %s | FileCheck %s
+; CHECK: @Y
+; CHECK: section ".foo"
+
+%struct.xyz = type { double, i32 }
+
+@Y = internal global %struct.xyz* null ,section ".foo" ; <%struct.xyz**> [#uses=2]
+@numf2s = external global i32 ; <i32*> [#uses=1]
+
+define void @init_net() #0 {
+; CHECK-LABEL: init_net(
+; CHECK: load i32, i32* @numf2s
+; CHECK: call i8* @malloc
+; CHECK: store %struct.xyz* {{.*}}, %struct.xyz** @Y
+entry:
+ %0 = load i32, i32* @numf2s, align 4 ; <i32> [#uses=1]
+ %mallocsize2 = shl i32 %0, 4 ; <i32> [#uses=1]
+ %malloccall3 = tail call i8* @malloc(i32 %mallocsize2) ; <i8*> [#uses=1]
+ %1 = bitcast i8* %malloccall3 to %struct.xyz* ; <%struct.xyz*> [#uses=1]
+ store %struct.xyz* %1, %struct.xyz** @Y, align 8
+ ret void
+}
+
+define %struct.xyz* @load_train() #0 {
+; CHECK-LABEL: load_train(
+; CHECK: load %struct.xyz*, %struct.xyz** @Y
+entry:
+ %0 = load %struct.xyz*, %struct.xyz** @Y, align 8 ; <%struct.xyz*> [#uses=0]
+ ret %struct.xyz* %0
+}
+
+declare noalias i8* @malloc(i32)
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-1-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-1-no-null-opt.ll
new file mode 100644
index 00000000000..c826e7f7a04
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-1-no-null-opt.ll
@@ -0,0 +1,40 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+@X = internal global %struct.foo* null
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i64 %Size) nounwind noinline #0 {
+entry:
+ %mallocsize = mul i64 %Size, 8 ; <i64> [#uses=1]
+ %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+ %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+ store %struct.foo* %.sub, %struct.foo** @X, align 4
+ ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+bb1.thread:
+ %0 = load %struct.foo*, %struct.foo** @X, align 4
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb1.thread
+ %i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+ %sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+ %1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+ %2 = load i32, i32* %1, align 4
+ %3 = add i32 %2, %sum.0.reg2mem.0
+ %indvar.next = add i32 %i.0.reg2mem.0, 1
+ %exitcond = icmp eq i32 %indvar.next, 1200
+ br i1 %exitcond, label %bb2, label %bb1
+
+bb2: ; preds = %bb1
+ ret i32 %3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-1.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-1.ll
index 6035eaaefcc..28a20ada03f 100644
--- a/llvm/test/Transforms/GlobalOpt/heap-sra-1.ll
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-1.ll
@@ -36,3 +36,10 @@ bb2: ; preds = %bb1
ret i32 %3
}
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+ %0 = load %struct.foo*, %struct.foo** @X, align 4
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll
new file mode 100644
index 00000000000..c33bcba9921
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll
@@ -0,0 +1,39 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+@X = internal global %struct.foo* null ; <%struct.foo**> [#uses=2]
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i32 %Size) nounwind noinline #0 {
+entry:
+ %malloccall = tail call i8* @malloc(i64 8000000) ; <i8*> [#uses=1]
+ %0 = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1]
+ %.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %0, i32 0, i32 0 ; <%struct.foo*> [#uses=1]
+ store %struct.foo* %.sub, %struct.foo** @X, align 4
+ ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+bb1.thread:
+ %0 = load %struct.foo*, %struct.foo** @X, align 4 ; <%struct.foo*> [#uses=1]
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb1.thread
+ %i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ] ; <i32> [#uses=2]
+ %sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ] ; <i32> [#uses=1]
+ %1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0 ; <i32*> [#uses=1]
+ %2 = load i32, i32* %1, align 4 ; <i32> [#uses=1]
+ %3 = add i32 %2, %sum.0.reg2mem.0 ; <i32> [#uses=2]
+ %indvar.next = add i32 %i.0.reg2mem.0, 1 ; <i32> [#uses=2]
+ %exitcond = icmp eq i32 %indvar.next, 1200 ; <i1> [#uses=1]
+ br i1 %exitcond, label %bb2, label %bb1
+
+bb2: ; preds = %bb1
+ ret i32 %3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-2.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-2.ll
index d66c627b184..ec05b22b33b 100644
--- a/llvm/test/Transforms/GlobalOpt/heap-sra-2.ll
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-2.ll
@@ -36,3 +36,10 @@ bb2: ; preds = %bb1
ret i32 %3
}
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+ %0 = load %struct.foo*, %struct.foo** @X, align 4
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-3-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-3-no-null-opt.ll
new file mode 100644
index 00000000000..ba3b0a418a1
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-3-no-null-opt.ll
@@ -0,0 +1,41 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+@X = internal global %struct.foo* null
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i64 %Size) nounwind noinline #0 {
+entry:
+ %mallocsize = mul i64 8, %Size ; <i64> [#uses=1]
+; CHECK: mul i64 8, %Size
+ %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+ %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+ store %struct.foo* %.sub, %struct.foo** @X, align 4
+ ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+bb1.thread:
+; CHECK: load %struct.foo*, %struct.foo** @X, align 4
+ %0 = load %struct.foo*, %struct.foo** @X, align 4
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb1.thread
+ %i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+ %sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+ %1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+ %2 = load i32, i32* %1, align 4
+ %3 = add i32 %2, %sum.0.reg2mem.0
+ %indvar.next = add i32 %i.0.reg2mem.0, 1
+ %exitcond = icmp eq i32 %indvar.next, 1200
+ br i1 %exitcond, label %bb2, label %bb1
+
+bb2: ; preds = %bb1
+ ret i32 %3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-3.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-3.ll
index 6a34364b49f..67058c8aba2 100644
--- a/llvm/test/Transforms/GlobalOpt/heap-sra-3.ll
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-3.ll
@@ -37,3 +37,10 @@ bb2: ; preds = %bb1
ret i32 %3
}
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+ %0 = load %struct.foo*, %struct.foo** @X, align 4
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-4-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-4-no-null-opt.ll
new file mode 100644
index 00000000000..607c93d1e8a
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-4-no-null-opt.ll
@@ -0,0 +1,44 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+
+@X = internal global %struct.foo* null
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i64 %Size) nounwind noinline #0 {
+entry:
+ %mallocsize = shl i64 %Size, 3 ; <i64> [#uses=1]
+ %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+; CHECK: shl i64 %Size, 3
+ %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+ store %struct.foo* %.sub, %struct.foo** @X, align 4
+ ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+; CHECK-LABEL: @baz(
+bb1.thread:
+; CHECK: load %struct.foo*, %struct.foo** @X, align 4
+ %0 = load %struct.foo*, %struct.foo** @X, align 4
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb1.thread
+ %i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+ %sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+ %1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+ %2 = load i32, i32* %1, align 4
+; CHECK: load i32, i32* %1, align 4
+ %3 = add i32 %2, %sum.0.reg2mem.0
+ %indvar.next = add i32 %i.0.reg2mem.0, 1
+ %exitcond = icmp eq i32 %indvar.next, 1200
+ br i1 %exitcond, label %bb2, label %bb1
+
+bb2: ; preds = %bb1
+ ret i32 %3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-4.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-4.ll
index 2176b9fcbee..71832f34923 100644
--- a/llvm/test/Transforms/GlobalOpt/heap-sra-4.ll
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-4.ll
@@ -37,3 +37,11 @@ bb2: ; preds = %bb1
ret i32 %3
}
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+ %0 = load %struct.foo*, %struct.foo** @X, align 4
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll
new file mode 100644
index 00000000000..06c74e5bfc4
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll
@@ -0,0 +1,54 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+
+@X = internal global %struct.foo* null ; <%struct.foo**> [#uses=2]
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i32 %Size) nounwind noinline #0 {
+; CHECK-LABEL: @bar(
+entry:
+ %malloccall = tail call i8* @malloc(i64 8000000) ; <i8*> [#uses=1]
+ %tmp = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1]
+ %.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %tmp, i32 0, i32 0 ; <%struct.foo*> [#uses=1]
+ store %struct.foo* %.sub, %struct.foo** @X, align 4
+ ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+; CHECK-LABEL: @baz(
+bb1.thread:
+ %tmpLD1 = load %struct.foo*, %struct.foo** @X, align 4 ; <%struct.foo*> [#uses=1]
+; CHECK: load %struct.foo*, %struct.foo** @X, align 4
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb1.thread
+ %tmp = phi %struct.foo* [%tmpLD1, %bb1.thread ], [ %tmpLD2, %bb1 ] ; <i32> [#uses=2]
+; CHECK: %tmp = phi %struct.foo* [ %tmpLD1, %bb1.thread ], [ %tmpLD2, %bb1 ]
+ %i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ] ; <i32> [#uses=2]
+ %sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %tmp3, %bb1 ] ; <i32> [#uses=1]
+ %tmp1 = getelementptr %struct.foo, %struct.foo* %tmp, i32 %i.0.reg2mem.0, i32 0 ; <i32*> [#uses=1]
+ %tmp2 = load i32, i32* %tmp1, align 4 ; <i32> [#uses=1]
+; CHECK: load i32, i32* %tmp1, align 4
+ %tmp6 = add i32 %tmp2, %sum.0.reg2mem.0 ; <i32> [#uses=2]
+ %tmp4 = getelementptr %struct.foo, %struct.foo* %tmp, i32 %i.0.reg2mem.0, i32 1 ; <i32*> [#uses=1]
+ %tmp5 = load i32 , i32 * %tmp4
+; CHECK: load i32, i32* %tmp4
+ %tmp3 = add i32 %tmp5, %tmp6
+ %indvar.next = add i32 %i.0.reg2mem.0, 1 ; <i32> [#uses=2]
+
+ %tmpLD2 = load %struct.foo*, %struct.foo** @X, align 4 ; <%struct.foo*> [#uses=1]
+; CHECK: load %struct.foo*, %struct.foo** @X, align 4
+
+ %exitcond = icmp eq i32 %indvar.next, 1200 ; <i1> [#uses=1]
+ br i1 %exitcond, label %bb2, label %bb1
+
+bb2: ; preds = %bb1
+ ret i32 %tmp3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll
index 995f9dc142c..770220dd07b 100644
--- a/llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll
+++ b/llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll
@@ -42,3 +42,11 @@ bb1: ; preds = %bb1, %bb1.thread
bb2: ; preds = %bb1
ret i32 %tmp3
}
+
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+ %0 = load %struct.foo*, %struct.foo** @X, align 4
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/load-store-global-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/load-store-global-no-null-opt.ll
new file mode 100644
index 00000000000..d319d162ff4
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/load-store-global-no-null-opt.ll
@@ -0,0 +1,28 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+@a = internal global i64* null, align 8
+; CHECK: @a
+
+; PR13968
+define void @qux_no_null_opt() nounwind #0 {
+; CHECK-LABEL: @qux_no_null_opt(
+; CHECK: getelementptr i64*, i64** @a, i32 1
+; CHECK: store i64* inttoptr (i64 1 to i64*), i64** @a
+ %b = bitcast i64** @a to i8*
+ %g = getelementptr i64*, i64** @a, i32 1
+ %cmp = icmp ne i8* null, %b
+ %cmp2 = icmp eq i8* null, %b
+ %cmp3 = icmp eq i64** null, %g
+ store i64* inttoptr (i64 1 to i64*), i64** @a, align 8
+ %l = load i64*, i64** @a, align 8
+ ret void
+}
+
+define i64* @bar() {
+ %X = load i64*, i64** @a, align 8
+ ret i64* %X
+; CHECK-LABEL: @bar(
+; CHECK: load
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/malloc-promote-1-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/malloc-promote-1-no-null-opt.ll
new file mode 100644
index 00000000000..fc6dab31640
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/malloc-promote-1-no-null-opt.ll
@@ -0,0 +1,31 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+@G = internal global i32* null ; <i32**> [#uses=3]
+; CHECK: global
+
+define void @init() #0 {
+; CHECK-LABEL: @init(
+; CHECK: store
+; CHECK: load
+ %malloccall = tail call i8* @malloc(i64 4) ; <i8*> [#uses=1]
+ %P = bitcast i8* %malloccall to i32* ; <i32*> [#uses=1]
+ store i32* %P, i32** @G
+ %GV = load i32*, i32** @G ; <i32*> [#uses=1]
+ store i32 0, i32* %GV
+ ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @get() #0 {
+; CHECK-LABEL: @get(
+; CHECK: load i32*, i32** @G
+; CHECK-NEXT: load i32, i32* %GV
+ %GV = load i32*, i32** @G ; <i32*> [#uses=1]
+ %V = load i32, i32* %GV ; <i32> [#uses=1]
+ ret i32 %V
+; CHECK: ret i32 %V
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/malloc-promote-1.ll b/llvm/test/Transforms/GlobalOpt/malloc-promote-1.ll
index d5087dea344..a8f127474e3 100644
--- a/llvm/test/Transforms/GlobalOpt/malloc-promote-1.ll
+++ b/llvm/test/Transforms/GlobalOpt/malloc-promote-1.ll
@@ -1,7 +1,7 @@
; RUN: opt < %s -globalopt -S | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
-@G = internal global i32* null ; <i32**> [#uses=3]
+@G = internal global i32* null ; <i32**> [#uses=4]
; CHECK-NOT: global
define void @init() {
@@ -22,3 +22,11 @@ define i32 @get() {
; CHECK: ret i32 0
}
+define void @foo(i64 %Size) nounwind noinline #0 {
+entry:
+ %0 = load i32*, i32** @G, align 4
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+
diff --git a/llvm/test/Transforms/GlobalOpt/malloc-promote-2-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/malloc-promote-2-no-null-opt.ll
new file mode 100644
index 00000000000..009a33435fd
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/malloc-promote-2-no-null-opt.ll
@@ -0,0 +1,24 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+@G = internal global i32* null
+
+define void @t() #0 {
+; CHECK: @t()
+; CHECK: call i8* @malloc
+; CHECK: bitcast
+; CHECK: store
+; CHECK: load
+; CHECK: getelementptr
+; CHECK: store
+ %malloccall = tail call i8* @malloc(i64 mul (i64 100, i64 4))
+ %P = bitcast i8* %malloccall to i32*
+ store i32* %P, i32** @G
+ %GV = load i32*, i32** @G
+ %GVe = getelementptr i32, i32* %GV, i32 40
+ store i32 20, i32* %GVe
+ ret void
+}
+
+declare noalias i8* @malloc(i64)
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/malloc-promote-2.ll b/llvm/test/Transforms/GlobalOpt/malloc-promote-2.ll
index 335ed82a8cf..64f379365c7 100644
--- a/llvm/test/Transforms/GlobalOpt/malloc-promote-2.ll
+++ b/llvm/test/Transforms/GlobalOpt/malloc-promote-2.ll
@@ -17,3 +17,11 @@ define void @t() {
}
declare noalias i8* @malloc(i64)
+
+define void @foo(i64 %Size) nounwind noinline #0 {
+entry:
+ %0 = load i32*, i32** @G, align 4
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/storepointer-compare-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/storepointer-compare-no-null-opt.ll
new file mode 100644
index 00000000000..709df17e0b5
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/storepointer-compare-no-null-opt.ll
@@ -0,0 +1,40 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: global
+
+@G = internal global void ()* null ; <void ()**> [#uses=2]
+
+define internal void @Actual() {
+; CHECK-LABEL: Actual(
+ ret void
+}
+
+define void @init() {
+; CHECK-LABEL: init(
+; CHECK: store void ()* @Actual, void ()** @G
+ store void ()* @Actual, void ()** @G
+ ret void
+}
+
+define void @doit() #0 {
+; CHECK-LABEL: doit(
+ %FP = load void ()*, void ()** @G ; <void ()*> [#uses=2]
+; CHECK: %FP = load void ()*, void ()** @G
+ %CC = icmp eq void ()* %FP, null ; <i1> [#uses=1]
+; CHECK: %CC = icmp eq void ()* %FP, null
+ br i1 %CC, label %isNull, label %DoCall
+; CHECK: br i1 %CC, label %isNull, label %DoCall
+
+DoCall: ; preds = %0
+; CHECK: DoCall:
+; CHECK: call void %FP()
+; CHECK: ret void
+ call void %FP( )
+ ret void
+
+isNull: ; preds = %0
+; CHECK: isNull:
+; CHECK: ret void
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
diff --git a/llvm/test/Transforms/GlobalOpt/storepointer-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/storepointer-no-null-opt.ll
new file mode 100644
index 00000000000..c9a63f0080d
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/storepointer-no-null-opt.ll
@@ -0,0 +1,27 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+@G = internal global void ()* null ; <void ()**> [#uses=2]
+; CHECK: global
+
+define internal void @Actual() {
+; CHECK-LABEL: Actual(
+ ret void
+}
+
+define void @init() {
+; CHECK-LABEL: init(
+; CHECK: store void ()* @Actual, void ()** @G
+ store void ()* @Actual, void ()** @G
+ ret void
+}
+
+define void @doit() #0 {
+; CHECK-LABEL: doit(
+; CHECK: %FP = load void ()*, void ()** @G
+; CHECK: call void %FP()
+ %FP = load void ()*, void ()** @G ; <void ()*> [#uses=1]
+ call void %FP( )
+ ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
OpenPOWER on IntegriCloud