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