1; RUN: llc -mtriple=i686 -O0 < %s | FileCheck %s 2; RUN: llc -mtriple=x86_64 -O0 < %s | FileCheck %s 3 4; CHECK-LABEL: in_bounds: 5; CHECK-NOT: __stack_chk_guard 6define i32 @in_bounds() #0 { 7 %var = alloca i32, align 4 8 store i32 0, i32* %var, align 4 9 %gep = getelementptr inbounds i32, i32* %var, i32 0 10 %ret = load i32, i32* %gep, align 4 11 ret i32 %ret 12} 13 14; CHECK-LABEL: constant_out_of_bounds: 15; CHECK: __stack_chk_guard 16define i32 @constant_out_of_bounds() #0 { 17 %var = alloca i32, align 4 18 store i32 0, i32* %var, align 4 19 %gep = getelementptr inbounds i32, i32* %var, i32 1 20 %ret = load i32, i32* %gep, align 4 21 ret i32 %ret 22} 23 24; CHECK-LABEL: nonconstant_out_of_bounds: 25; CHECK: __stack_chk_guard 26define i32 @nonconstant_out_of_bounds(i32 %n) #0 { 27 %var = alloca i32, align 4 28 store i32 0, i32* %var, align 4 29 %gep = getelementptr inbounds i32, i32* %var, i32 %n 30 %ret = load i32, i32* %gep, align 4 31 ret i32 %ret 32} 33 34; CHECK-LABEL: phi_before_gep_in_bounds: 35; CHECK-NOT: __stack_chk_guard 36define i32 @phi_before_gep_in_bounds(i32 %k) #0 { 37entry: 38 %var1 = alloca i32, align 4 39 %var2 = alloca i32, align 4 40 store i32 0, i32* %var1, align 4 41 store i32 0, i32* %var2, align 4 42 %cmp = icmp ne i32 %k, 0 43 br i1 %cmp, label %if, label %then 44 45if: 46 br label %then 47 48then: 49 %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ] 50 %gep = getelementptr inbounds i32, i32* %ptr, i32 0 51 %ret = load i32, i32* %gep, align 4 52 ret i32 %ret 53} 54 55; CHECK-LABEL: phi_before_gep_constant_out_of_bounds: 56; CHECK: __stack_chk_guard 57define i32 @phi_before_gep_constant_out_of_bounds(i32 %k) #0 { 58entry: 59 %var1 = alloca i32, align 4 60 %var2 = alloca i32, align 4 61 store i32 0, i32* %var1, align 4 62 store i32 0, i32* %var2, align 4 63 %cmp = icmp ne i32 %k, 0 64 br i1 %cmp, label %if, label %then 65 66if: 67 br label %then 68 69then: 70 %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ] 71 %gep = getelementptr inbounds i32, i32* %ptr, i32 1 72 %ret = load i32, i32* %gep, align 4 73 ret i32 %ret 74} 75 76; CHECK-LABEL: phi_before_gep_nonconstant_out_of_bounds: 77; CHECK: __stack_chk_guard 78define i32 @phi_before_gep_nonconstant_out_of_bounds(i32 %k, i32 %n) #0 { 79entry: 80 %var1 = alloca i32, align 4 81 %var2 = alloca i32, align 4 82 store i32 0, i32* %var1, align 4 83 store i32 0, i32* %var2, align 4 84 %cmp = icmp ne i32 %k, 0 85 br i1 %cmp, label %if, label %then 86 87if: 88 br label %then 89 90then: 91 %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ] 92 %gep = getelementptr inbounds i32, i32* %ptr, i32 %n 93 %ret = load i32, i32* %gep, align 4 94 ret i32 %ret 95} 96 97; CHECK-LABEL: phi_after_gep_in_bounds: 98; CHECK-NOT: __stack_chk_guard 99define i32 @phi_after_gep_in_bounds(i32 %k) #0 { 100entry: 101 %var1 = alloca i32, align 4 102 %var2 = alloca i32, align 4 103 store i32 0, i32* %var1, align 4 104 store i32 0, i32* %var2, align 4 105 %cmp = icmp ne i32 %k, 0 106 br i1 %cmp, label %if, label %else 107 108if: 109 %gep1 = getelementptr inbounds i32, i32* %var1, i32 0 110 br label %then 111 112else: 113 %gep2 = getelementptr inbounds i32, i32* %var2, i32 0 114 br label %then 115 116then: 117 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ] 118 %ret = load i32, i32* %ptr, align 4 119 ret i32 %ret 120} 121 122; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_a: 123; CHECK: __stack_chk_guard 124define i32 @phi_after_gep_constant_out_of_bounds_a(i32 %k) #0 { 125entry: 126 %var1 = alloca i32, align 4 127 %var2 = alloca i32, align 4 128 store i32 0, i32* %var1, align 4 129 store i32 0, i32* %var2, align 4 130 %cmp = icmp ne i32 %k, 0 131 br i1 %cmp, label %if, label %else 132 133if: 134 %gep1 = getelementptr inbounds i32, i32* %var1, i32 0 135 br label %then 136 137else: 138 %gep2 = getelementptr inbounds i32, i32* %var2, i32 1 139 br label %then 140 141then: 142 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ] 143 %ret = load i32, i32* %ptr, align 4 144 ret i32 %ret 145} 146 147; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_b: 148; CHECK: __stack_chk_guard 149define i32 @phi_after_gep_constant_out_of_bounds_b(i32 %k) #0 { 150entry: 151 %var1 = alloca i32, align 4 152 %var2 = alloca i32, align 4 153 store i32 0, i32* %var1, align 4 154 store i32 0, i32* %var2, align 4 155 %cmp = icmp ne i32 %k, 0 156 br i1 %cmp, label %if, label %else 157 158if: 159 %gep1 = getelementptr inbounds i32, i32* %var1, i32 1 160 br label %then 161 162else: 163 %gep2 = getelementptr inbounds i32, i32* %var2, i32 0 164 br label %then 165 166then: 167 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ] 168 %ret = load i32, i32* %ptr, align 4 169 ret i32 %ret 170} 171 172; CHECK-LABEL: phi_different_types_a: 173; CHECK: __stack_chk_guard 174define i64 @phi_different_types_a(i32 %k) #0 { 175entry: 176 %var1 = alloca i64, align 4 177 %var2 = alloca i32, align 4 178 store i64 0, i64* %var1, align 4 179 store i32 0, i32* %var2, align 4 180 %cmp = icmp ne i32 %k, 0 181 br i1 %cmp, label %if, label %then 182 183if: 184 %bitcast = bitcast i32* %var2 to i64* 185 br label %then 186 187then: 188 %ptr = phi i64* [ %var1, %entry ], [ %bitcast, %if ] 189 %ret = load i64, i64* %ptr, align 4 190 ret i64 %ret 191} 192 193; CHECK-LABEL: phi_different_types_b: 194; CHECK: __stack_chk_guard 195define i64 @phi_different_types_b(i32 %k) #0 { 196entry: 197 %var1 = alloca i32, align 4 198 %var2 = alloca i64, align 4 199 store i32 0, i32* %var1, align 4 200 store i64 0, i64* %var2, align 4 201 %cmp = icmp ne i32 %k, 0 202 br i1 %cmp, label %if, label %then 203 204if: 205 %bitcast = bitcast i32* %var1 to i64* 206 br label %then 207 208then: 209 %ptr = phi i64* [ %var2, %entry ], [ %bitcast, %if ] 210 %ret = load i64, i64* %ptr, align 4 211 ret i64 %ret 212} 213 214; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_a: 215; CHECK: __stack_chk_guard 216define i32 @phi_after_gep_nonconstant_out_of_bounds_a(i32 %k, i32 %n) #0 { 217entry: 218 %var1 = alloca i32, align 4 219 %var2 = alloca i32, align 4 220 store i32 0, i32* %var1, align 4 221 store i32 0, i32* %var2, align 4 222 %cmp = icmp ne i32 %k, 0 223 br i1 %cmp, label %if, label %else 224 225if: 226 %gep1 = getelementptr inbounds i32, i32* %var1, i32 0 227 br label %then 228 229else: 230 %gep2 = getelementptr inbounds i32, i32* %var2, i32 %n 231 br label %then 232 233then: 234 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ] 235 %ret = load i32, i32* %ptr, align 4 236 ret i32 %ret 237} 238 239; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_b: 240; CHECK: __stack_chk_guard 241define i32 @phi_after_gep_nonconstant_out_of_bounds_b(i32 %k, i32 %n) #0 { 242entry: 243 %var1 = alloca i32, align 4 244 %var2 = alloca i32, align 4 245 store i32 0, i32* %var1, align 4 246 store i32 0, i32* %var2, align 4 247 %cmp = icmp ne i32 %k, 0 248 br i1 %cmp, label %if, label %else 249 250if: 251 %gep1 = getelementptr inbounds i32, i32* %var1, i32 %n 252 br label %then 253 254else: 255 %gep2 = getelementptr inbounds i32, i32* %var2, i32 0 256 br label %then 257 258then: 259 %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ] 260 %ret = load i32, i32* %ptr, align 4 261 ret i32 %ret 262} 263 264%struct.outer = type { %struct.inner, %struct.inner } 265%struct.inner = type { i32, i32 } 266 267; CHECK-LABEL: struct_in_bounds: 268; CHECK-NOT: __stack_chk_guard 269define void @struct_in_bounds() #0 { 270 %var = alloca %struct.outer, align 4 271 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 1 272 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 1 273 store i32 0, i32* %innergep, align 4 274 ret void 275} 276 277; CHECK-LABEL: struct_constant_out_of_bounds_a: 278; CHECK: __stack_chk_guard 279define void @struct_constant_out_of_bounds_a() #0 { 280 %var = alloca %struct.outer, align 4 281 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 1, i32 0 282 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 0 283 store i32 0, i32* %innergep, align 4 284 ret void 285} 286 287; CHECK-LABEL: struct_constant_out_of_bounds_b: 288; Here the offset is out-of-bounds of the addressed struct.inner member, but 289; still within bounds of the outer struct so no stack guard is needed. 290; CHECK-NOT: __stack_chk_guard 291define void @struct_constant_out_of_bounds_b() #0 { 292 %var = alloca %struct.outer, align 4 293 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 0 294 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 1, i32 0 295 store i32 0, i32* %innergep, align 4 296 ret void 297} 298 299; CHECK-LABEL: struct_constant_out_of_bounds_c: 300; Here we are out-of-bounds of both the inner and outer struct. 301; CHECK: __stack_chk_guard 302define void @struct_constant_out_of_bounds_c() #0 { 303 %var = alloca %struct.outer, align 4 304 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 1 305 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 1, i32 0 306 store i32 0, i32* %innergep, align 4 307 ret void 308} 309 310; CHECK-LABEL: struct_nonconstant_out_of_bounds_a: 311; CHECK: __stack_chk_guard 312define void @struct_nonconstant_out_of_bounds_a(i32 %n) #0 { 313 %var = alloca %struct.outer, align 4 314 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 %n, i32 0 315 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 0 316 store i32 0, i32* %innergep, align 4 317 ret void 318} 319 320; CHECK-LABEL: struct_nonconstant_out_of_bounds_b: 321; CHECK: __stack_chk_guard 322define void @struct_nonconstant_out_of_bounds_b(i32 %n) #0 { 323 %var = alloca %struct.outer, align 4 324 %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 0 325 %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 %n, i32 0 326 store i32 0, i32* %innergep, align 4 327 ret void 328} 329 330; CHECK-LABEL: bitcast_smaller_load 331; CHECK-NOT: __stack_chk_guard 332define i32 @bitcast_smaller_load() #0 { 333 %var = alloca i64, align 4 334 store i64 0, i64* %var, align 4 335 %bitcast = bitcast i64* %var to i32* 336 %ret = load i32, i32* %bitcast, align 4 337 ret i32 %ret 338} 339 340; CHECK-LABEL: bitcast_same_size_load 341; CHECK-NOT: __stack_chk_guard 342define i32 @bitcast_same_size_load() #0 { 343 %var = alloca i64, align 4 344 store i64 0, i64* %var, align 4 345 %bitcast = bitcast i64* %var to %struct.inner* 346 %gep = getelementptr inbounds %struct.inner, %struct.inner* %bitcast, i32 0, i32 1 347 %ret = load i32, i32* %gep, align 4 348 ret i32 %ret 349} 350 351; CHECK-LABEL: bitcast_larger_load 352; CHECK: __stack_chk_guard 353define i64 @bitcast_larger_load() #0 { 354 %var = alloca i32, align 4 355 store i32 0, i32* %var, align 4 356 %bitcast = bitcast i32* %var to i64* 357 %ret = load i64, i64* %bitcast, align 4 358 ret i64 %ret 359} 360 361; CHECK-LABEL: bitcast_larger_store 362; CHECK: __stack_chk_guard 363define i32 @bitcast_larger_store() #0 { 364 %var = alloca i32, align 4 365 %bitcast = bitcast i32* %var to i64* 366 store i64 0, i64* %bitcast, align 4 367 %ret = load i32, i32* %var, align 4 368 ret i32 %ret 369} 370 371; CHECK-LABEL: bitcast_larger_cmpxchg 372; CHECK: __stack_chk_guard 373define i64 @bitcast_larger_cmpxchg(i64 %desired, i64 %new) #0 { 374 %var = alloca i32, align 4 375 %bitcast = bitcast i32* %var to i64* 376 %pair = cmpxchg i64* %bitcast, i64 %desired, i64 %new seq_cst monotonic 377 %ret = extractvalue { i64, i1 } %pair, 0 378 ret i64 %ret 379} 380 381; CHECK-LABEL: bitcast_larger_atomic_rmw 382; CHECK: __stack_chk_guard 383define i64 @bitcast_larger_atomic_rmw() #0 { 384 %var = alloca i32, align 4 385 %bitcast = bitcast i32* %var to i64* 386 %ret = atomicrmw add i64* %bitcast, i64 1 monotonic 387 ret i64 %ret 388} 389 390%struct.packed = type <{ i16, i32 }> 391 392; CHECK-LABEL: bitcast_overlap 393; CHECK: __stack_chk_guard 394define i32 @bitcast_overlap() #0 { 395 %var = alloca i32, align 4 396 %bitcast = bitcast i32* %var to %struct.packed* 397 %gep = getelementptr inbounds %struct.packed, %struct.packed* %bitcast, i32 0, i32 1 398 %ret = load i32, i32* %gep, align 2 399 ret i32 %ret 400} 401 402%struct.multi_dimensional = type { [10 x [10 x i32]], i32 } 403 404; CHECK-LABEL: multi_dimensional_array 405; CHECK: __stack_chk_guard 406define i32 @multi_dimensional_array() #0 { 407 %var = alloca %struct.multi_dimensional, align 4 408 %gep1 = getelementptr inbounds %struct.multi_dimensional, %struct.multi_dimensional* %var, i32 0, i32 0 409 %gep2 = getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* %gep1, i32 0, i32 10 410 %gep3 = getelementptr inbounds [10 x i32], [10 x i32]* %gep2, i32 0, i32 5 411 %ret = load i32, i32* %gep3, align 4 412 ret i32 %ret 413} 414 415attributes #0 = { sspstrong } 416