1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=mem2reg -S | FileCheck %s
4 ; This tests that mem2reg preserves the !nonnull metadata on loads
5 ; from allocas that get optimized out.
7 ; Check the case where the alloca in question has a single store.
8 define ptr @single_store_noundef(ptr %arg) {
9 ; CHECK-LABEL: @single_store_noundef(
11 ; CHECK-NEXT: [[ARG_LOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
12 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr [[ARG_LOAD]], null
13 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
14 ; CHECK-NEXT: ret ptr [[ARG_LOAD]]
18 %arg.load = load ptr, ptr %arg, align 8
19 store ptr %arg.load, ptr %buf, align 8
20 %buf.load = load ptr, ptr %buf, !nonnull !0, !noundef !0
24 define ptr @single_store_missing_noundef(ptr %arg) {
25 ; CHECK-LABEL: @single_store_missing_noundef(
27 ; CHECK-NEXT: [[ARG_LOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
28 ; CHECK-NEXT: ret ptr [[ARG_LOAD]]
32 %arg.load = load ptr, ptr %arg, align 8
33 store ptr %arg.load, ptr %buf, align 8
34 %buf.load = load ptr, ptr %buf, !nonnull !0
38 ; Check the case where the alloca in question has more than one
39 ; store but still within one basic block.
40 define ptr @single_block_noundef(ptr %arg) {
41 ; CHECK-LABEL: @single_block_noundef(
43 ; CHECK-NEXT: [[ARG_LOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
44 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr [[ARG_LOAD]], null
45 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
46 ; CHECK-NEXT: ret ptr [[ARG_LOAD]]
50 %arg.load = load ptr, ptr %arg, align 8
51 store ptr null, ptr %buf, align 8
52 store ptr %arg.load, ptr %buf, align 8
53 %buf.load = load ptr, ptr %buf, !nonnull !0, !noundef !0
57 define ptr @single_block_missing_noundef(ptr %arg) {
58 ; CHECK-LABEL: @single_block_missing_noundef(
60 ; CHECK-NEXT: [[ARG_LOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
61 ; CHECK-NEXT: ret ptr [[ARG_LOAD]]
65 %arg.load = load ptr, ptr %arg, align 8
66 store ptr null, ptr %buf, align 8
67 store ptr %arg.load, ptr %buf, align 8
68 %buf.load = load ptr, ptr %buf, !nonnull !0
72 ; Check the case where the alloca in question has more than one
73 ; store and also reads ands writes in multiple blocks.
74 define ptr @multi_block_noundef(ptr %arg) {
75 ; CHECK-LABEL: @multi_block_noundef(
77 ; CHECK-NEXT: [[ARG_LOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
78 ; CHECK-NEXT: br label [[NEXT:%.*]]
80 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr [[ARG_LOAD]], null
81 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
82 ; CHECK-NEXT: ret ptr [[ARG_LOAD]]
86 %arg.load = load ptr, ptr %arg, align 8
87 store ptr null, ptr %buf, align 8
90 store ptr %arg.load, ptr %buf, align 8
91 %buf.load = load ptr, ptr %buf, !nonnull !0, !noundef !0
95 define ptr @multi_block_missing_noundef(ptr %arg) {
96 ; CHECK-LABEL: @multi_block_missing_noundef(
98 ; CHECK-NEXT: [[ARG_LOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
99 ; CHECK-NEXT: br label [[NEXT:%.*]]
101 ; CHECK-NEXT: ret ptr [[ARG_LOAD]]
105 %arg.load = load ptr, ptr %arg, align 8
106 store ptr null, ptr %buf, align 8
109 store ptr %arg.load, ptr %buf, align 8
110 %buf.load = load ptr, ptr %buf, !nonnull !0
114 ; Check that we don't add an assume if it's not
115 ; necessary i.e. the value is already implied to be nonnull
116 define ptr @no_assume(ptr %arg) {
117 ; CHECK-LABEL: @no_assume(
119 ; CHECK-NEXT: [[ARG_LOAD:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
120 ; CHECK-NEXT: [[CN:%.*]] = icmp ne ptr [[ARG_LOAD]], null
121 ; CHECK-NEXT: br i1 [[CN]], label [[NEXT:%.*]], label [[FIN:%.*]]
123 ; CHECK-NEXT: ret ptr [[ARG_LOAD]]
125 ; CHECK-NEXT: ret ptr null
129 %arg.load = load ptr, ptr %arg, align 8
130 %cn = icmp ne ptr %arg.load, null
131 br i1 %cn, label %next, label %fin
133 ; At this point the above nonnull check ensures that
134 ; the value %arg.load is nonnull in this block and thus
135 ; we need not add the assume.
136 store ptr %arg.load, ptr %buf, align 8
137 %buf.load = load ptr, ptr %buf, !nonnull !0
143 define ptr @no_store_single_load_noundef() {
144 ; CHECK-LABEL: @no_store_single_load_noundef(
146 ; CHECK-NEXT: store i1 true, ptr poison, align 1
147 ; CHECK-NEXT: ret ptr undef
151 %buf.load = load ptr, ptr %buf, !noundef !0
155 define ptr @no_store_multiple_loads_noundef(i1 %c) {
156 ; CHECK-LABEL: @no_store_multiple_loads_noundef(
158 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
160 ; CHECK-NEXT: store i1 true, ptr poison, align 1
161 ; CHECK-NEXT: ret ptr undef
163 ; CHECK-NEXT: store i1 true, ptr poison, align 1
164 ; CHECK-NEXT: ret ptr undef
168 br i1 %c, label %if, label %else
171 %buf.load = load ptr, ptr %buf, !noundef !0
175 %buf.load2 = load ptr, ptr %buf, !noundef !0
179 define ptr @no_store_single_load_nonnull_noundef() {
180 ; CHECK-LABEL: @no_store_single_load_nonnull_noundef(
182 ; CHECK-NEXT: store i1 true, ptr poison, align 1
183 ; CHECK-NEXT: ret ptr undef
187 %buf.load = load ptr, ptr %buf, !nonnull !0, !noundef !0
191 define ptr @no_store_multiple_loads_nonnull_noundef(i1 %c) {
192 ; CHECK-LABEL: @no_store_multiple_loads_nonnull_noundef(
194 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
196 ; CHECK-NEXT: store i1 true, ptr poison, align 1
197 ; CHECK-NEXT: ret ptr undef
199 ; CHECK-NEXT: store i1 true, ptr poison, align 1
200 ; CHECK-NEXT: ret ptr undef
204 br i1 %c, label %if, label %else
207 %buf.load = load ptr, ptr %buf, !nonnull !0, !noundef !0
211 %buf.load2 = load ptr, ptr %buf, !nonnull !0, !noundef !0