1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --disable --function-signature --scrub-attributes 2; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_MODULE 3; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_CGSCC 4; RUN: opt -passes=attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_MODULE 5; RUN: opt -passes=attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_CGSCC 6 7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 8 9; Test cases specifically designed for "align" attribute. 10; We use FIXME's to indicate problems and missing attributes. 11 12 13; TEST 1 14; ATTRIBUTOR: define align 8 i32* @test1(i32* nofree readnone returned align 8 "no-capture-maybe-returned" %0) 15define i32* @test1(i32* align 8 %0) #0 { 16 ret i32* %0 17} 18 19; TEST 2 20; ATTRIBUTOR: define i32* @test2(i32* nofree readnone returned "no-capture-maybe-returned" %0) 21define i32* @test2(i32* %0) #0 { 22 ret i32* %0 23} 24 25; TEST 3 26; ATTRIBUTOR: define align 4 i32* @test3(i32* nofree readnone align 8 "no-capture-maybe-returned" %0, i32* nofree readnone align 4 "no-capture-maybe-returned" %1, i1 %2) 27define i32* @test3(i32* align 8 %0, i32* align 4 %1, i1 %2) #0 { 28 %ret = select i1 %2, i32* %0, i32* %1 29 ret i32* %ret 30} 31 32; TEST 4 33; ATTRIBUTOR: define align 32 i32* @test4(i32* nofree readnone align 32 "no-capture-maybe-returned" %0, i32* nofree readnone align 32 "no-capture-maybe-returned" %1, i1 %2) 34define i32* @test4(i32* align 32 %0, i32* align 32 %1, i1 %2) #0 { 35 %ret = select i1 %2, i32* %0, i32* %1 36 ret i32* %ret 37} 38 39; TEST 5 40declare i32* @unknown() 41declare align 8 i32* @align8() 42 43 44; ATTRIBUTOR: define align 8 i32* @test5_1() 45define i32* @test5_1() { 46 %ret = tail call align 8 i32* @unknown() 47 ret i32* %ret 48} 49 50; ATTRIBUTOR: define align 8 i32* @test5_2() 51define i32* @test5_2() { 52 %ret = tail call i32* @align8() 53 ret i32* %ret 54} 55 56; TEST 6 57; SCC 58; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @test6_1() 59define i32* @test6_1() #0 { 60 %ret = tail call i32* @test6_2() 61 ret i32* %ret 62} 63 64; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @test6_2() 65define i32* @test6_2() #0 { 66 %ret = tail call i32* @test6_1() 67 ret i32* %ret 68} 69 70 71; char a1 __attribute__((aligned(8))); 72; char a2 __attribute__((aligned(16))); 73; 74; char* f1(char* a ){ 75; return a?a:f2(&a1); 76; } 77; char* f2(char* a){ 78; return a?f1(a):f3(&a2); 79; } 80; 81; char* f3(char* a){ 82; return a?&a1: f1(&a2); 83; } 84 85@a1 = common global i8 0, align 8 86@a2 = common global i8 0, align 16 87 88; Function Attrs: nounwind readnone ssp uwtable 89define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 { 90 %2 = icmp eq i8* %0, null 91 br i1 %2, label %3, label %5 92 93; <label>:3: ; preds = %1 94 %4 = tail call i8* @f2(i8* nonnull @a1) 95 %l = load i8, i8* %4 96 br label %5 97 98; <label>:5: ; preds = %1, %3 99 %6 = phi i8* [ %4, %3 ], [ %0, %1 ] 100 ret i8* %6 101} 102 103; Function Attrs: nounwind readnone ssp uwtable 104define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 { 105 %2 = icmp eq i8* %0, null 106 br i1 %2, label %5, label %3 107 108; <label>:3: ; preds = %1 109 110 %4 = tail call i8* @f1(i8* nonnull %0) 111 br label %7 112 113; <label>:5: ; preds = %1 114 %6 = tail call i8* @f3(i8* nonnull @a2) 115 br label %7 116 117; <label>:7: ; preds = %5, %3 118 %8 = phi i8* [ %4, %3 ], [ %6, %5 ] 119 ret i8* %8 120} 121 122; Function Attrs: nounwind readnone ssp uwtable 123define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 { 124 %2 = icmp eq i8* %0, null 125 br i1 %2, label %3, label %5 126 127; <label>:3: ; preds = %1 128 %4 = tail call i8* @f1(i8* nonnull @a2) 129 br label %5 130 131; <label>:5: ; preds = %1, %3 132 %6 = phi i8* [ %4, %3 ], [ @a1, %1 ] 133 ret i8* %6 134} 135 136; UTC_ARGS: --enable 137 138; TEST 7 139; Better than IR information 140define align 4 i8* @test7() #0 { 141; ATTRIBUTOR_MODULE-LABEL: define {{[^@]+}}@test7() 142; ATTRIBUTOR_MODULE-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) 143; ATTRIBUTOR_MODULE-NEXT: ret i8* [[C]] 144; 145; ATTRIBUTOR_CGSCC-LABEL: define {{[^@]+}}@test7() 146; ATTRIBUTOR_CGSCC-NEXT: [[C:%.*]] = tail call nonnull align 8 dereferenceable(1) i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) 147; ATTRIBUTOR_CGSCC-NEXT: ret i8* [[C]] 148; 149 %c = tail call i8* @f1(i8* align 8 dereferenceable(1) @a1) 150 ret i8* %c 151} 152 153; TEST 7b 154; Function Attrs: nounwind readnone ssp uwtable 155define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { 156; ATTRIBUTOR_MODULE-LABEL: define {{[^@]+}}@f1b 157; ATTRIBUTOR_MODULE-SAME: (i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr 158; ATTRIBUTOR_MODULE-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null 159; ATTRIBUTOR_MODULE-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] 160; ATTRIBUTOR_MODULE: 3: 161; ATTRIBUTOR_MODULE-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b() 162; ATTRIBUTOR_MODULE-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8 163; ATTRIBUTOR_MODULE-NEXT: store i8 [[L]], i8* @a1, align 8 164; ATTRIBUTOR_MODULE-NEXT: br label [[TMP5]] 165; ATTRIBUTOR_MODULE: 5: 166; ATTRIBUTOR_MODULE-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] 167; ATTRIBUTOR_MODULE-NEXT: ret i8* [[TMP6]] 168; 169; ATTRIBUTOR_CGSCC-LABEL: define {{[^@]+}}@f1b 170; ATTRIBUTOR_CGSCC-SAME: (i8* nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr 171; ATTRIBUTOR_CGSCC-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null 172; ATTRIBUTOR_CGSCC-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] 173; ATTRIBUTOR_CGSCC: 3: 174; ATTRIBUTOR_CGSCC-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b() 175; ATTRIBUTOR_CGSCC-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8 176; ATTRIBUTOR_CGSCC-NEXT: store i8 [[L]], i8* @a1, align 8 177; ATTRIBUTOR_CGSCC-NEXT: br label [[TMP5]] 178; ATTRIBUTOR_CGSCC: 5: 179; ATTRIBUTOR_CGSCC-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] 180; ATTRIBUTOR_CGSCC-NEXT: ret i8* [[TMP6]] 181; 182 %2 = icmp eq i8* %0, null 183 br i1 %2, label %3, label %5 184 185; <label>:3: ; preds = %1 186 %4 = tail call i8* @f2b(i8* nonnull @a1) 187 %l = load i8, i8* %4 188 store i8 %l, i8* @a1 189 br label %5 190 191; <label>:5: ; preds = %1, %3 192 %6 = phi i8* [ %4, %3 ], [ %0, %1 ] 193 ret i8* %6 194} 195 196; Function Attrs: nounwind readnone ssp uwtable 197define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 { 198; 199; ATTRIBUTOR-LABEL: define {{[^@]+}}@f2b() local_unnamed_addr 200; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null 201; ATTRIBUTOR-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]] 202; ATTRIBUTOR: 2: 203; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) 204; ATTRIBUTOR-NEXT: br label [[TMP6:%.*]] 205; ATTRIBUTOR: 4: 206; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = tail call i8* @f3b() 207; ATTRIBUTOR-NEXT: br label [[TMP6]] 208; ATTRIBUTOR: 6: 209; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ] 210; ATTRIBUTOR-NEXT: ret i8* [[TMP7]] 211; 212 %2 = icmp eq i8* %0, null 213 br i1 %2, label %5, label %3 214 215; <label>:3: ; preds = %1 216 217 %4 = tail call i8* @f1b(i8* nonnull %0) 218 br label %7 219 220; <label>:5: ; preds = %1 221 %6 = tail call i8* @f3b(i8* nonnull @a2) 222 br label %7 223 224; <label>:7: ; preds = %5, %3 225 %8 = phi i8* [ %4, %3 ], [ %6, %5 ] 226 ret i8* %8 227} 228 229; Function Attrs: nounwind readnone ssp uwtable 230define internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 { 231; 232; ATTRIBUTOR-LABEL: define {{[^@]+}}@f3b() local_unnamed_addr 233; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null 234; ATTRIBUTOR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] 235; ATTRIBUTOR: 2: 236; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 16 dereferenceable(1) @a2) 237; ATTRIBUTOR-NEXT: br label [[TMP4]] 238; ATTRIBUTOR: 4: 239; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ @a1, [[TMP0:%.*]] ] 240; ATTRIBUTOR-NEXT: ret i8* [[TMP5]] 241; 242 %2 = icmp eq i8* %0, null 243 br i1 %2, label %3, label %5 244 245; <label>:3: ; preds = %1 246 %4 = tail call i8* @f1b(i8* nonnull @a2) 247 br label %5 248 249; <label>:5: ; preds = %1, %3 250 %6 = phi i8* [ %4, %3 ], [ @a1, %1 ] 251 ret i8* %6 252} 253 254define align 4 i32* @test7b(i32* align 32 %p) #0 { 255; ATTRIBUTOR-LABEL: define {{[^@]+}}@test7b 256; ATTRIBUTOR-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) 257; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) 258; ATTRIBUTOR-NEXT: ret i32* [[P]] 259; 260 tail call i8* @f1b(i8* align 8 dereferenceable(1) @a1) 261 ret i32* %p 262} 263 264; UTC_ARGS: --disable 265 266; TEST 8 267define void @test8_helper() { 268 %ptr0 = tail call i32* @unknown() 269 %ptr1 = tail call align 4 i32* @unknown() 270 %ptr2 = tail call align 8 i32* @unknown() 271 272 tail call void @test8(i32* %ptr1, i32* %ptr1, i32* %ptr0) 273; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1, i32* noalias readnone %ptr0) 274 tail call void @test8(i32* %ptr2, i32* %ptr1, i32* %ptr1) 275; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 8 %ptr2, i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1) 276 tail call void @test8(i32* %ptr2, i32* %ptr1, i32* %ptr1) 277; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 8 %ptr2, i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1) 278 ret void 279} 280 281declare void @user_i32_ptr(i32* nocapture readnone) nounwind 282define internal void @test8(i32* %a, i32* %b, i32* %c) { 283; ATTRIBUTOR_MODULE: define internal void @test8(i32* noalias nocapture readnone align 4 %a, i32* noalias nocapture readnone align 4 %b, i32* noalias nocapture readnone %c) 284; ATTRIBUTOR_CGSCC: define internal void @test8(i32* nocapture readnone align 4 %a, i32* nocapture readnone align 4 %b, i32* nocapture readnone %c) 285 call void @user_i32_ptr(i32* %a) 286 call void @user_i32_ptr(i32* %b) 287 call void @user_i32_ptr(i32* %c) 288 ret void 289} 290 291declare void @test9_helper(i32* %A) 292define void @test9_traversal(i1 %c, i32* align 4 %B, i32* align 8 %C) { 293 %sel = select i1 %c, i32* %B, i32* %C 294 call void @test9_helper(i32* %sel) 295 ret void 296} 297 298; FIXME: This will work with an upcoming patch (D66618 or similar) 299; define align 32 i32* @test10a(i32* align 32 "no-capture-maybe-returned" %p) 300; ATTRIBUTOR: define i32* @test10a(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" %p) 301define i32* @test10a(i32* align 32 %p) { 302; ATTRIBUTOR: %l = load i32, i32* %p, align 32 303 %l = load i32, i32* %p 304 %c = icmp eq i32 %l, 0 305 br i1 %c, label %t, label %f 306t: 307 %r = call i32* @test10a(i32* %p) 308; FIXME: This will work with an upcoming patch (D66618 or similar) 309; store i32 1, i32* %r, align 32 310; ATTRIBUTOR: store i32 1, i32* %r 311 store i32 1, i32* %r 312 %g0 = getelementptr i32, i32* %p, i32 8 313 br label %e 314f: 315 %g1 = getelementptr i32, i32* %p, i32 8 316; FIXME: This will work with an upcoming patch (D66618 or similar) 317; store i32 -1, i32* %g1, align 32 318; ATTRIBUTOR: store i32 -1, i32* %g1 319 store i32 -1, i32* %g1 320 br label %e 321e: 322 %phi = phi i32* [%g0, %t], [%g1, %f] 323 ret i32* %phi 324} 325 326; FIXME: This will work with an upcoming patch (D66618 or similar) 327; define align 32 i32* @test10b(i32* align 32 "no-capture-maybe-returned" %p) 328; ATTRIBUTOR: define i32* @test10b(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" %p) 329define i32* @test10b(i32* align 32 %p) { 330; ATTRIBUTOR: %l = load i32, i32* %p, align 32 331 %l = load i32, i32* %p 332 %c = icmp eq i32 %l, 0 333 br i1 %c, label %t, label %f 334t: 335 %r = call i32* @test10b(i32* %p) 336; FIXME: This will work with an upcoming patch (D66618 or similar) 337; store i32 1, i32* %r, align 32 338; ATTRIBUTOR: store i32 1, i32* %r 339 store i32 1, i32* %r 340 %g0 = getelementptr i32, i32* %p, i32 8 341 br label %e 342f: 343 %g1 = getelementptr i32, i32* %p, i32 -8 344; FIXME: This will work with an upcoming patch (D66618 or similar) 345; store i32 -1, i32* %g1, align 32 346; ATTRIBUTOR: store i32 -1, i32* %g1 347 store i32 -1, i32* %g1 348 br label %e 349e: 350 %phi = phi i32* [%g0, %t], [%g1, %f] 351 ret i32* %phi 352} 353 354 355; ATTRIBUTOR: define i64 @test11(i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) %p) 356define i64 @test11(i32* %p) { 357 %p-cast = bitcast i32* %p to i64* 358 %ret = load i64, i64* %p-cast, align 8 359 ret i64 %ret 360} 361 362; TEST 12 363; Test for deduction using must-be-executed-context and GEP instruction 364 365; FXIME: %p should have nonnull 366; ATTRIBUTOR: define i64 @test12-1(i32* nocapture nofree readonly align 16 %p) 367define i64 @test12-1(i32* align 4 %p) { 368 %p-cast = bitcast i32* %p to i64* 369 %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 370 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 371 %ret = load i64, i64* %arrayidx1, align 16 372 ret i64 %ret 373} 374 375; ATTRIBUTOR: define i64 @test12-2(i32* nocapture nofree nonnull readonly align 16 dereferenceable(8) %p) 376define i64 @test12-2(i32* align 4 %p) { 377 %p-cast = bitcast i32* %p to i64* 378 %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 379 %ret = load i64, i64* %arrayidx0, align 16 380 ret i64 %ret 381} 382 383; FXIME: %p should have nonnull 384; ATTRIBUTOR: define void @test12-3(i32* nocapture nofree writeonly align 16 %p) 385define void @test12-3(i32* align 4 %p) { 386 %p-cast = bitcast i32* %p to i64* 387 %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 388 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 389 store i64 0, i64* %arrayidx1, align 16 390 ret void 391} 392 393; ATTRIBUTOR: define void @test12-4(i32* nocapture nofree nonnull writeonly align 16 dereferenceable(8) %p) 394define void @test12-4(i32* align 4 %p) { 395 %p-cast = bitcast i32* %p to i64* 396 %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 397 store i64 0, i64* %arrayidx0, align 16 398 ret void 399} 400 401declare void @use(i64*) willreturn nounwind 402 403; ATTRIBUTOR: define void @test12-5(i32* align 16 %p) 404define void @test12-5(i32* align 4 %p) { 405 %p-cast = bitcast i32* %p to i64* 406 %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 407 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 408 tail call void @use(i64* align 16 %arrayidx1) 409 ret void 410} 411 412; ATTRIBUTOR: define void @test12-6(i32* align 16 %p) 413define void @test12-6(i32* align 4 %p) { 414 %p-cast = bitcast i32* %p to i64* 415 %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 416 tail call void @use(i64* align 16 %arrayidx0) 417 ret void 418} 419 420define void @test13(i1 %c, i32* align 32 %dst) #0 { 421; ATTRIBUTOR-LABEL: define {{[^@]+}}@test13 422; ATTRIBUTOR-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) 423; ATTRIBUTOR-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] 424; ATTRIBUTOR: truebb: 425; ATTRIBUTOR-NEXT: br label [[END:%.*]] 426; ATTRIBUTOR: falsebb: 427; ATTRIBUTOR-NEXT: br label [[END]] 428; ATTRIBUTOR: end: 429; ATTRIBUTOR-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] 430; ATTRIBUTOR-NEXT: store i32 0, i32* [[PTR]], align 32 431; ATTRIBUTOR-NEXT: ret void 432; 433 br i1 %c, label %truebb, label %falsebb 434truebb: 435 br label %end 436falsebb: 437 br label %end 438end: 439 %ptr = phi i32* [ %dst, %truebb ], [ null, %falsebb ] 440 store i32 0, i32* %ptr 441 ret void 442} 443 444define void @test13-1(i1 %c, i32* align 32 %dst) { 445; ATTRIBUTOR-LABEL: @test13-1( 446; ATTRIBUTOR-NEXT: br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] 447; ATTRIBUTOR: truebb: 448; ATTRIBUTOR-NEXT: br label [[END:%.*]] 449; ATTRIBUTOR: falsebb: 450; ATTRIBUTOR-NEXT: br label [[END]] 451; ATTRIBUTOR: end: 452; ATTRIBUTOR-NEXT: [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 48 to i32*), [[FALSEBB]] ] 453; ATTRIBUTOR-NEXT: store i32 0, i32* [[PTR]], align 16 454; ATTRIBUTOR-NEXT: ret void 455; 456 br i1 %c, label %truebb, label %falsebb 457truebb: 458 br label %end 459falsebb: 460 br label %end 461end: 462 %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 48 to i32*), %falsebb ] 463 store i32 0, i32* %ptr 464 ret void 465} 466 467define void @test13-2(i1 %c, i32* align 32 %dst) { 468; ATTRIBUTOR-LABEL: @test13-2( 469; ATTRIBUTOR-NEXT: br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] 470; ATTRIBUTOR: truebb: 471; ATTRIBUTOR-NEXT: br label [[END:%.*]] 472; ATTRIBUTOR: falsebb: 473; ATTRIBUTOR-NEXT: br label [[END]] 474; ATTRIBUTOR: end: 475; ATTRIBUTOR-NEXT: [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 160 to i32*), [[FALSEBB]] ] 476; ATTRIBUTOR-NEXT: store i32 0, i32* [[PTR]], align 32 477; ATTRIBUTOR-NEXT: ret void 478; 479 br i1 %c, label %truebb, label %falsebb 480truebb: 481 br label %end 482falsebb: 483 br label %end 484end: 485 %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 160 to i32*), %falsebb ] 486 store i32 0, i32* %ptr 487 ret void 488} 489 490define void @test13-3(i1 %c, i32* align 32 %dst) { 491; ATTRIBUTOR-LABEL: @test13-3( 492; ATTRIBUTOR-NEXT: br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] 493; ATTRIBUTOR: truebb: 494; ATTRIBUTOR-NEXT: br label [[END:%.*]] 495; ATTRIBUTOR: falsebb: 496; ATTRIBUTOR-NEXT: br label [[END]] 497; ATTRIBUTOR: end: 498; ATTRIBUTOR-NEXT: [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 128 to i32*), [[FALSEBB]] ] 499; ATTRIBUTOR-NEXT: store i32 0, i32* [[PTR]], align 32 500; ATTRIBUTOR-NEXT: ret void 501; 502 br i1 %c, label %truebb, label %falsebb 503truebb: 504 br label %end 505falsebb: 506 br label %end 507end: 508 %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 128 to i32*), %falsebb ] 509 store i32 0, i32* %ptr 510 ret void 511} 512 513; Don't crash on ptr2int/int2ptr uses. 514define i64 @ptr2int(i32* %p) { 515 %p2i = ptrtoint i32* %p to i64 516 ret i64 %p2i 517} 518define i64* @int2ptr(i64 %i) { 519 %i2p = inttoptr i64 %i to i64* 520 ret i64* %i2p 521} 522 523; Use the store alignment only for the pointer operand. 524define void @aligned_store(i8* %Value, i8** %Ptr) { 525; ATTRIBUTOR: define void @aligned_store(i8* nofree writeonly %Value, i8** nocapture nofree nonnull writeonly align 32 dereferenceable(8) %Ptr) 526 store i8* %Value, i8** %Ptr, align 32 527 ret void 528} 529 530; UTC_ARGS: --enable 531declare i8* @some_func(i8*) 532define void @align_call_op_not_store(i8* align 2048 %arg) { 533; ATTRIBUTOR-LABEL: define {{[^@]+}}@align_call_op_not_store 534; ATTRIBUTOR-SAME: (i8* align 2048 [[ARG:%.*]]) 535; ATTRIBUTOR-NEXT: [[UNKNOWN:%.*]] = call i8* @some_func(i8* align 2048 [[ARG]]) 536; ATTRIBUTOR-NEXT: store i8 0, i8* [[UNKNOWN]] 537; ATTRIBUTOR-NEXT: ret void 538; 539 %unknown = call i8* @some_func(i8* %arg) 540 store i8 0, i8* %unknown 541 ret void 542} 543define void @align_store_after_bc(i32* align 2048 %arg) { 544; 545; ATTRIBUTOR-LABEL: define {{[^@]+}}@align_store_after_bc 546; ATTRIBUTOR-SAME: (i32* nocapture nofree nonnull writeonly align 2048 dereferenceable(1) [[ARG:%.*]]) 547; ATTRIBUTOR-NEXT: [[BC:%.*]] = bitcast i32* [[ARG]] to i8* 548; ATTRIBUTOR-NEXT: store i8 0, i8* [[BC]], align 2048 549; ATTRIBUTOR-NEXT: ret void 550; 551 %bc = bitcast i32* %arg to i8* 552 store i8 0, i8* %bc 553 ret void 554} 555 556; Make sure we do not annotate the callee of a must-tail call with an alignment 557; we cannot also put on the caller. 558@cnd = external global i1 559define i32 @musttail_callee_1(i32* %p) { 560 %v = load i32, i32* %p, align 32 561 ret i32 %v 562} 563define i32 @musttail_caller_1(i32* %p) { 564 %c = load i1, i1* @cnd 565 br i1 %c, label %mt, label %exit 566mt: 567 %v = musttail call i32 @musttail_callee_1(i32* %p) 568 ret i32 %v 569exit: 570 ret i32 0 571} 572; UTC_ARGS: --disable 573 574attributes #0 = { nounwind uwtable noinline } 575attributes #1 = { uwtable noinline } 576attributes #2 = { "null-pointer-is-valid"="true" } 577