1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -correlated-propagation -S | FileCheck %s 3 4define void @test1(i8* %ptr) { 5; CHECK-LABEL: @test1( 6; CHECK-NEXT: [[A:%.*]] = load i8, i8* [[PTR:%.*]], align 1 7; CHECK-NEXT: br label [[BB:%.*]] 8; CHECK: bb: 9; CHECK-NEXT: ret void 10; 11 %A = load i8, i8* %ptr 12 br label %bb 13bb: 14 icmp ne i8* %ptr, null 15 ret void 16} 17 18define void @test1_no_null_opt(i8* %ptr) #0 { 19; CHECK-LABEL: @test1_no_null_opt( 20; CHECK-NEXT: [[A:%.*]] = load i8, i8* [[PTR:%.*]], align 1 21; CHECK-NEXT: br label [[BB:%.*]] 22; CHECK: bb: 23; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[PTR]], null 24; CHECK-NEXT: ret void 25; 26 %A = load i8, i8* %ptr 27 br label %bb 28bb: 29 icmp ne i8* %ptr, null 30 ret void 31} 32 33define void @test2(i8* %ptr) { 34; CHECK-LABEL: @test2( 35; CHECK-NEXT: store i8 0, i8* [[PTR:%.*]], align 1 36; CHECK-NEXT: br label [[BB:%.*]] 37; CHECK: bb: 38; CHECK-NEXT: ret void 39; 40 store i8 0, i8* %ptr 41 br label %bb 42bb: 43 icmp ne i8* %ptr, null 44 ret void 45} 46 47define void @test2_no_null_opt(i8* %ptr) #0 { 48; CHECK-LABEL: @test2_no_null_opt( 49; CHECK-NEXT: store i8 0, i8* [[PTR:%.*]], align 1 50; CHECK-NEXT: br label [[BB:%.*]] 51; CHECK: bb: 52; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[PTR]], null 53; CHECK-NEXT: ret void 54; 55 store i8 0, i8* %ptr 56 br label %bb 57bb: 58 icmp ne i8* %ptr, null 59 ret void 60} 61 62define void @test3() { 63; CHECK-LABEL: @test3( 64; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 65; CHECK-NEXT: br label [[BB:%.*]] 66; CHECK: bb: 67; CHECK-NEXT: ret void 68; 69 %ptr = alloca i8 70 br label %bb 71bb: 72 icmp ne i8* %ptr, null 73 ret void 74} 75 76;; OK to remove icmp here since ptr is coming from alloca. 77 78define void @test3_no_null_opt() #0 { 79; CHECK-LABEL: @test3_no_null_opt( 80; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 81; CHECK-NEXT: br label [[BB:%.*]] 82; CHECK: bb: 83; CHECK-NEXT: ret void 84; 85 %ptr = alloca i8 86 br label %bb 87bb: 88 icmp ne i8* %ptr, null 89 ret void 90} 91 92declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1) 93 94define void @test4(i8* %dest, i8* %src) { 95; CHECK-LABEL: @test4( 96; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 false) 97; CHECK-NEXT: br label [[BB:%.*]] 98; CHECK: bb: 99; CHECK-NEXT: ret void 100; 101 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 false) 102 br label %bb 103bb: 104 icmp ne i8* %dest, null 105 icmp ne i8* %src, null 106 ret void 107} 108 109define void @test4_no_null_opt(i8* %dest, i8* %src) #0 { 110; CHECK-LABEL: @test4_no_null_opt( 111; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 false) 112; CHECK-NEXT: br label [[BB:%.*]] 113; CHECK: bb: 114; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[DEST]], null 115; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8* [[SRC]], null 116; CHECK-NEXT: ret void 117; 118 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 false) 119 br label %bb 120bb: 121 icmp ne i8* %dest, null 122 icmp ne i8* %src, null 123 ret void 124} 125 126declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i1) 127define void @test5(i8* %dest, i8* %src) { 128; CHECK-LABEL: @test5( 129; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 false) 130; CHECK-NEXT: br label [[BB:%.*]] 131; CHECK: bb: 132; CHECK-NEXT: ret void 133; 134 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 false) 135 br label %bb 136bb: 137 icmp ne i8* %dest, null 138 icmp ne i8* %src, null 139 ret void 140} 141 142define void @test5_no_null_opt(i8* %dest, i8* %src) #0 { 143; CHECK-LABEL: @test5_no_null_opt( 144; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 false) 145; CHECK-NEXT: br label [[BB:%.*]] 146; CHECK: bb: 147; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[DEST]], null 148; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8* [[SRC]], null 149; CHECK-NEXT: ret void 150; 151 call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 false) 152 br label %bb 153bb: 154 icmp ne i8* %dest, null 155 icmp ne i8* %src, null 156 ret void 157} 158 159declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i1) 160define void @test6(i8* %dest) { 161; CHECK-LABEL: @test6( 162; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[DEST:%.*]], i8 -1, i32 1, i1 false) 163; CHECK-NEXT: br label [[BB:%.*]] 164; CHECK: bb: 165; CHECK-NEXT: ret void 166; 167 call void @llvm.memset.p0i8.i32(i8* %dest, i8 255, i32 1, i1 false) 168 br label %bb 169bb: 170 icmp ne i8* %dest, null 171 ret void 172} 173 174define void @test6_no_null_opt(i8* %dest) #0 { 175; CHECK-LABEL: @test6_no_null_opt( 176; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[DEST:%.*]], i8 -1, i32 1, i1 false) 177; CHECK-NEXT: br label [[BB:%.*]] 178; CHECK: bb: 179; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8* [[DEST]], null 180; CHECK-NEXT: ret void 181; 182 call void @llvm.memset.p0i8.i32(i8* %dest, i8 255, i32 1, i1 false) 183 br label %bb 184bb: 185 icmp ne i8* %dest, null 186 ret void 187} 188 189define void @test7(i8* %dest, i8* %src, i32 %len) { 190; CHECK-LABEL: @test7( 191; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 [[LEN:%.*]], i1 false) 192; CHECK-NEXT: br label [[BB:%.*]] 193; CHECK: bb: 194; CHECK-NEXT: [[KEEP1:%.*]] = icmp ne i8* [[DEST]], null 195; CHECK-NEXT: [[KEEP2:%.*]] = icmp ne i8* [[SRC]], null 196; CHECK-NEXT: ret void 197; 198 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false) 199 br label %bb 200bb: 201 %KEEP1 = icmp ne i8* %dest, null 202 %KEEP2 = icmp ne i8* %src, null 203 ret void 204} 205 206declare void @llvm.memcpy.p1i8.p1i8.i32(i8 addrspace(1) *, i8 addrspace(1) *, i32, i1) 207define void @test8(i8 addrspace(1) * %dest, i8 addrspace(1) * %src) { 208; CHECK-LABEL: @test8( 209; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i32(i8 addrspace(1)* [[DEST:%.*]], i8 addrspace(1)* [[SRC:%.*]], i32 1, i1 false) 210; CHECK-NEXT: br label [[BB:%.*]] 211; CHECK: bb: 212; CHECK-NEXT: [[KEEP1:%.*]] = icmp ne i8 addrspace(1)* [[DEST]], null 213; CHECK-NEXT: [[KEEP2:%.*]] = icmp ne i8 addrspace(1)* [[SRC]], null 214; CHECK-NEXT: ret void 215; 216 call void @llvm.memcpy.p1i8.p1i8.i32(i8 addrspace(1) * %dest, i8 addrspace(1) * %src, i32 1, i1 false) 217 br label %bb 218bb: 219 %KEEP1 = icmp ne i8 addrspace(1) * %dest, null 220 %KEEP2 = icmp ne i8 addrspace(1) * %src, null 221 ret void 222} 223 224define void @test9(i8* %dest, i8* %src) { 225; CHECK-LABEL: @test9( 226; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[DEST:%.*]], i8* [[SRC:%.*]], i32 1, i1 true) 227; CHECK-NEXT: br label [[BB:%.*]] 228; CHECK: bb: 229; CHECK-NEXT: [[KEEP1:%.*]] = icmp ne i8* [[DEST]], null 230; CHECK-NEXT: [[KEEP2:%.*]] = icmp ne i8* [[SRC]], null 231; CHECK-NEXT: ret void 232; 233 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 1, i1 true) 234 br label %bb 235bb: 236 %KEEP1 = icmp ne i8* %dest, null 237 %KEEP2 = icmp ne i8* %src, null 238 ret void 239} 240 241declare void @test10_helper(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) 242 243define void @test10(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) { 244; CHECK-LABEL: @test10( 245; CHECK-NEXT: entry: 246; CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8* [[ARG1:%.*]], null 247; CHECK-NEXT: br i1 [[IS_NULL]], label [[NULL:%.*]], label [[NON_NULL:%.*]] 248; CHECK: non_null: 249; CHECK-NEXT: call void @test10_helper(i8* nonnull [[ARG1]], i8* [[ARG2:%.*]], i32 [[NON_POINTER_ARG:%.*]]) 250; CHECK-NEXT: br label [[NULL]] 251; CHECK: null: 252; CHECK-NEXT: call void @test10_helper(i8* [[ARG1]], i8* [[ARG2]], i32 [[NON_POINTER_ARG]]) 253; CHECK-NEXT: ret void 254; 255entry: 256 %is_null = icmp eq i8* %arg1, null 257 br i1 %is_null, label %null, label %non_null 258 259non_null: 260 call void @test10_helper(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) 261 br label %null 262 263null: 264 call void @test10_helper(i8* %arg1, i8* %arg2, i32 %non-pointer-arg) 265 ret void 266} 267 268declare void @test11_helper(i8* %arg) 269 270define void @test11(i8* %arg1, i8** %arg2) { 271; CHECK-LABEL: @test11( 272; CHECK-NEXT: entry: 273; CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8* [[ARG1:%.*]], null 274; CHECK-NEXT: br i1 [[IS_NULL]], label [[NULL:%.*]], label [[NON_NULL:%.*]] 275; CHECK: non_null: 276; CHECK-NEXT: br label [[MERGE:%.*]] 277; CHECK: null: 278; CHECK-NEXT: [[ANOTHER_ARG:%.*]] = alloca i8, align 1 279; CHECK-NEXT: br label [[MERGE]] 280; CHECK: merge: 281; CHECK-NEXT: [[MERGED_ARG:%.*]] = phi i8* [ [[ANOTHER_ARG]], [[NULL]] ], [ [[ARG1]], [[NON_NULL]] ] 282; CHECK-NEXT: call void @test11_helper(i8* nonnull [[MERGED_ARG]]) 283; CHECK-NEXT: ret void 284; 285entry: 286 %is_null = icmp eq i8* %arg1, null 287 br i1 %is_null, label %null, label %non_null 288 289non_null: 290 br label %merge 291 292null: 293 %another_arg = alloca i8 294 br label %merge 295 296merge: 297 %merged_arg = phi i8* [%another_arg, %null], [%arg1, %non_null] 298 call void @test11_helper(i8* %merged_arg) 299 ret void 300} 301 302declare void @test12_helper(i8* %arg) 303 304define void @test12(i8* %arg1, i8** %arg2) { 305; CHECK-LABEL: @test12( 306; CHECK-NEXT: entry: 307; CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8* [[ARG1:%.*]], null 308; CHECK-NEXT: br i1 [[IS_NULL]], label [[NULL:%.*]], label [[NON_NULL:%.*]] 309; CHECK: non_null: 310; CHECK-NEXT: br label [[MERGE:%.*]] 311; CHECK: null: 312; CHECK-NEXT: [[ANOTHER_ARG:%.*]] = load i8*, i8** [[ARG2:%.*]], align 8, !nonnull !0 313; CHECK-NEXT: br label [[MERGE]] 314; CHECK: merge: 315; CHECK-NEXT: [[MERGED_ARG:%.*]] = phi i8* [ [[ANOTHER_ARG]], [[NULL]] ], [ [[ARG1]], [[NON_NULL]] ] 316; CHECK-NEXT: call void @test12_helper(i8* nonnull [[MERGED_ARG]]) 317; CHECK-NEXT: ret void 318; 319entry: 320 %is_null = icmp eq i8* %arg1, null 321 br i1 %is_null, label %null, label %non_null 322 323non_null: 324 br label %merge 325 326null: 327 %another_arg = load i8*, i8** %arg2, !nonnull !{} 328 br label %merge 329 330merge: 331 %merged_arg = phi i8* [%another_arg, %null], [%arg1, %non_null] 332 call void @test12_helper(i8* %merged_arg) 333 ret void 334} 335 336define i1 @test_store_same_block(i8* %arg) { 337; CHECK-LABEL: @test_store_same_block( 338; CHECK-NEXT: store i8 0, i8* [[ARG:%.*]], align 1 339; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8* [[ARG]], null 340; CHECK-NEXT: ret i1 true 341; 342 store i8 0, i8* %arg 343 %cmp = icmp ne i8* %arg, null 344 ret i1 %cmp 345} 346 347attributes #0 = { null_pointer_is_valid } 348