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