@@ -344,4 +344,105 @@ define i1 @test_store_same_block(ptr %arg) {
344
344
ret i1 %cmp
345
345
}
346
346
347
+
348
+ define i1 @test_known_nonnull_at_callsite (ptr %src ) {
349
+ ; CHECK-LABEL: @test_known_nonnull_at_callsite(
350
+ ; CHECK-NEXT: entry:
351
+ ; CHECK-NEXT: call void @callee(ptr noundef nonnull [[SRC:%.*]])
352
+ ; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
353
+ ; CHECK-NEXT: ret i1 false
354
+ ;
355
+ entry:
356
+ call void @callee (ptr noundef nonnull %src )
357
+ %nonnull = icmp eq ptr %src , null
358
+ ret i1 %nonnull
359
+ }
360
+
361
+ define i1 @test_known_nonnull_mixed (ptr %src ) {
362
+ ; CHECK-LABEL: @test_known_nonnull_mixed(
363
+ ; CHECK-NEXT: entry:
364
+ ; CHECK-NEXT: call void @callee2(ptr nonnull [[SRC:%.*]])
365
+ ; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
366
+ ; CHECK-NEXT: ret i1 false
367
+ ;
368
+ entry:
369
+ call void @callee2 (ptr nonnull %src )
370
+ %nonnull = icmp eq ptr %src , null
371
+ ret i1 %nonnull
372
+ }
373
+
374
+ define i1 @test_known_nonnull_at_callsite_dereferenceable (ptr %src ) {
375
+ ; CHECK-LABEL: @test_known_nonnull_at_callsite_dereferenceable(
376
+ ; CHECK-NEXT: entry:
377
+ ; CHECK-NEXT: call void @callee(ptr dereferenceable(1) [[SRC:%.*]])
378
+ ; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
379
+ ; CHECK-NEXT: ret i1 false
380
+ ;
381
+ entry:
382
+ call void @callee (ptr dereferenceable (1 ) %src )
383
+ %nonnull = icmp eq ptr %src , null
384
+ ret i1 %nonnull
385
+ }
386
+
387
+ define i1 @test_known_nonnull_at_callsite_gep_inbounds (ptr %src , i64 %x ) {
388
+ ; CHECK-LABEL: @test_known_nonnull_at_callsite_gep_inbounds(
389
+ ; CHECK-NEXT: entry:
390
+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[X:%.*]]
391
+ ; CHECK-NEXT: call void @callee(ptr noundef nonnull [[GEP]])
392
+ ; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
393
+ ; CHECK-NEXT: ret i1 false
394
+ ;
395
+ entry:
396
+ %gep = getelementptr inbounds i8 , ptr %src , i64 %x
397
+ call void @callee (ptr noundef nonnull %gep )
398
+ %nonnull = icmp eq ptr %src , null
399
+ ret i1 %nonnull
400
+ }
401
+
402
+ ; Negative tests
403
+
404
+ define i1 @test_known_nonnull_at_callsite_without_noundef (ptr %src ) {
405
+ ; CHECK-LABEL: @test_known_nonnull_at_callsite_without_noundef(
406
+ ; CHECK-NEXT: entry:
407
+ ; CHECK-NEXT: call void @callee(ptr nonnull [[SRC:%.*]])
408
+ ; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
409
+ ; CHECK-NEXT: ret i1 [[NONNULL]]
410
+ ;
411
+ entry:
412
+ call void @callee (ptr nonnull %src )
413
+ %nonnull = icmp eq ptr %src , null
414
+ ret i1 %nonnull
415
+ }
416
+
417
+ define i1 @test_known_nonnull_at_callsite_dereferenceable_null_is_defined (ptr %src ) #0 {
418
+ ; CHECK-LABEL: @test_known_nonnull_at_callsite_dereferenceable_null_is_defined(
419
+ ; CHECK-NEXT: entry:
420
+ ; CHECK-NEXT: call void @callee(ptr dereferenceable(1) [[SRC:%.*]])
421
+ ; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
422
+ ; CHECK-NEXT: ret i1 [[NONNULL]]
423
+ ;
424
+ entry:
425
+ call void @callee (ptr dereferenceable (1 ) %src )
426
+ %nonnull = icmp eq ptr %src , null
427
+ ret i1 %nonnull
428
+ }
429
+
430
+ define i1 @test_known_nonnull_at_callsite_gep_without_inbounds (ptr %src , i64 %x ) {
431
+ ; CHECK-LABEL: @test_known_nonnull_at_callsite_gep_without_inbounds(
432
+ ; CHECK-NEXT: entry:
433
+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[X:%.*]]
434
+ ; CHECK-NEXT: call void @callee(ptr noundef nonnull [[GEP]])
435
+ ; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
436
+ ; CHECK-NEXT: ret i1 [[NONNULL]]
437
+ ;
438
+ entry:
439
+ %gep = getelementptr i8 , ptr %src , i64 %x
440
+ call void @callee (ptr noundef nonnull %gep )
441
+ %nonnull = icmp eq ptr %src , null
442
+ ret i1 %nonnull
443
+ }
444
+
445
+ declare void @callee (ptr )
446
+ declare void @callee2 (ptr noundef)
447
+
347
448
attributes #0 = { null_pointer_is_valid }
0 commit comments