@@ -344,4 +344,105 @@ define i1 @test_store_same_block(ptr %arg) {
344344 ret i1 %cmp
345345}
346346
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+
347448attributes #0 = { null_pointer_is_valid }
0 commit comments