brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.4 KiB · dff7e13 Raw
290 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instsimplify < %s | FileCheck %s3 4declare void @bar(ptr %a, ptr nonnull noundef %b)5declare void @bar_without_noundef(ptr %a, ptr nonnull %b)6 7; 'y' must be nonnull.8 9define i1 @caller1(ptr %x, ptr %y) {10; CHECK-LABEL: @caller1(11; CHECK-NEXT:    call void @bar(ptr [[X:%.*]], ptr [[Y:%.*]])12; CHECK-NEXT:    ret i1 false13;14  call void @bar(ptr %x, ptr %y)15  %null_check = icmp eq ptr %y, null16  ret i1 %null_check17}18 19; Don't know anything about 'y'.20 21define i1 @caller1_maybepoison(ptr %x, ptr %y) {22; CHECK-LABEL: @caller1_maybepoison(23; CHECK-NEXT:    call void @bar_without_noundef(ptr [[X:%.*]], ptr [[Y:%.*]])24; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[Y]], null25; CHECK-NEXT:    ret i1 [[NULL_CHECK]]26;27  call void @bar_without_noundef(ptr %x, ptr %y)28  %null_check = icmp eq ptr %y, null29  ret i1 %null_check30}31 32; Don't know anything about 'y'.33 34define i1 @caller2(ptr %x, ptr %y) {35; CHECK-LABEL: @caller2(36; CHECK-NEXT:    call void @bar(ptr [[Y:%.*]], ptr [[X:%.*]])37; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[Y]], null38; CHECK-NEXT:    ret i1 [[NULL_CHECK]]39;40  call void @bar(ptr %y, ptr %x)41  %null_check = icmp eq ptr %y, null42  ret i1 %null_check43}44 45; 'y' must be nonnull.46 47define i1 @caller3(ptr %x, ptr %y) {48; CHECK-LABEL: @caller3(49; CHECK-NEXT:    call void @bar(ptr [[X:%.*]], ptr [[Y:%.*]])50; CHECK-NEXT:    ret i1 true51;52  call void @bar(ptr %x, ptr %y)53  %null_check = icmp ne ptr %y, null54  ret i1 %null_check55}56 57; FIXME: The call is guaranteed to execute, so 'y' must be nonnull throughout.58 59define i1 @caller4(ptr %x, ptr %y) {60; CHECK-LABEL: @caller4(61; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp ne ptr [[Y:%.*]], null62; CHECK-NEXT:    call void @bar(ptr [[X:%.*]], ptr [[Y]])63; CHECK-NEXT:    ret i1 [[NULL_CHECK]]64;65  %null_check = icmp ne ptr %y, null66  call void @bar(ptr %x, ptr %y)67  ret i1 %null_check68}69 70; The call to bar() does not dominate the null check, so no change.71 72define i1 @caller5(ptr %x, ptr %y) {73; CHECK-LABEL: @caller5(74; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[Y:%.*]], null75; CHECK-NEXT:    br i1 [[NULL_CHECK]], label [[T:%.*]], label [[F:%.*]]76; CHECK:       t:77; CHECK-NEXT:    ret i1 [[NULL_CHECK]]78; CHECK:       f:79; CHECK-NEXT:    call void @bar(ptr [[X:%.*]], ptr [[Y]])80; CHECK-NEXT:    ret i1 [[NULL_CHECK]]81;82  %null_check = icmp eq ptr %y, null83  br i1 %null_check, label %t, label %f84t:85  ret i1 %null_check86f:87  call void @bar(ptr %x, ptr %y)88  ret i1 %null_check89}90 91; Make sure that an invoke works similarly to a call.92 93declare i32 @esfp(...)94 95define i1 @caller6(ptr %x, ptr %y) personality ptr @esfp{96; CHECK-LABEL: @caller6(97; CHECK-NEXT:    invoke void @bar(ptr [[X:%.*]], ptr nonnull [[Y:%.*]])98; CHECK-NEXT:    to label [[CONT:%.*]] unwind label [[EXC:%.*]]99; CHECK:       cont:100; CHECK-NEXT:    ret i1 false101; CHECK:       exc:102; CHECK-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }103; CHECK-NEXT:    filter [0 x ptr] zeroinitializer104; CHECK-NEXT:    unreachable105;106  invoke void @bar(ptr %x, ptr nonnull %y)107  to label %cont unwind label %exc108 109cont:110  %null_check = icmp eq ptr %y, null111  ret i1 %null_check112 113exc:114  %lp = landingpad { ptr, i32 }115  filter [0 x ptr] zeroinitializer116  unreachable117}118 119declare ptr @returningPtr(ptr returned %p)120 121define i1 @nonnullReturnTest(ptr nonnull %x) {122; CHECK-LABEL: @nonnullReturnTest(123; CHECK-NEXT:    [[X2:%.*]] = call ptr @returningPtr(ptr [[X:%.*]])124; CHECK-NEXT:    ret i1 false125;126  %x2 = call ptr @returningPtr(ptr %x)127  %null_check = icmp eq ptr %x2, null128  ret i1 %null_check129}130 131define i1 @unknownReturnTest(ptr %x) {132; CHECK-LABEL: @unknownReturnTest(133; CHECK-NEXT:    [[X2:%.*]] = call ptr @returningPtr(ptr [[X:%.*]])134; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[X2]], null135; CHECK-NEXT:    ret i1 [[NULL_CHECK]]136;137  %x2 = call ptr @returningPtr(ptr %x)138  %null_check = icmp eq ptr %x2, null139  ret i1 %null_check140}141 142; Make sure that if load/store happened, the pointer is nonnull.143 144define i32 @test_null_after_store(ptr %0) {145; CHECK-LABEL: @test_null_after_store(146; CHECK-NEXT:    store i32 123, ptr [[TMP0:%.*]], align 4147; CHECK-NEXT:    ret i32 2148;149  store i32 123, ptr %0, align 4150  %2 = icmp eq ptr %0, null151  %3 = select i1 %2, i32 1, i32 2152  ret i32 %3153}154 155define i32 @test_null_after_load(ptr %0) {156; CHECK-LABEL: @test_null_after_load(157; CHECK-NEXT:    ret i32 1158;159  %2 = load i32, ptr %0, align 4160  %3 = icmp eq ptr %0, null161  %4 = select i1 %3, i32 %2, i32 1162  ret i32 %4163}164 165; Make sure that different address space does not affect null pointer check.166 167define i32 @test_null_after_store_addrspace(ptr addrspace(1) %0) {168; CHECK-LABEL: @test_null_after_store_addrspace(169; CHECK-NEXT:    store i32 123, ptr addrspace(1) [[TMP0:%.*]], align 4170; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr addrspace(1) [[TMP0]], null171; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP2]], i32 1, i32 2172; CHECK-NEXT:    ret i32 [[TMP3]]173;174  store i32 123, ptr addrspace(1) %0, align 4175  %2 = icmp eq ptr addrspace(1) %0, null176  %3 = select i1 %2, i32 1, i32 2177  ret i32 %3178}179 180define i32 @test_null_after_load_addrspace(ptr addrspace(1) %0) {181; CHECK-LABEL: @test_null_after_load_addrspace(182; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr addrspace(1) [[TMP0:%.*]], align 4183; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq ptr addrspace(1) [[TMP0]], null184; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 1185; CHECK-NEXT:    ret i32 [[TMP4]]186;187  %2 = load i32, ptr addrspace(1) %0, align 4188  %3 = icmp eq ptr addrspace(1) %0, null189  %4 = select i1 %3, i32 %2, i32 1190  ret i32 %4191}192 193; Make sure if store happened after the check, nullptr check is not removed.194 195declare ptr @func(i64)196 197define ptr @test_load_store_after_check(ptr %0) {198; CHECK-LABEL: @test_load_store_after_check(199; CHECK-NEXT:  entry:200; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @func(i64 0)201; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[TMP1]], null202; CHECK-NEXT:    br i1 [[NULL_CHECK]], label [[RETURN:%.*]], label [[IF_END:%.*]]203; CHECK:       if.end:204; CHECK-NEXT:    store i8 7, ptr [[TMP1]], align 1205; CHECK-NEXT:    br label [[RETURN]]206; CHECK:       return:207; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi ptr [ [[TMP1]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ]208; CHECK-NEXT:    ret ptr [[RETVAL_0]]209;210entry:211  %1 = call ptr @func(i64 0)212  %null_check = icmp eq ptr %1, null213  br i1 %null_check, label %return, label %if.end214 215if.end:216  store i8 7, ptr %1217  br label %return218 219return:220  %retval.0 = phi ptr [ %1, %if.end ], [ null, %entry ]221  ret ptr %retval.0222}223 224define i1 @test_known_nonnull_at_callsite(ptr %src) {225; CHECK-LABEL: @test_known_nonnull_at_callsite(226; CHECK-NEXT:  entry:227; CHECK-NEXT:    call void @callee(ptr noundef nonnull [[SRC:%.*]])228; CHECK-NEXT:    ret i1 false229;230entry:231  call void @callee(ptr noundef nonnull %src)232  %nonnull = icmp eq ptr %src, null233  ret i1 %nonnull234}235 236define i1 @test_known_nonnull_mixed(ptr %src) {237; CHECK-LABEL: @test_known_nonnull_mixed(238; CHECK-NEXT:  entry:239; CHECK-NEXT:    call void @callee2(ptr nonnull [[SRC:%.*]])240; CHECK-NEXT:    ret i1 false241;242entry:243  call void @callee2(ptr nonnull %src)244  %nonnull = icmp eq ptr %src, null245  ret i1 %nonnull246}247 248define i1 @test_known_nonnull_at_callsite_dereferenceable(ptr %src) {249; CHECK-LABEL: @test_known_nonnull_at_callsite_dereferenceable(250; CHECK-NEXT:  entry:251; CHECK-NEXT:    call void @callee(ptr dereferenceable(1) [[SRC:%.*]])252; CHECK-NEXT:    ret i1 false253;254entry:255  call void @callee(ptr dereferenceable(1) %src)256  %nonnull = icmp eq ptr %src, null257  ret i1 %nonnull258}259 260; Negative tests261 262define i1 @test_known_nonnull_at_callsite_without_noundef(ptr %src) {263; CHECK-LABEL: @test_known_nonnull_at_callsite_without_noundef(264; CHECK-NEXT:  entry:265; CHECK-NEXT:    call void @callee(ptr nonnull [[SRC:%.*]])266; CHECK-NEXT:    [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null267; CHECK-NEXT:    ret i1 [[NONNULL]]268;269entry:270  call void @callee(ptr nonnull %src)271  %nonnull = icmp eq ptr %src, null272  ret i1 %nonnull273}274 275define i1 @test_known_nonnull_at_callsite_dereferenceable_null_is_defined(ptr %src) null_pointer_is_valid {276; CHECK-LABEL: @test_known_nonnull_at_callsite_dereferenceable_null_is_defined(277; CHECK-NEXT:  entry:278; CHECK-NEXT:    call void @callee(ptr dereferenceable(1) [[SRC:%.*]])279; CHECK-NEXT:    [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null280; CHECK-NEXT:    ret i1 [[NONNULL]]281;282entry:283  call void @callee(ptr dereferenceable(1) %src)284  %nonnull = icmp eq ptr %src, null285  ret i1 %nonnull286}287 288declare void @callee(ptr)289declare void @callee2(ptr noundef)290