647 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: llc -verify-machineinstrs -O3 -mtriple=x86_64-apple-macosx -enable-implicit-null-checks < %s | FileCheck %s3 4define i32 @imp_null_check_load(ptr %x) {5; CHECK-LABEL: imp_null_check_load:6; CHECK: ## %bb.0: ## %entry7; CHECK-NEXT: Ltmp0:8; CHECK-NEXT: movl (%rdi), %eax ## on-fault: LBB0_19; CHECK-NEXT: ## %bb.2: ## %not_null10; CHECK-NEXT: retq11; CHECK-NEXT: LBB0_1: ## %is_null12; CHECK-NEXT: movl $42, %eax13; CHECK-NEXT: retq14 15 entry:16 %c = icmp eq ptr %x, null17 br i1 %c, label %is_null, label %not_null, !make.implicit !018 19 is_null:20 ret i32 4221 22 not_null:23 %t = load i32, ptr %x24 ret i32 %t25}26 27; TODO: can make implicit28define i32 @imp_null_check_unordered_load(ptr %x) {29; CHECK-LABEL: imp_null_check_unordered_load:30; CHECK: ## %bb.0: ## %entry31; CHECK-NEXT: Ltmp1:32; CHECK-NEXT: movl (%rdi), %eax ## on-fault: LBB1_133; CHECK-NEXT: ## %bb.2: ## %not_null34; CHECK-NEXT: retq35; CHECK-NEXT: LBB1_1: ## %is_null36; CHECK-NEXT: movl $42, %eax37; CHECK-NEXT: retq38 39 entry:40 %c = icmp eq ptr %x, null41 br i1 %c, label %is_null, label %not_null, !make.implicit !042 43 is_null:44 ret i32 4245 46 not_null:47 %t = load atomic i32, ptr %x unordered, align 448 ret i32 %t49}50 51 52; TODO: Can be converted into implicit check.53;; Probably could be implicit, but we're conservative for now54define i32 @imp_null_check_seq_cst_load(ptr %x) {55; CHECK-LABEL: imp_null_check_seq_cst_load:56; CHECK: ## %bb.0: ## %entry57; CHECK-NEXT: testq %rdi, %rdi58; CHECK-NEXT: je LBB2_159; CHECK-NEXT: ## %bb.2: ## %not_null60; CHECK-NEXT: movl (%rdi), %eax61; CHECK-NEXT: retq62; CHECK-NEXT: LBB2_1: ## %is_null63; CHECK-NEXT: movl $42, %eax64; CHECK-NEXT: retq65 66 entry:67 %c = icmp eq ptr %x, null68 br i1 %c, label %is_null, label %not_null, !make.implicit !069 70 is_null:71 ret i32 4272 73 not_null:74 %t = load atomic i32, ptr %x seq_cst, align 475 ret i32 %t76}77 78;; Might be memory mapped IO, so can't rely on fault behavior79define i32 @imp_null_check_volatile_load(ptr %x) {80; CHECK-LABEL: imp_null_check_volatile_load:81; CHECK: ## %bb.0: ## %entry82; CHECK-NEXT: testq %rdi, %rdi83; CHECK-NEXT: je LBB3_184; CHECK-NEXT: ## %bb.2: ## %not_null85; CHECK-NEXT: movl (%rdi), %eax86; CHECK-NEXT: retq87; CHECK-NEXT: LBB3_1: ## %is_null88; CHECK-NEXT: movl $42, %eax89; CHECK-NEXT: retq90 91 entry:92 %c = icmp eq ptr %x, null93 br i1 %c, label %is_null, label %not_null, !make.implicit !094 95 is_null:96 ret i32 4297 98 not_null:99 %t = load volatile i32, ptr %x, align 4100 ret i32 %t101}102 103 104define i8 @imp_null_check_load_i8(ptr %x) {105; CHECK-LABEL: imp_null_check_load_i8:106; CHECK: ## %bb.0: ## %entry107; CHECK-NEXT: Ltmp2:108; CHECK-NEXT: movb (%rdi), %al ## on-fault: LBB4_1109; CHECK-NEXT: ## %bb.2: ## %not_null110; CHECK-NEXT: retq111; CHECK-NEXT: LBB4_1: ## %is_null112; CHECK-NEXT: movb $42, %al113; CHECK-NEXT: retq114 115 entry:116 %c = icmp eq ptr %x, null117 br i1 %c, label %is_null, label %not_null, !make.implicit !0118 119 is_null:120 ret i8 42121 122 not_null:123 %t = load i8, ptr %x124 ret i8 %t125}126 127define i256 @imp_null_check_load_i256(ptr %x) {128; CHECK-LABEL: imp_null_check_load_i256:129; CHECK: ## %bb.0: ## %entry130; CHECK-NEXT: movq %rdi, %rax131; CHECK-NEXT: Ltmp3:132; CHECK-NEXT: movaps (%rsi), %xmm0 ## on-fault: LBB5_1133; CHECK-NEXT: ## %bb.2: ## %not_null134; CHECK-NEXT: movaps 16(%rsi), %xmm1135; CHECK-NEXT: movaps %xmm1, 16(%rax)136; CHECK-NEXT: movaps %xmm0, (%rax)137; CHECK-NEXT: retq138; CHECK-NEXT: LBB5_1: ## %is_null139; CHECK-NEXT: xorps %xmm0, %xmm0140; CHECK-NEXT: movaps %xmm0, 16(%rax)141; CHECK-NEXT: movq $0, 8(%rax)142; CHECK-NEXT: movq $42, (%rax)143; CHECK-NEXT: retq144 145 entry:146 %c = icmp eq ptr %x, null147 br i1 %c, label %is_null, label %not_null, !make.implicit !0148 149 is_null:150 ret i256 42151 152 not_null:153 %t = load i256, ptr %x154 ret i256 %t155}156 157 158 159define i32 @imp_null_check_gep_load(ptr %x) {160; CHECK-LABEL: imp_null_check_gep_load:161; CHECK: ## %bb.0: ## %entry162; CHECK-NEXT: Ltmp4:163; CHECK-NEXT: movl 128(%rdi), %eax ## on-fault: LBB6_1164; CHECK-NEXT: ## %bb.2: ## %not_null165; CHECK-NEXT: retq166; CHECK-NEXT: LBB6_1: ## %is_null167; CHECK-NEXT: movl $42, %eax168; CHECK-NEXT: retq169 170 entry:171 %c = icmp eq ptr %x, null172 br i1 %c, label %is_null, label %not_null, !make.implicit !0173 174 is_null:175 ret i32 42176 177 not_null:178 %x.gep = getelementptr i32, ptr %x, i32 32179 %t = load i32, ptr %x.gep180 ret i32 %t181}182 183define i32 @imp_null_check_add_result(ptr %x, i32 %p) {184; CHECK-LABEL: imp_null_check_add_result:185; CHECK: ## %bb.0: ## %entry186; CHECK-NEXT: Ltmp5:187; CHECK-NEXT: addl (%rdi), %esi ## on-fault: LBB7_1188; CHECK-NEXT: ## %bb.2: ## %not_null189; CHECK-NEXT: movl %esi, %eax190; CHECK-NEXT: retq191; CHECK-NEXT: LBB7_1: ## %is_null192; CHECK-NEXT: movl $42, %eax193; CHECK-NEXT: retq194 195 entry:196 %c = icmp eq ptr %x, null197 br i1 %c, label %is_null, label %not_null, !make.implicit !0198 199 is_null:200 ret i32 42201 202 not_null:203 %t = load i32, ptr %x204 %p1 = add i32 %t, %p205 ret i32 %p1206}207 208define i32 @imp_null_check_sub_result(ptr %x, i32 %p) {209; CHECK-LABEL: imp_null_check_sub_result:210; CHECK: ## %bb.0: ## %entry211; CHECK-NEXT: Ltmp6:212; CHECK-NEXT: movl (%rdi), %eax ## on-fault: LBB8_1213; CHECK-NEXT: ## %bb.2: ## %not_null214; CHECK-NEXT: subl %esi, %eax215; CHECK-NEXT: retq216; CHECK-NEXT: LBB8_1: ## %is_null217; CHECK-NEXT: movl $42, %eax218; CHECK-NEXT: retq219 220 entry:221 %c = icmp eq ptr %x, null222 br i1 %c, label %is_null, label %not_null, !make.implicit !0223 224 is_null:225 ret i32 42226 227 not_null:228 %t = load i32, ptr %x229 %p1 = sub i32 %t, %p230 ret i32 %p1231}232 233define i32 @imp_null_check_mul_result(ptr %x, i32 %p) {234; CHECK-LABEL: imp_null_check_mul_result:235; CHECK: ## %bb.0: ## %entry236; CHECK-NEXT: Ltmp7:237; CHECK-NEXT: imull (%rdi), %esi ## on-fault: LBB9_1238; CHECK-NEXT: ## %bb.2: ## %not_null239; CHECK-NEXT: movl %esi, %eax240; CHECK-NEXT: retq241; CHECK-NEXT: LBB9_1: ## %is_null242; CHECK-NEXT: movl $42, %eax243; CHECK-NEXT: retq244 245 entry:246 %c = icmp eq ptr %x, null247 br i1 %c, label %is_null, label %not_null, !make.implicit !0248 249 is_null:250 ret i32 42251 252 not_null:253 %t = load i32, ptr %x254 %p1 = mul i32 %t, %p255 ret i32 %p1256}257 258define i32 @imp_null_check_udiv_result(ptr %x, i32 %p) {259; CHECK-LABEL: imp_null_check_udiv_result:260; CHECK: ## %bb.0: ## %entry261; CHECK-NEXT: Ltmp8:262; CHECK-NEXT: movl (%rdi), %eax ## on-fault: LBB10_1263; CHECK-NEXT: ## %bb.2: ## %not_null264; CHECK-NEXT: xorl %edx, %edx265; CHECK-NEXT: divl %esi266; CHECK-NEXT: retq267; CHECK-NEXT: LBB10_1: ## %is_null268; CHECK-NEXT: movl $42, %eax269; CHECK-NEXT: retq270 271 entry:272 %c = icmp eq ptr %x, null273 br i1 %c, label %is_null, label %not_null, !make.implicit !0274 275 is_null:276 ret i32 42277 278 not_null:279 %t = load i32, ptr %x280 %p1 = udiv i32 %t, %p281 ret i32 %p1282}283 284define i32 @imp_null_check_shl_result(ptr %x, i32 %p) {285; CHECK-LABEL: imp_null_check_shl_result:286; CHECK: ## %bb.0: ## %entry287; CHECK-NEXT: Ltmp9:288; CHECK-NEXT: movl (%rdi), %eax ## on-fault: LBB11_1289; CHECK-NEXT: ## %bb.2: ## %not_null290; CHECK-NEXT: movl %esi, %ecx291; CHECK-NEXT: shll %cl, %eax292; CHECK-NEXT: retq293; CHECK-NEXT: LBB11_1: ## %is_null294; CHECK-NEXT: movl $42, %eax295; CHECK-NEXT: retq296 297 entry:298 %c = icmp eq ptr %x, null299 br i1 %c, label %is_null, label %not_null, !make.implicit !0300 301 is_null:302 ret i32 42303 304 not_null:305 %t = load i32, ptr %x306 %p1 = shl i32 %t, %p307 ret i32 %p1308}309 310define i32 @imp_null_check_lshr_result(ptr %x, i32 %p) {311; CHECK-LABEL: imp_null_check_lshr_result:312; CHECK: ## %bb.0: ## %entry313; CHECK-NEXT: Ltmp10:314; CHECK-NEXT: movl (%rdi), %eax ## on-fault: LBB12_1315; CHECK-NEXT: ## %bb.2: ## %not_null316; CHECK-NEXT: movl %esi, %ecx317; CHECK-NEXT: shrl %cl, %eax318; CHECK-NEXT: retq319; CHECK-NEXT: LBB12_1: ## %is_null320; CHECK-NEXT: movl $42, %eax321; CHECK-NEXT: retq322 323 entry:324 %c = icmp eq ptr %x, null325 br i1 %c, label %is_null, label %not_null, !make.implicit !0326 327 is_null:328 ret i32 42329 330 not_null:331 %t = load i32, ptr %x332 %p1 = lshr i32 %t, %p333 ret i32 %p1334}335 336 337 338 339define i32 @imp_null_check_hoist_over_unrelated_load(ptr %x, ptr %y, ptr %z) {340; CHECK-LABEL: imp_null_check_hoist_over_unrelated_load:341; CHECK: ## %bb.0: ## %entry342; CHECK-NEXT: Ltmp11:343; CHECK-NEXT: movl (%rdi), %eax ## on-fault: LBB13_1344; CHECK-NEXT: ## %bb.2: ## %not_null345; CHECK-NEXT: movl (%rsi), %ecx346; CHECK-NEXT: movl %ecx, (%rdx)347; CHECK-NEXT: retq348; CHECK-NEXT: LBB13_1: ## %is_null349; CHECK-NEXT: movl $42, %eax350; CHECK-NEXT: retq351 352 entry:353 %c = icmp eq ptr %x, null354 br i1 %c, label %is_null, label %not_null, !make.implicit !0355 356 is_null:357 ret i32 42358 359 not_null:360 %t0 = load i32, ptr %y361 %t1 = load i32, ptr %x362 store i32 %t0, ptr %z363 ret i32 %t1364}365 366define i32 @imp_null_check_via_mem_comparision(ptr %x, i32 %val) {367; CHECK-LABEL: imp_null_check_via_mem_comparision:368; CHECK: ## %bb.0: ## %entry369; CHECK-NEXT: Ltmp12:370; CHECK-NEXT: cmpl %esi, 4(%rdi) ## on-fault: LBB14_3371; CHECK-NEXT: ## %bb.1: ## %not_null372; CHECK-NEXT: jge LBB14_2373; CHECK-NEXT: ## %bb.4: ## %ret_100374; CHECK-NEXT: movl $100, %eax375; CHECK-NEXT: retq376; CHECK-NEXT: LBB14_3: ## %is_null377; CHECK-NEXT: movl $42, %eax378; CHECK-NEXT: retq379; CHECK-NEXT: LBB14_2: ## %ret_200380; CHECK-NEXT: movl $200, %eax381; CHECK-NEXT: retq382 383 entry:384 %c = icmp eq ptr %x, null385 br i1 %c, label %is_null, label %not_null, !make.implicit !0386 387 is_null:388 ret i32 42389 390 not_null:391 %x.loc = getelementptr i32, ptr %x, i32 1392 %t = load i32, ptr %x.loc393 %m = icmp slt i32 %t, %val394 br i1 %m, label %ret_100, label %ret_200395 396 ret_100:397 ret i32 100398 399 ret_200:400 ret i32 200401}402 403define i32 @imp_null_check_gep_load_with_use_dep(ptr %x, i32 %a) {404; CHECK-LABEL: imp_null_check_gep_load_with_use_dep:405; CHECK: ## %bb.0: ## %entry406; CHECK-NEXT: ## kill: def $esi killed $esi def $rsi407; CHECK-NEXT: Ltmp13:408; CHECK-NEXT: movl (%rdi), %eax ## on-fault: LBB15_1409; CHECK-NEXT: ## %bb.2: ## %not_null410; CHECK-NEXT: addl %edi, %esi411; CHECK-NEXT: leal 4(%rax,%rsi), %eax412; CHECK-NEXT: retq413; CHECK-NEXT: LBB15_1: ## %is_null414; CHECK-NEXT: movl $42, %eax415; CHECK-NEXT: retq416 417 entry:418 %c = icmp eq ptr %x, null419 br i1 %c, label %is_null, label %not_null, !make.implicit !0420 421 is_null:422 ret i32 42423 424 not_null:425 %x.loc = getelementptr i32, ptr %x, i32 1426 %y = ptrtoint ptr %x.loc to i32427 %b = add i32 %a, %y428 %t = load i32, ptr %x429 %z = add i32 %t, %b430 ret i32 %z431}432 433;; TODO: We could handle this case as we can lift the fence into the434;; previous block before the conditional without changing behavior.435define i32 @imp_null_check_load_fence1(ptr %x) {436; CHECK-LABEL: imp_null_check_load_fence1:437; CHECK: ## %bb.0: ## %entry438; CHECK-NEXT: testq %rdi, %rdi439; CHECK-NEXT: je LBB16_1440; CHECK-NEXT: ## %bb.2: ## %not_null441; CHECK-NEXT: ##MEMBARRIER442; CHECK-NEXT: movl (%rdi), %eax443; CHECK-NEXT: retq444; CHECK-NEXT: LBB16_1: ## %is_null445; CHECK-NEXT: movl $42, %eax446; CHECK-NEXT: retq447 448entry:449 %c = icmp eq ptr %x, null450 br i1 %c, label %is_null, label %not_null, !make.implicit !0451 452is_null:453 ret i32 42454 455not_null:456 fence acquire457 %t = load i32, ptr %x458 ret i32 %t459}460 461;; TODO: We could handle this case as we can lift the fence into the462;; previous block before the conditional without changing behavior.463define i32 @imp_null_check_load_fence2(ptr %x) {464; CHECK-LABEL: imp_null_check_load_fence2:465; CHECK: ## %bb.0: ## %entry466; CHECK-NEXT: testq %rdi, %rdi467; CHECK-NEXT: je LBB17_1468; CHECK-NEXT: ## %bb.2: ## %not_null469; CHECK-NEXT: lock orl $0, -{{[0-9]+}}(%rsp)470; CHECK-NEXT: movl (%rdi), %eax471; CHECK-NEXT: retq472; CHECK-NEXT: LBB17_1: ## %is_null473; CHECK-NEXT: movl $42, %eax474; CHECK-NEXT: retq475 476entry:477 %c = icmp eq ptr %x, null478 br i1 %c, label %is_null, label %not_null, !make.implicit !0479 480is_null:481 ret i32 42482 483not_null:484 fence seq_cst485 %t = load i32, ptr %x486 ret i32 %t487}488 489define void @imp_null_check_store(ptr %x) {490; CHECK-LABEL: imp_null_check_store:491; CHECK: ## %bb.0: ## %entry492; CHECK-NEXT: Ltmp14:493; CHECK-NEXT: movl $1, (%rdi) ## on-fault: LBB18_1494; CHECK-NEXT: ## %bb.2: ## %not_null495; CHECK-NEXT: retq496; CHECK-NEXT: LBB18_1: ## %is_null497; CHECK-NEXT: retq498 499 entry:500 %c = icmp eq ptr %x, null501 br i1 %c, label %is_null, label %not_null, !make.implicit !0502 503 is_null:504 ret void505 506 not_null:507 store i32 1, ptr %x508 ret void509}510 511;; TODO: can be implicit512define void @imp_null_check_unordered_store(ptr %x) {513; CHECK-LABEL: imp_null_check_unordered_store:514; CHECK: ## %bb.0: ## %entry515; CHECK-NEXT: Ltmp15:516; CHECK-NEXT: movl $1, (%rdi) ## on-fault: LBB19_1517; CHECK-NEXT: ## %bb.2: ## %not_null518; CHECK-NEXT: retq519; CHECK-NEXT: LBB19_1: ## %is_null520; CHECK-NEXT: retq521 522 entry:523 %c = icmp eq ptr %x, null524 br i1 %c, label %is_null, label %not_null, !make.implicit !0525 526 is_null:527 ret void528 529 not_null:530 store atomic i32 1, ptr %x unordered, align 4531 ret void532}533 534define i32 @imp_null_check_neg_gep_load(ptr %x) {535; CHECK-LABEL: imp_null_check_neg_gep_load:536; CHECK: ## %bb.0: ## %entry537; CHECK-NEXT: Ltmp16:538; CHECK-NEXT: movl -128(%rdi), %eax ## on-fault: LBB20_1539; CHECK-NEXT: ## %bb.2: ## %not_null540; CHECK-NEXT: retq541; CHECK-NEXT: LBB20_1: ## %is_null542; CHECK-NEXT: movl $42, %eax543; CHECK-NEXT: retq544 545 entry:546 %c = icmp eq ptr %x, null547 br i1 %c, label %is_null, label %not_null, !make.implicit !0548 549 is_null:550 ret i32 42551 552 not_null:553 %x.gep = getelementptr i32, ptr %x, i32 -32554 %t = load i32, ptr %x.gep555 ret i32 %t556}557 558; This redefines the null check reg by doing a zero-extend and a shift on559; itself.560; Converted into implicit null check since both of these operations do not561; change the nullness of %x (i.e. if it is null, it remains null).562define i64 @imp_null_check_load_shift_addr(ptr %x) {563; CHECK-LABEL: imp_null_check_load_shift_addr:564; CHECK: ## %bb.0: ## %entry565; CHECK-NEXT: shlq $6, %rdi566; CHECK-NEXT: Ltmp17:567; CHECK-NEXT: movq 8(%rdi), %rax ## on-fault: LBB21_1568; CHECK-NEXT: ## %bb.2: ## %not_null569; CHECK-NEXT: retq570; CHECK-NEXT: LBB21_1: ## %is_null571; CHECK-NEXT: movl $42, %eax572; CHECK-NEXT: retq573 574 entry:575 %c = icmp eq ptr %x, null576 br i1 %c, label %is_null, label %not_null, !make.implicit !0577 578 is_null:579 ret i64 42580 581 not_null:582 %y = ptrtoint ptr %x to i64583 %shry = shl i64 %y, 6584 %y.ptr = inttoptr i64 %shry to ptr585 %x.loc = getelementptr i64, ptr %y.ptr, i64 1586 %t = load i64, ptr %x.loc587 ret i64 %t588}589 590; Same as imp_null_check_load_shift_addr but shift is by 3 and this is now591; converted into complex addressing.592define i64 @imp_null_check_load_shift_by_3_addr(ptr %x) {593; CHECK-LABEL: imp_null_check_load_shift_by_3_addr:594; CHECK: ## %bb.0: ## %entry595; CHECK-NEXT: Ltmp18:596; CHECK-NEXT: movq 8(,%rdi,8), %rax ## on-fault: LBB22_1597; CHECK-NEXT: ## %bb.2: ## %not_null598; CHECK-NEXT: retq599; CHECK-NEXT: LBB22_1: ## %is_null600; CHECK-NEXT: movl $42, %eax601; CHECK-NEXT: retq602 603 entry:604 %c = icmp eq ptr %x, null605 br i1 %c, label %is_null, label %not_null, !make.implicit !0606 607 is_null:608 ret i64 42609 610 not_null:611 %y = ptrtoint ptr %x to i64612 %shry = shl i64 %y, 3613 %y.ptr = inttoptr i64 %shry to ptr614 %x.loc = getelementptr i64, ptr %y.ptr, i64 1615 %t = load i64, ptr %x.loc616 ret i64 %t617}618 619define i64 @imp_null_check_load_shift_add_addr(ptr %x) {620; CHECK-LABEL: imp_null_check_load_shift_add_addr:621; CHECK: ## %bb.0: ## %entry622; CHECK-NEXT: Ltmp19:623; CHECK-NEXT: movq 3526(,%rdi,8), %rax ## on-fault: LBB23_1624; CHECK-NEXT: ## %bb.2: ## %not_null625; CHECK-NEXT: retq626; CHECK-NEXT: LBB23_1: ## %is_null627; CHECK-NEXT: movl $42, %eax628; CHECK-NEXT: retq629 630 entry:631 %c = icmp eq ptr %x, null632 br i1 %c, label %is_null, label %not_null, !make.implicit !0633 634 is_null:635 ret i64 42636 637 not_null:638 %y = ptrtoint ptr %x to i64639 %shry = shl i64 %y, 3640 %shry.add = add i64 %shry, 3518641 %y.ptr = inttoptr i64 %shry.add to ptr642 %x.loc = getelementptr i64, ptr %y.ptr, i64 1643 %t = load i64, ptr %x.loc644 ret i64 %t645}646!0 = !{}647