1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -S -passes=sccp < %s | FileCheck %s --check-prefixes=CHECK,SCCP 3; RUN: opt -S -passes=ipsccp < %s | FileCheck %s --check-prefixes=CHECK,IPSCCP 4 5declare ptr @get() 6 7define i1 @test_no_attr(ptr %p) { 8; CHECK-LABEL: define i1 @test_no_attr( 9; CHECK-SAME: ptr [[P:%.*]]) { 10; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[P]], null 11; CHECK-NEXT: ret i1 [[CMP]] 12; 13 %cmp = icmp ne ptr %p, null 14 ret i1 %cmp 15} 16 17define i1 @test_nonnull(ptr nonnull %p) { 18; CHECK-LABEL: define i1 @test_nonnull( 19; CHECK-SAME: ptr nonnull [[P:%.*]]) { 20; CHECK-NEXT: ret i1 true 21; 22 %cmp = icmp ne ptr %p, null 23 ret i1 %cmp 24} 25 26define i1 @test_nonnull_eq(ptr nonnull %p) { 27; CHECK-LABEL: define i1 @test_nonnull_eq( 28; CHECK-SAME: ptr nonnull [[P:%.*]]) { 29; CHECK-NEXT: ret i1 false 30; 31 %cmp = icmp eq ptr %p, null 32 ret i1 %cmp 33} 34 35define i1 @test_dereferenceable(ptr dereferenceable(4) %p) { 36; CHECK-LABEL: define i1 @test_dereferenceable( 37; CHECK-SAME: ptr dereferenceable(4) [[P:%.*]]) { 38; CHECK-NEXT: ret i1 true 39; 40 %cmp = icmp ne ptr %p, null 41 ret i1 %cmp 42} 43 44define i1 @test_alloca() { 45; CHECK-LABEL: define i1 @test_alloca() { 46; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 47; CHECK-NEXT: ret i1 true 48; 49 %a = alloca i32 50 %cmp = icmp ne ptr %a, null 51 ret i1 %cmp 52} 53 54define i1 @test_alloca_addrspace() { 55; CHECK-LABEL: define i1 @test_alloca_addrspace() { 56; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4, addrspace(1) 57; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr addrspace(1) [[A]], null 58; CHECK-NEXT: ret i1 [[CMP]] 59; 60 %a = alloca i32, addrspace(1) 61 %cmp = icmp ne ptr addrspace(1) %a, null 62 ret i1 %cmp 63} 64 65define i1 @test_alloca_null_pointer_valid() null_pointer_is_valid { 66; CHECK-LABEL: define i1 @test_alloca_null_pointer_valid( 67; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { 68; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 69; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[A]], null 70; CHECK-NEXT: ret i1 [[CMP]] 71; 72 %a = alloca i32 73 %cmp = icmp ne ptr %a, null 74 ret i1 %cmp 75} 76 77define i1 @test_load_nonnull(ptr %p) { 78; CHECK-LABEL: define i1 @test_load_nonnull( 79; CHECK-SAME: ptr [[P:%.*]]) { 80; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0:![0-9]+]] 81; CHECK-NEXT: ret i1 true 82; 83 %p2 = load ptr, ptr %p, !nonnull !{} 84 %cmp = icmp ne ptr %p2, null 85 ret i1 %cmp 86} 87 88define i1 @test_call_nonnull() { 89; CHECK-LABEL: define i1 @test_call_nonnull() { 90; CHECK-NEXT: [[P:%.*]] = call nonnull ptr @get() 91; CHECK-NEXT: ret i1 true 92; 93 %p = call nonnull ptr @get() 94 %cmp = icmp ne ptr %p, null 95 ret i1 %cmp 96} 97 98define i1 @test_call_dereferenceable() { 99; CHECK-LABEL: define i1 @test_call_dereferenceable() { 100; CHECK-NEXT: [[P:%.*]] = call dereferenceable(4) ptr @get() 101; CHECK-NEXT: ret i1 true 102; 103 %p = call dereferenceable(4) ptr @get() 104 %cmp = icmp ne ptr %p, null 105 ret i1 %cmp 106} 107 108define i1 @test_gep_no_flags(ptr nonnull %p, i64 %x) { 109; CHECK-LABEL: define i1 @test_gep_no_flags( 110; CHECK-SAME: ptr nonnull [[P:%.*]], i64 [[X:%.*]]) { 111; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P]], i64 [[X]] 112; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[GEP]], null 113; CHECK-NEXT: ret i1 [[CMP]] 114; 115 %gep = getelementptr i8, ptr %p, i64 %x 116 %cmp = icmp ne ptr %gep, null 117 ret i1 %cmp 118} 119 120define i1 @test_gep_nuw(ptr nonnull %p, i64 %x) { 121; CHECK-LABEL: define i1 @test_gep_nuw( 122; CHECK-SAME: ptr nonnull [[P:%.*]], i64 [[X:%.*]]) { 123; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[X]] 124; CHECK-NEXT: ret i1 true 125; 126 %gep = getelementptr nuw i8, ptr %p, i64 %x 127 %cmp = icmp ne ptr %gep, null 128 ret i1 %cmp 129} 130 131define i1 @test_gep_inbounds(ptr nonnull %p, i64 %x) { 132; CHECK-LABEL: define i1 @test_gep_inbounds( 133; CHECK-SAME: ptr nonnull [[P:%.*]], i64 [[X:%.*]]) { 134; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[X]] 135; CHECK-NEXT: ret i1 true 136; 137 %gep = getelementptr inbounds i8, ptr %p, i64 %x 138 %cmp = icmp ne ptr %gep, null 139 ret i1 %cmp 140} 141 142define i1 @test_gep_inbounds_null_pointer_valid(ptr nonnull %p, i64 %x) null_pointer_is_valid { 143; CHECK-LABEL: define i1 @test_gep_inbounds_null_pointer_valid( 144; CHECK-SAME: ptr nonnull [[P:%.*]], i64 [[X:%.*]]) #[[ATTR0]] { 145; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[X]] 146; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[GEP]], null 147; CHECK-NEXT: ret i1 [[CMP]] 148; 149 %gep = getelementptr inbounds i8, ptr %p, i64 %x 150 %cmp = icmp ne ptr %gep, null 151 ret i1 %cmp 152} 153 154define i1 @test_select(i1 %c, ptr nonnull %p, i64 %x) { 155; CHECK-LABEL: define i1 @test_select( 156; CHECK-SAME: i1 [[C:%.*]], ptr nonnull [[P:%.*]], i64 [[X:%.*]]) { 157; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[X]] 158; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], ptr [[P]], ptr [[GEP]] 159; CHECK-NEXT: ret i1 true 160; 161 %gep = getelementptr nuw i8, ptr %p, i64 %x 162 %sel = select i1 %c, ptr %p, ptr %gep 163 %cmp = icmp ne ptr %sel, null 164 ret i1 %cmp 165} 166 167define i1 @test_select_not_nuw(i1 %c, ptr nonnull %p, i64 %x) { 168; CHECK-LABEL: define i1 @test_select_not_nuw( 169; CHECK-SAME: i1 [[C:%.*]], ptr nonnull [[P:%.*]], i64 [[X:%.*]]) { 170; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P]], i64 [[X]] 171; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], ptr [[P]], ptr [[GEP]] 172; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[SEL]], null 173; CHECK-NEXT: ret i1 [[CMP]] 174; 175 %gep = getelementptr i8, ptr %p, i64 %x 176 %sel = select i1 %c, ptr %p, ptr %gep 177 %cmp = icmp ne ptr %sel, null 178 ret i1 %cmp 179} 180 181define i1 @test_phi(i1 %c, ptr nonnull %p, i64 %x) { 182; CHECK-LABEL: define i1 @test_phi( 183; CHECK-SAME: i1 [[C:%.*]], ptr nonnull [[P:%.*]], i64 [[X:%.*]]) { 184; CHECK-NEXT: [[ENTRY:.*]]: 185; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[JOIN:.*]] 186; CHECK: [[IF]]: 187; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[X]] 188; CHECK-NEXT: br label %[[JOIN]] 189; CHECK: [[JOIN]]: 190; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[P]], %[[ENTRY]] ], [ [[GEP]], %[[IF]] ] 191; CHECK-NEXT: ret i1 true 192; 193entry: 194 br i1 %c, label %if, label %join 195 196if: 197 %gep = getelementptr nuw i8, ptr %p, i64 %x 198 br label %join 199 200join: 201 %phi = phi ptr [ %p, %entry ], [ %gep, %if ] 202 %cmp = icmp ne ptr %phi, null 203 ret i1 %cmp 204} 205 206define internal i1 @ip_test_nonnull_callee(ptr nonnull %p) { 207; SCCP-LABEL: define internal i1 @ip_test_nonnull_callee( 208; SCCP-SAME: ptr nonnull [[P:%.*]]) { 209; SCCP-NEXT: ret i1 true 210; 211; IPSCCP-LABEL: define internal i1 @ip_test_nonnull_callee( 212; IPSCCP-SAME: ptr nonnull [[P:%.*]]) { 213; IPSCCP-NEXT: ret i1 poison 214; 215 %cmp = icmp ne ptr %p, null 216 ret i1 %cmp 217} 218 219define i1 @ip_test_nonnull_caller(ptr %p) { 220; SCCP-LABEL: define i1 @ip_test_nonnull_caller( 221; SCCP-SAME: ptr [[P:%.*]]) { 222; SCCP-NEXT: [[RES:%.*]] = call i1 @ip_test_nonnull_callee(ptr [[P]]) 223; SCCP-NEXT: ret i1 [[RES]] 224; 225; IPSCCP-LABEL: define i1 @ip_test_nonnull_caller( 226; IPSCCP-SAME: ptr [[P:%.*]]) { 227; IPSCCP-NEXT: [[RES:%.*]] = call i1 @ip_test_nonnull_callee(ptr [[P]]) 228; IPSCCP-NEXT: ret i1 true 229; 230 %res = call i1 @ip_test_nonnull_callee(ptr %p) 231 ret i1 %res 232} 233 234define ptr @ret_nonnull_pointer(ptr nonnull %p) { 235; CHECK-LABEL: define nonnull ptr @ret_nonnull_pointer( 236; CHECK-SAME: ptr nonnull [[P:%.*]]) { 237; CHECK-NEXT: ret ptr [[P]] 238; 239 ret ptr %p 240} 241 242define ptr @ret_maybe_null_pointer(ptr %p) { 243; CHECK-LABEL: define ptr @ret_maybe_null_pointer( 244; CHECK-SAME: ptr [[P:%.*]]) { 245; CHECK-NEXT: ret ptr [[P]] 246; 247 ret ptr %p 248} 249 250define internal void @ip_nonnull_arg_callee(ptr %p) { 251; SCCP-LABEL: define internal void @ip_nonnull_arg_callee( 252; SCCP-SAME: ptr [[P:%.*]]) { 253; SCCP-NEXT: ret void 254; 255; IPSCCP-LABEL: define internal void @ip_nonnull_arg_callee( 256; IPSCCP-SAME: ptr nonnull [[P:%.*]]) { 257; IPSCCP-NEXT: ret void 258; 259 ret void 260} 261 262define internal void @ip_not_nonnull_arg_callee(ptr %p) { 263; CHECK-LABEL: define internal void @ip_not_nonnull_arg_callee( 264; CHECK-SAME: ptr [[P:%.*]]) { 265; CHECK-NEXT: ret void 266; 267 ret void 268} 269 270define void @ip_nonnull_arg_caller(ptr nonnull %p) { 271; CHECK-LABEL: define void @ip_nonnull_arg_caller( 272; CHECK-SAME: ptr nonnull [[P:%.*]]) { 273; CHECK-NEXT: call void @ip_nonnull_arg_callee(ptr [[P]]) 274; CHECK-NEXT: call void @ip_not_nonnull_arg_callee(ptr [[P]]) 275; CHECK-NEXT: call void @ip_not_nonnull_arg_callee(ptr null) 276; CHECK-NEXT: ret void 277; 278 call void @ip_nonnull_arg_callee(ptr %p) 279 call void @ip_not_nonnull_arg_callee(ptr %p) 280 call void @ip_not_nonnull_arg_callee(ptr null) 281 ret void 282} 283 284;. 285; SCCP: [[META0]] = !{} 286;. 287; IPSCCP: [[META0]] = !{} 288;. 289