; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals ; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; Test cases specifically designed for "align" attribute. ; We use FIXME's to indicate problems and missing attributes. ; TEST 1 ;; ;. ; CHECK: @[[A1:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 8 ; CHECK: @[[A2:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 16 ; CHECK: @[[CND:[a-zA-Z0-9_$"\\.-]+]] = external global i1 ; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = global i8 0, align 32 ;. define i32* @test1(i32* align 8 %0) #0 { ; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; CHECK-LABEL: define {{[^@]+}}@test1 ; CHECK-SAME: (i32* nofree readnone returned align 8 "no-capture-maybe-returned" [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: ret i32* [[TMP0]] ; ret i32* %0 } ; TEST 2 define i32* @test2(i32* %0) #0 { ; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; CHECK-LABEL: define {{[^@]+}}@test2 ; CHECK-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[TMP0:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: ret i32* [[TMP0]] ; ret i32* %0 } ; TEST 3 define i32* @test3(i32* align 8 %0, i32* align 4 %1, i1 %2) #0 { ; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; CHECK-LABEL: define {{[^@]+}}@test3 ; CHECK-SAME: (i32* nofree readnone align 8 "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree readnone align 4 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP1]] ; CHECK-NEXT: ret i32* [[RET]] ; %ret = select i1 %2, i32* %0, i32* %1 ret i32* %ret } ; TEST 4 define i32* @test4(i32* align 32 %0, i32* align 32 %1, i1 %2) #0 { ; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; CHECK-LABEL: define {{[^@]+}}@test4 ; CHECK-SAME: (i32* nofree readnone align 32 "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree readnone align 32 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP1]] ; CHECK-NEXT: ret i32* [[RET]] ; %ret = select i1 %2, i32* %0, i32* %1 ret i32* %ret } ; TEST 5 declare i32* @unknown() declare align 8 i32* @align8() define i32* @test5_1() { ; CHECK-LABEL: define {{[^@]+}}@test5_1() { ; CHECK-NEXT: [[RET:%.*]] = tail call align 8 i32* @unknown() ; CHECK-NEXT: ret i32* [[RET]] ; %ret = tail call align 8 i32* @unknown() ret i32* %ret } define i32* @test5_2() { ; CHECK-LABEL: define {{[^@]+}}@test5_2() { ; CHECK-NEXT: [[RET:%.*]] = tail call align 8 i32* @align8() ; CHECK-NEXT: ret i32* [[RET]] ; %ret = tail call i32* @align8() ret i32* %ret } ; TEST 6 ; SCC define i32* @test6_1() #0 { ; NOT_CGSCC_NPM: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test6_1 ; NOT_CGSCC_NPM-SAME: () #[[ATTR1:[0-9]+]] { ; NOT_CGSCC_NPM-NEXT: ret i32* undef ; ; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test6_1 ; IS__CGSCC_NPM-SAME: () #[[ATTR0]] { ; IS__CGSCC_NPM-NEXT: ret i32* undef ; %ret = tail call i32* @test6_2() ret i32* %ret } define i32* @test6_2() #0 { ; NOT_CGSCC_NPM: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test6_2 ; NOT_CGSCC_NPM-SAME: () #[[ATTR1]] { ; NOT_CGSCC_NPM-NEXT: ret i32* undef ; ; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test6_2 ; IS__CGSCC_NPM-SAME: () #[[ATTR0]] { ; IS__CGSCC_NPM-NEXT: ret i32* undef ; %ret = tail call i32* @test6_1() ret i32* %ret } ; char a1 __attribute__((aligned(8))); ; char a2 __attribute__((aligned(16))); ; ; char* f1(char* a ){ ; return a?a:f2(&a1); ; } ; char* f2(char* a){ ; return a?f1(a):f3(&a2); ; } ; ; char* f3(char* a){ ; return a?&a1: f1(&a2); ; } @a1 = common global i8 0, align 8 @a2 = common global i8 0, align 16 ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 { ; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; CHECK-LABEL: define {{[^@]+}}@f1 ; CHECK-SAME: (i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: br label [[TMP3:%.*]] ; CHECK: 2: ; CHECK-NEXT: unreachable ; CHECK: 3: ; CHECK-NEXT: ret i8* [[TMP0]] ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 ; <label>:3: ; preds = %1 %4 = tail call i8* @f2(i8* nonnull @a1) %l = load i8, i8* %4 br label %5 ; <label>:5: ; preds = %1, %3 %6 = phi i8* [ %4, %3 ], [ %0, %1 ] ret i8* %6 } ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 { ; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f2 ; IS__CGSCC_OPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp eq i8* undef, null ; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] ; IS__CGSCC_OPM: 3: ; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = tail call i8* @f1(i8* noalias nonnull readnone align 4294967296 dereferenceable(4294967295) undef) ; IS__CGSCC_OPM-NEXT: br label [[TMP7:%.*]] ; IS__CGSCC_OPM: 5: ; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = tail call i8* @f3(i8* nonnull @a2) ; IS__CGSCC_OPM-NEXT: br label [[TMP7]] ; IS__CGSCC_OPM: 7: ; IS__CGSCC_OPM-NEXT: [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ] ; IS__CGSCC_OPM-NEXT: ret i8* [[TMP8]] ; ; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2 ; IS__CGSCC_NPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp eq i8* undef, null ; IS__CGSCC_NPM-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] ; IS__CGSCC_NPM: 3: ; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = tail call i8* @f1(i8* noalias nonnull readnone align 4294967296 dereferenceable(4294967295) undef) ; IS__CGSCC_NPM-NEXT: br label [[TMP7:%.*]] ; IS__CGSCC_NPM: 5: ; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = tail call i8* @f3() ; IS__CGSCC_NPM-NEXT: br label [[TMP7]] ; IS__CGSCC_NPM: 7: ; IS__CGSCC_NPM-NEXT: [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ] ; IS__CGSCC_NPM-NEXT: ret i8* [[TMP8]] ; %2 = icmp eq i8* %0, null br i1 %2, label %5, label %3 ; <label>:3: ; preds = %1 %4 = tail call i8* @f1(i8* nonnull %0) br label %7 ; <label>:5: ; preds = %1 %6 = tail call i8* @f3(i8* nonnull @a2) br label %7 ; <label>:7: ; preds = %5, %3 %8 = phi i8* [ %4, %3 ], [ %6, %5 ] ret i8* %8 } ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 { ; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f3 ; IS__CGSCC_OPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] { ; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null ; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] ; IS__CGSCC_OPM: 3: ; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = tail call i8* @f1(i8* noalias noundef nonnull readnone align 16 dereferenceable(1) @a2) ; IS__CGSCC_OPM-NEXT: br label [[TMP5]] ; IS__CGSCC_OPM: 5: ; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ @a1, [[TMP1:%.*]] ] ; IS__CGSCC_OPM-NEXT: ret i8* [[TMP6]] ; ; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f3 ; IS__CGSCC_NPM-SAME: () local_unnamed_addr #[[ATTR0]] { ; IS__CGSCC_NPM-NEXT: br label [[TMP2:%.*]] ; IS__CGSCC_NPM: 1: ; IS__CGSCC_NPM-NEXT: unreachable ; IS__CGSCC_NPM: 2: ; IS__CGSCC_NPM-NEXT: ret i8* @a1 ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 ; <label>:3: ; preds = %1 %4 = tail call i8* @f1(i8* nonnull @a2) br label %5 ; <label>:5: ; preds = %1, %3 %6 = phi i8* [ %4, %3 ], [ @a1, %1 ] ret i8* %6 } ; TEST 7 ; Better than IR information define align 4 i8* @test7() #0 { ; IS__TUNIT____: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7 ; IS__TUNIT____-SAME: () #[[ATTR0]] { ; IS__TUNIT____-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) #[[ATTR9:[0-9]+]] ; IS__TUNIT____-NEXT: ret i8* [[C]] ; ; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test7 ; IS__CGSCC_OPM-SAME: () #[[ATTR1]] { ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = tail call noundef nonnull align 8 dereferenceable(1) i8* @f1(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) @a1) #[[ATTR13:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i8* [[C]] ; ; IS__CGSCC_NPM: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test7 ; IS__CGSCC_NPM-SAME: () #[[ATTR2:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = tail call noundef nonnull align 8 dereferenceable(1) i8* @f1(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) @a1) #[[ATTR13:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i8* [[C]] ; %c = tail call i8* @f1(i8* align 8 dereferenceable(1) @a1) ret i8* %c } ; TEST 7b ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@f1b ; IS__CGSCC____-SAME: (i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { ; IS__CGSCC____-NEXT: br label [[TMP3:%.*]] ; IS__CGSCC____: 2: ; IS__CGSCC____-NEXT: unreachable ; IS__CGSCC____: 3: ; IS__CGSCC____-NEXT: ret i8* [[TMP0]] ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 ; <label>:3: ; preds = %1 %4 = tail call i8* @f2b(i8* nonnull @a1) %l = load i8, i8* %4 store i8 %l, i8* @a1 br label %5 ; <label>:5: ; preds = %1, %3 %6 = phi i8* [ %4, %3 ], [ %0, %1 ] ret i8* %6 } ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 { ; ; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f2b ; IS__CGSCC_OPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] { ; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp eq i8* undef, null ; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] ; IS__CGSCC_OPM: 3: ; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = tail call i8* @f1b(i8* noalias nonnull readnone align 4294967296 dereferenceable(4294967295) undef) ; IS__CGSCC_OPM-NEXT: br label [[TMP7:%.*]] ; IS__CGSCC_OPM: 5: ; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = tail call i8* @f3b(i8* nonnull @a2) ; IS__CGSCC_OPM-NEXT: br label [[TMP7]] ; IS__CGSCC_OPM: 7: ; IS__CGSCC_OPM-NEXT: [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ] ; IS__CGSCC_OPM-NEXT: ret i8* [[TMP8]] ; ; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2b ; IS__CGSCC_NPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp eq i8* undef, null ; IS__CGSCC_NPM-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] ; IS__CGSCC_NPM: 3: ; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = tail call i8* @f1b(i8* noalias nonnull readnone align 4294967296 dereferenceable(4294967295) undef) ; IS__CGSCC_NPM-NEXT: br label [[TMP7:%.*]] ; IS__CGSCC_NPM: 5: ; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = tail call i8* @f3b() ; IS__CGSCC_NPM-NEXT: br label [[TMP7]] ; IS__CGSCC_NPM: 7: ; IS__CGSCC_NPM-NEXT: [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ] ; IS__CGSCC_NPM-NEXT: ret i8* [[TMP8]] ; %2 = icmp eq i8* %0, null br i1 %2, label %5, label %3 ; <label>:3: ; preds = %1 %4 = tail call i8* @f1b(i8* nonnull %0) br label %7 ; <label>:5: ; preds = %1 %6 = tail call i8* @f3b(i8* nonnull @a2) br label %7 ; <label>:7: ; preds = %5, %3 %8 = phi i8* [ %4, %3 ], [ %6, %5 ] ret i8* %8 } ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 { ; ; IS__CGSCC_OPM: Function Attrs: noinline nounwind uwtable ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f3b ; IS__CGSCC_OPM-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] { ; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null ; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] ; IS__CGSCC_OPM: 3: ; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = tail call i8* @f1b(i8* noalias noundef nonnull readnone align 16 dereferenceable(1) @a2) ; IS__CGSCC_OPM-NEXT: br label [[TMP5]] ; IS__CGSCC_OPM: 5: ; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ @a1, [[TMP1:%.*]] ] ; IS__CGSCC_OPM-NEXT: ret i8* [[TMP6]] ; ; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f3b ; IS__CGSCC_NPM-SAME: () local_unnamed_addr #[[ATTR0]] { ; IS__CGSCC_NPM-NEXT: br label [[TMP2:%.*]] ; IS__CGSCC_NPM: 1: ; IS__CGSCC_NPM-NEXT: unreachable ; IS__CGSCC_NPM: 2: ; IS__CGSCC_NPM-NEXT: ret i8* @a1 ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 ; <label>:3: ; preds = %1 %4 = tail call i8* @f1b(i8* nonnull @a2) br label %5 ; <label>:5: ; preds = %1, %3 %6 = phi i8* [ %4, %3 ], [ @a1, %1 ] ret i8* %6 } define align 4 i32* @test7b(i32* align 32 %p) #0 { ; IS__TUNIT____: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7b ; IS__TUNIT____-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR0]] { ; IS__TUNIT____-NEXT: ret i32* [[P]] ; ; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test7b ; IS__CGSCC_OPM-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] { ; IS__CGSCC_OPM-NEXT: ret i32* [[P]] ; ; IS__CGSCC_NPM: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test7b ; IS__CGSCC_NPM-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR2]] { ; IS__CGSCC_NPM-NEXT: ret i32* [[P]] ; tail call i8* @f1b(i8* align 8 dereferenceable(1) @a1) ret i32* %p } ; TEST 8 define void @test8_helper() { ; IS__TUNIT____-LABEL: define {{[^@]+}}@test8_helper() { ; IS__TUNIT____-NEXT: [[PTR0:%.*]] = tail call i32* @unknown() ; IS__TUNIT____-NEXT: [[PTR1:%.*]] = tail call align 4 i32* @unknown() ; IS__TUNIT____-NEXT: [[PTR2:%.*]] = tail call align 8 i32* @unknown() ; IS__TUNIT____-NEXT: tail call void @test8(i32* noalias nocapture readnone align 4 [[PTR1]], i32* noalias nocapture readnone align 4 [[PTR1]], i32* noalias nocapture readnone [[PTR0]]) #[[ATTR2:[0-9]+]] ; IS__TUNIT____-NEXT: tail call void @test8(i32* noalias nocapture readnone align 8 [[PTR2]], i32* noalias nocapture readnone align 4 [[PTR1]], i32* noalias nocapture readnone align 4 [[PTR1]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: tail call void @test8(i32* noalias nocapture readnone align 8 [[PTR2]], i32* noalias nocapture readnone align 4 [[PTR1]], i32* noalias nocapture readnone align 4 [[PTR1]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____-LABEL: define {{[^@]+}}@test8_helper() { ; IS__CGSCC____-NEXT: [[PTR0:%.*]] = tail call i32* @unknown() ; IS__CGSCC____-NEXT: [[PTR1:%.*]] = tail call align 4 i32* @unknown() ; IS__CGSCC____-NEXT: [[PTR2:%.*]] = tail call align 8 i32* @unknown() ; IS__CGSCC____-NEXT: tail call void @test8(i32* noalias nocapture readnone align 4 [[PTR1]], i32* noalias nocapture readnone align 4 [[PTR1]], i32* noalias nocapture readnone [[PTR0]]) #[[ATTR3:[0-9]+]] ; IS__CGSCC____-NEXT: tail call void @test8(i32* noalias nocapture readnone align 8 [[PTR2]], i32* noalias nocapture readnone align 4 [[PTR1]], i32* noalias nocapture readnone align 4 [[PTR1]]) #[[ATTR3]] ; IS__CGSCC____-NEXT: tail call void @test8(i32* noalias nocapture readnone align 8 [[PTR2]], i32* noalias nocapture readnone align 4 [[PTR1]], i32* noalias nocapture readnone align 4 [[PTR1]]) #[[ATTR3]] ; IS__CGSCC____-NEXT: ret void ; %ptr0 = tail call i32* @unknown() %ptr1 = tail call align 4 i32* @unknown() %ptr2 = tail call align 8 i32* @unknown() tail call void @test8(i32* %ptr1, i32* %ptr1, i32* %ptr0) tail call void @test8(i32* %ptr2, i32* %ptr1, i32* %ptr1) tail call void @test8(i32* %ptr2, i32* %ptr1, i32* %ptr1) ret void } declare void @user_i32_ptr(i32* nocapture readnone) nounwind define internal void @test8(i32* %a, i32* %b, i32* %c) { ; IS__TUNIT____: Function Attrs: nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@test8 ; IS__TUNIT____-SAME: (i32* noalias nocapture readnone align 4 [[A:%.*]], i32* noalias nocapture readnone align 4 [[B:%.*]], i32* noalias nocapture readnone [[C:%.*]]) #[[ATTR2]] { ; IS__TUNIT____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone align 4 [[A]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone align 4 [[B]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone [[C]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@test8 ; IS__CGSCC____-SAME: (i32* noalias nocapture readnone align 4 [[A:%.*]], i32* noalias nocapture readnone align 4 [[B:%.*]], i32* noalias nocapture readnone [[C:%.*]]) #[[ATTR3]] { ; IS__CGSCC____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone align 4 [[A]]) #[[ATTR3]] ; IS__CGSCC____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone align 4 [[B]]) #[[ATTR3]] ; IS__CGSCC____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone [[C]]) #[[ATTR3]] ; IS__CGSCC____-NEXT: ret void ; call void @user_i32_ptr(i32* %a) call void @user_i32_ptr(i32* %b) call void @user_i32_ptr(i32* %c) ret void } declare void @test9_helper(i32* %A) define void @test9_traversal(i1 %cnd, i32* align 4 %B, i32* align 8 %C) { ; CHECK-LABEL: define {{[^@]+}}@test9_traversal ; CHECK-SAME: (i1 [[CND:%.*]], i32* align 4 [[B:%.*]], i32* align 8 [[C:%.*]]) { ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CND]], i32* [[B]], i32* [[C]] ; CHECK-NEXT: call void @test9_helper(i32* align 4 [[SEL]]) ; CHECK-NEXT: ret void ; %sel = select i1 %cnd, i32* %B, i32* %C call void @test9_helper(i32* %sel) ret void } ; FIXME: This will work with an upcoming patch (D66618 or similar) ; define align 32 i32* @test10a(i32* align 32 "no-capture-maybe-returned" %p) ; FIXME: This will work with an upcoming patch (D66618 or similar) ; store i32 1, i32* %r, align 32 ; FIXME: This will work with an upcoming patch (D66618 or similar) ; store i32 -1, i32* %g1, align 32 define i32* @test10a(i32* align 32 %p) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@test10a ; IS__TUNIT____-SAME: (i32* nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3:[0-9]+]] { ; IS__TUNIT____-NEXT: [[L:%.*]] = load i32, i32* [[P]], align 32 ; IS__TUNIT____-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 ; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__TUNIT____: t: ; IS__TUNIT____-NEXT: [[R:%.*]] = call align 32 i32* @test10a(i32* nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR3]] ; IS__TUNIT____-NEXT: store i32 1, i32* [[R]], align 32 ; IS__TUNIT____-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8 ; IS__TUNIT____-NEXT: br label [[E:%.*]] ; IS__TUNIT____: f: ; IS__TUNIT____-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 8 ; IS__TUNIT____-NEXT: store i32 -1, i32* [[G1]], align 32 ; IS__TUNIT____-NEXT: br label [[E]] ; IS__TUNIT____: e: ; IS__TUNIT____-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] ; IS__TUNIT____-NEXT: ret i32* [[PHI]] ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@test10a ; IS__CGSCC____-SAME: (i32* nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4:[0-9]+]] { ; IS__CGSCC____-NEXT: [[L:%.*]] = load i32, i32* [[P]], align 32 ; IS__CGSCC____-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: t: ; IS__CGSCC____-NEXT: [[R:%.*]] = call align 32 i32* @test10a(i32* nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR4]] ; IS__CGSCC____-NEXT: store i32 1, i32* [[R]], align 32 ; IS__CGSCC____-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8 ; IS__CGSCC____-NEXT: br label [[E:%.*]] ; IS__CGSCC____: f: ; IS__CGSCC____-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 8 ; IS__CGSCC____-NEXT: store i32 -1, i32* [[G1]], align 32 ; IS__CGSCC____-NEXT: br label [[E]] ; IS__CGSCC____: e: ; IS__CGSCC____-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] ; IS__CGSCC____-NEXT: ret i32* [[PHI]] ; %l = load i32, i32* %p %c = icmp eq i32 %l, 0 br i1 %c, label %t, label %f t: %r = call i32* @test10a(i32* %p) store i32 1, i32* %r %g0 = getelementptr i32, i32* %p, i32 8 br label %e f: %g1 = getelementptr i32, i32* %p, i32 8 store i32 -1, i32* %g1 br label %e e: %phi = phi i32* [%g0, %t], [%g1, %f] ret i32* %phi } ; FIXME: This will work with an upcoming patch (D66618 or similar) ; define align 32 i32* @test10b(i32* align 32 "no-capture-maybe-returned" %p) ; FIXME: This will work with an upcoming patch (D66618 or similar) ; store i32 1, i32* %r, align 32 ; FIXME: This will work with an upcoming patch (D66618 or similar) ; store i32 -1, i32* %g1, align 32 define i32* @test10b(i32* align 32 %p) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@test10b ; IS__TUNIT____-SAME: (i32* nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3]] { ; IS__TUNIT____-NEXT: [[L:%.*]] = load i32, i32* [[P]], align 32 ; IS__TUNIT____-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 ; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__TUNIT____: t: ; IS__TUNIT____-NEXT: [[R:%.*]] = call align 32 i32* @test10b(i32* nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR3]] ; IS__TUNIT____-NEXT: store i32 1, i32* [[R]], align 32 ; IS__TUNIT____-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8 ; IS__TUNIT____-NEXT: br label [[E:%.*]] ; IS__TUNIT____: f: ; IS__TUNIT____-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 -8 ; IS__TUNIT____-NEXT: store i32 -1, i32* [[G1]], align 32 ; IS__TUNIT____-NEXT: br label [[E]] ; IS__TUNIT____: e: ; IS__TUNIT____-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] ; IS__TUNIT____-NEXT: ret i32* [[PHI]] ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@test10b ; IS__CGSCC____-SAME: (i32* nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4]] { ; IS__CGSCC____-NEXT: [[L:%.*]] = load i32, i32* [[P]], align 32 ; IS__CGSCC____-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: t: ; IS__CGSCC____-NEXT: [[R:%.*]] = call align 32 i32* @test10b(i32* nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR4]] ; IS__CGSCC____-NEXT: store i32 1, i32* [[R]], align 32 ; IS__CGSCC____-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8 ; IS__CGSCC____-NEXT: br label [[E:%.*]] ; IS__CGSCC____: f: ; IS__CGSCC____-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 -8 ; IS__CGSCC____-NEXT: store i32 -1, i32* [[G1]], align 32 ; IS__CGSCC____-NEXT: br label [[E]] ; IS__CGSCC____: e: ; IS__CGSCC____-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] ; IS__CGSCC____-NEXT: ret i32* [[PHI]] ; %l = load i32, i32* %p %c = icmp eq i32 %l, 0 br i1 %c, label %t, label %f t: %r = call i32* @test10b(i32* %p) store i32 1, i32* %r %g0 = getelementptr i32, i32* %p, i32 8 br label %e f: %g1 = getelementptr i32, i32* %p, i32 -8 store i32 -1, i32* %g1 br label %e e: %phi = phi i32* [%g0, %t], [%g1, %f] ret i32* %phi } define i64 @test11(i32* %p) { ; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test11 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[P:%.*]]) #[[ATTR4:[0-9]+]] { ; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__TUNIT____-NEXT: [[RET:%.*]] = load i64, i64* [[P_CAST]], align 8 ; IS__TUNIT____-NEXT: ret i64 [[RET]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test11 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[P:%.*]]) #[[ATTR5:[0-9]+]] { ; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__CGSCC____-NEXT: [[RET:%.*]] = load i64, i64* [[P_CAST]], align 8 ; IS__CGSCC____-NEXT: ret i64 [[RET]] ; %p-cast = bitcast i32* %p to i64* %ret = load i64, i64* %p-cast, align 8 ret i64 %ret } ; TEST 12 ; Test for deduction using must-be-executed-context and GEP instruction ; FXIME: %p should have nonnull define i64 @test12-1(i32* align 4 %p) { ; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-1 ; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 16 [[P:%.*]]) #[[ATTR4]] { ; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 ; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 ; IS__TUNIT____-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX1]], align 16 ; IS__TUNIT____-NEXT: ret i64 [[RET]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-1 ; IS__CGSCC____-SAME: (i32* nocapture nofree readonly align 16 [[P:%.*]]) #[[ATTR5]] { ; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 ; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 ; IS__CGSCC____-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX1]], align 16 ; IS__CGSCC____-NEXT: ret i64 [[RET]] ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 %ret = load i64, i64* %arrayidx1, align 16 ret i64 %ret } define i64 @test12-2(i32* align 4 %p) { ; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-2 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 16 dereferenceable(8) [[P:%.*]]) #[[ATTR4]] { ; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 ; IS__TUNIT____-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX0]], align 16 ; IS__TUNIT____-NEXT: ret i64 [[RET]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-2 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 16 dereferenceable(8) [[P:%.*]]) #[[ATTR5]] { ; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 ; IS__CGSCC____-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX0]], align 16 ; IS__CGSCC____-NEXT: ret i64 [[RET]] ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 %ret = load i64, i64* %arrayidx0, align 16 ret i64 %ret } ; FXIME: %p should have nonnull define void @test12-3(i32* align 4 %p) { ; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-3 ; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly align 16 [[P:%.*]]) #[[ATTR5:[0-9]+]] { ; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 ; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 ; IS__TUNIT____-NEXT: store i64 0, i64* [[ARRAYIDX1]], align 16 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-3 ; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly align 16 [[P:%.*]]) #[[ATTR6:[0-9]+]] { ; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 ; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 ; IS__CGSCC____-NEXT: store i64 0, i64* [[ARRAYIDX1]], align 16 ; IS__CGSCC____-NEXT: ret void ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 store i64 0, i64* %arrayidx1, align 16 ret void } define void @test12-4(i32* align 4 %p) { ; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-4 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 16 dereferenceable(8) [[P:%.*]]) #[[ATTR5]] { ; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 ; IS__TUNIT____-NEXT: store i64 0, i64* [[ARRAYIDX0]], align 16 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-4 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 16 dereferenceable(8) [[P:%.*]]) #[[ATTR6]] { ; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 ; IS__CGSCC____-NEXT: store i64 0, i64* [[ARRAYIDX0]], align 16 ; IS__CGSCC____-NEXT: ret void ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 store i64 0, i64* %arrayidx0, align 16 ret void } declare void @use(i64*) willreturn nounwind define void @test12-5(i32* align 4 %p) { ; IS__TUNIT____: Function Attrs: nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-5 ; IS__TUNIT____-SAME: (i32* align 16 [[P:%.*]]) #[[ATTR6:[0-9]+]] { ; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 ; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 ; IS__TUNIT____-NEXT: tail call void @use(i64* align 16 [[ARRAYIDX1]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-5 ; IS__CGSCC____-SAME: (i32* align 16 [[P:%.*]]) #[[ATTR7:[0-9]+]] { ; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 ; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 ; IS__CGSCC____-NEXT: tail call void @use(i64* align 16 [[ARRAYIDX1]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: ret void ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 tail call void @use(i64* align 16 %arrayidx1) ret void } define void @test12-6(i32* align 4 %p) { ; IS__TUNIT____: Function Attrs: nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-6 ; IS__TUNIT____-SAME: (i32* align 16 [[P:%.*]]) #[[ATTR6]] { ; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 ; IS__TUNIT____-NEXT: tail call void @use(i64* align 16 [[ARRAYIDX0]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-6 ; IS__CGSCC____-SAME: (i32* align 16 [[P:%.*]]) #[[ATTR7]] { ; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* ; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 ; IS__CGSCC____-NEXT: tail call void @use(i64* align 16 [[ARRAYIDX0]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: ret void ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 tail call void @use(i64* align 16 %arrayidx0) ret void } define void @test13(i1 %c, i32* align 32 %dst) #0 { ; IS__TUNIT____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind willreturn writeonly uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@test13 ; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) #[[ATTR7:[0-9]+]] { ; IS__TUNIT____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] ; IS__TUNIT____: truebb: ; IS__TUNIT____-NEXT: br label [[END:%.*]] ; IS__TUNIT____: falsebb: ; IS__TUNIT____-NEXT: br label [[END]] ; IS__TUNIT____: end: ; IS__TUNIT____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] ; IS__TUNIT____-NEXT: store i32 0, i32* [[PTR]], align 32 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind willreturn writeonly uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@test13 ; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) #[[ATTR8:[0-9]+]] { ; IS__CGSCC____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] ; IS__CGSCC____: truebb: ; IS__CGSCC____-NEXT: br label [[END:%.*]] ; IS__CGSCC____: falsebb: ; IS__CGSCC____-NEXT: br label [[END]] ; IS__CGSCC____: end: ; IS__CGSCC____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] ; IS__CGSCC____-NEXT: store i32 0, i32* [[PTR]], align 32 ; IS__CGSCC____-NEXT: ret void ; br i1 %c, label %truebb, label %falsebb truebb: br label %end falsebb: br label %end end: %ptr = phi i32* [ %dst, %truebb ], [ null, %falsebb ] store i32 0, i32* %ptr ret void } define void @test13-1(i1 %c, i32* align 32 %dst) { ; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test13-1 ; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) #[[ATTR8:[0-9]+]] { ; IS__TUNIT____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] ; IS__TUNIT____: truebb: ; IS__TUNIT____-NEXT: br label [[END:%.*]] ; IS__TUNIT____: falsebb: ; IS__TUNIT____-NEXT: br label [[END]] ; IS__TUNIT____: end: ; IS__TUNIT____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to i32*), [[FALSEBB]] ] ; IS__TUNIT____-NEXT: store i32 0, i32* [[PTR]], align 16 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test13-1 ; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) #[[ATTR9:[0-9]+]] { ; IS__CGSCC____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] ; IS__CGSCC____: truebb: ; IS__CGSCC____-NEXT: br label [[END:%.*]] ; IS__CGSCC____: falsebb: ; IS__CGSCC____-NEXT: br label [[END]] ; IS__CGSCC____: end: ; IS__CGSCC____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to i32*), [[FALSEBB]] ] ; IS__CGSCC____-NEXT: store i32 0, i32* [[PTR]], align 16 ; IS__CGSCC____-NEXT: ret void ; br i1 %c, label %truebb, label %falsebb truebb: br label %end falsebb: br label %end end: %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 48 to i32*), %falsebb ] store i32 0, i32* %ptr ret void } define void @test13-2(i1 %c, i32* align 32 %dst) { ; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test13-2 ; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) #[[ATTR8]] { ; IS__TUNIT____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] ; IS__TUNIT____: truebb: ; IS__TUNIT____-NEXT: br label [[END:%.*]] ; IS__TUNIT____: falsebb: ; IS__TUNIT____-NEXT: br label [[END]] ; IS__TUNIT____: end: ; IS__TUNIT____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to i32*), [[FALSEBB]] ] ; IS__TUNIT____-NEXT: store i32 0, i32* [[PTR]], align 32 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test13-2 ; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) #[[ATTR9]] { ; IS__CGSCC____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] ; IS__CGSCC____: truebb: ; IS__CGSCC____-NEXT: br label [[END:%.*]] ; IS__CGSCC____: falsebb: ; IS__CGSCC____-NEXT: br label [[END]] ; IS__CGSCC____: end: ; IS__CGSCC____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to i32*), [[FALSEBB]] ] ; IS__CGSCC____-NEXT: store i32 0, i32* [[PTR]], align 32 ; IS__CGSCC____-NEXT: ret void ; br i1 %c, label %truebb, label %falsebb truebb: br label %end falsebb: br label %end end: %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 160 to i32*), %falsebb ] store i32 0, i32* %ptr ret void } define void @test13-3(i1 %c, i32* align 32 %dst) { ; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test13-3 ; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) #[[ATTR8]] { ; IS__TUNIT____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] ; IS__TUNIT____: truebb: ; IS__TUNIT____-NEXT: br label [[END:%.*]] ; IS__TUNIT____: falsebb: ; IS__TUNIT____-NEXT: br label [[END]] ; IS__TUNIT____: end: ; IS__TUNIT____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to i32*), [[FALSEBB]] ] ; IS__TUNIT____-NEXT: store i32 0, i32* [[PTR]], align 32 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test13-3 ; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) #[[ATTR9]] { ; IS__CGSCC____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] ; IS__CGSCC____: truebb: ; IS__CGSCC____-NEXT: br label [[END:%.*]] ; IS__CGSCC____: falsebb: ; IS__CGSCC____-NEXT: br label [[END]] ; IS__CGSCC____: end: ; IS__CGSCC____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to i32*), [[FALSEBB]] ] ; IS__CGSCC____-NEXT: store i32 0, i32* [[PTR]], align 32 ; IS__CGSCC____-NEXT: ret void ; br i1 %c, label %truebb, label %falsebb truebb: br label %end falsebb: br label %end end: %ptr = phi i32* [ %dst, %truebb ], [ inttoptr (i64 128 to i32*), %falsebb ] store i32 0, i32* %ptr ret void } ; Don't crash on ptr2int/int2ptr uses. define i64 @ptr2int(i32* %p) { ; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr2int ; IS__TUNIT____-SAME: (i32* nofree readnone [[P:%.*]]) #[[ATTR9]] { ; IS__TUNIT____-NEXT: [[P2I:%.*]] = ptrtoint i32* [[P]] to i64 ; IS__TUNIT____-NEXT: ret i64 [[P2I]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr2int ; IS__CGSCC____-SAME: (i32* nofree readnone [[P:%.*]]) #[[ATTR10:[0-9]+]] { ; IS__CGSCC____-NEXT: [[P2I:%.*]] = ptrtoint i32* [[P]] to i64 ; IS__CGSCC____-NEXT: ret i64 [[P2I]] ; %p2i = ptrtoint i32* %p to i64 ret i64 %p2i } define i64* @int2ptr(i64 %i) { ; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@int2ptr ; IS__TUNIT____-SAME: (i64 [[I:%.*]]) #[[ATTR9]] { ; IS__TUNIT____-NEXT: [[I2P:%.*]] = inttoptr i64 [[I]] to i64* ; IS__TUNIT____-NEXT: ret i64* [[I2P]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@int2ptr ; IS__CGSCC____-SAME: (i64 [[I:%.*]]) #[[ATTR10]] { ; IS__CGSCC____-NEXT: [[I2P:%.*]] = inttoptr i64 [[I]] to i64* ; IS__CGSCC____-NEXT: ret i64* [[I2P]] ; %i2p = inttoptr i64 %i to i64* ret i64* %i2p } ; Use the store alignment only for the pointer operand. define void @aligned_store(i8* %Value, i8** %Ptr) { ; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@aligned_store ; IS__TUNIT____-SAME: (i8* nofree writeonly [[VALUE:%.*]], i8** nocapture nofree noundef nonnull writeonly align 32 dereferenceable(8) [[PTR:%.*]]) #[[ATTR5]] { ; IS__TUNIT____-NEXT: store i8* [[VALUE]], i8** [[PTR]], align 32 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@aligned_store ; IS__CGSCC____-SAME: (i8* nofree writeonly [[VALUE:%.*]], i8** nocapture nofree noundef nonnull writeonly align 32 dereferenceable(8) [[PTR:%.*]]) #[[ATTR6]] { ; IS__CGSCC____-NEXT: store i8* [[VALUE]], i8** [[PTR]], align 32 ; IS__CGSCC____-NEXT: ret void ; store i8* %Value, i8** %Ptr, align 32 ret void } declare i8* @some_func(i8*) define void @align_call_op_not_store(i8* align 2048 %arg) { ; CHECK-LABEL: define {{[^@]+}}@align_call_op_not_store ; CHECK-SAME: (i8* align 2048 [[ARG:%.*]]) { ; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @some_func(i8* align 2048 [[ARG]]) ; CHECK-NEXT: store i8 0, i8* [[UNKNOWN]], align 1 ; CHECK-NEXT: ret void ; %unknown = call i8* @some_func(i8* %arg) store i8 0, i8* %unknown ret void } define void @align_store_after_bc(i32* align 2048 %arg) { ; ; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@align_store_after_bc ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 2048 dereferenceable(1) [[ARG:%.*]]) #[[ATTR5]] { ; IS__TUNIT____-NEXT: [[BC:%.*]] = bitcast i32* [[ARG]] to i8* ; IS__TUNIT____-NEXT: store i8 0, i8* [[BC]], align 2048 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@align_store_after_bc ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 2048 dereferenceable(1) [[ARG:%.*]]) #[[ATTR6]] { ; IS__CGSCC____-NEXT: [[BC:%.*]] = bitcast i32* [[ARG]] to i8* ; IS__CGSCC____-NEXT: store i8 0, i8* [[BC]], align 2048 ; IS__CGSCC____-NEXT: ret void ; %bc = bitcast i32* %arg to i8* store i8 0, i8* %bc ret void } ; Make sure we do not annotate the callee of a must-tail call with an alignment ; we cannot also put on the caller. @cnd = external global i1 define i32 @musttail_callee_1(i32* %p) { ; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@musttail_callee_1 ; IS__TUNIT____-SAME: (i32* nocapture nofree noundef nonnull readonly dereferenceable(4) [[P:%.*]]) #[[ATTR4]] { ; IS__TUNIT____-NEXT: [[V:%.*]] = load i32, i32* [[P]], align 32 ; IS__TUNIT____-NEXT: ret i32 [[V]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@musttail_callee_1 ; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull readonly dereferenceable(4) [[P:%.*]]) #[[ATTR5]] { ; IS__CGSCC____-NEXT: [[V:%.*]] = load i32, i32* [[P]], align 32 ; IS__CGSCC____-NEXT: ret i32 [[V]] ; %v = load i32, i32* %p, align 32 ret i32 %v } define i32 @musttail_caller_1(i32* %p) { ; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@musttail_caller_1 ; IS__TUNIT____-SAME: (i32* nocapture nofree readonly [[P:%.*]]) #[[ATTR10:[0-9]+]] { ; IS__TUNIT____-NEXT: [[C:%.*]] = load i1, i1* @cnd, align 1 ; IS__TUNIT____-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] ; IS__TUNIT____: mt: ; IS__TUNIT____-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(i32* nocapture nofree readonly [[P]]) #[[ATTR11:[0-9]+]] ; IS__TUNIT____-NEXT: ret i32 [[V]] ; IS__TUNIT____: exit: ; IS__TUNIT____-NEXT: ret i32 0 ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@musttail_caller_1 ; IS__CGSCC____-SAME: (i32* nocapture nofree readonly [[P:%.*]]) #[[ATTR11:[0-9]+]] { ; IS__CGSCC____-NEXT: [[C:%.*]] = load i1, i1* @cnd, align 1 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] ; IS__CGSCC____: mt: ; IS__CGSCC____-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(i32* nocapture nofree noundef nonnull readonly dereferenceable(4) [[P]]) #[[ATTR14:[0-9]+]] ; IS__CGSCC____-NEXT: ret i32 [[V]] ; IS__CGSCC____: exit: ; IS__CGSCC____-NEXT: ret i32 0 ; %c = load i1, i1* @cnd br i1 %c, label %mt, label %exit mt: %v = musttail call i32 @musttail_callee_1(i32* %p) ret i32 %v exit: ret i32 0 } define i32* @checkAndAdvance(i32* align(16) %p) { ; IS__TUNIT____: Function Attrs: nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@checkAndAdvance ; IS__TUNIT____-SAME: (i32* noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR2]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 16 ; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 ; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] ; IS__TUNIT____: if.then: ; IS__TUNIT____-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 4 ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @checkAndAdvance(i32* nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: return: ; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[ADD_PTR]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ] ; IS__TUNIT____-NEXT: call void @user_i32_ptr(i32* noalias nocapture nonnull readnone align 16 [[RETVAL_0]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: ret i32* [[RETVAL_0]] ; ; IS__CGSCC____: Function Attrs: nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@checkAndAdvance ; IS__CGSCC____-SAME: (i32* noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 16 ; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 ; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] ; IS__CGSCC____: if.then: ; IS__CGSCC____-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 4 ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @checkAndAdvance(i32* nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR3]] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: return: ; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[ADD_PTR]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ] ; IS__CGSCC____-NEXT: call void @user_i32_ptr(i32* noalias nocapture nonnull readnone align 16 [[RETVAL_0]]) #[[ATTR3]] ; IS__CGSCC____-NEXT: ret i32* [[RETVAL_0]] ; entry: %0 = load i32, i32* %p, align 4 %cmp = icmp eq i32 %0, 0 br i1 %cmp, label %if.then, label %return if.then: ; preds = %entry %add.ptr = getelementptr inbounds i32, i32* %p, i64 4 %call = call i32* @checkAndAdvance(i32* nonnull %add.ptr) br label %return return: ; preds = %entry, %if.then %retval.0 = phi i32* [ %call, %if.then ], [ %p, %entry ] call void @user_i32_ptr(i32* %retval.0) ret i32* %retval.0 } ; FIXME: align 4 should not be propagated to the caller's p unless there is noundef define void @align4_caller(i8* %p) { ; CHECK-LABEL: define {{[^@]+}}@align4_caller ; CHECK-SAME: (i8* align 4 [[P:%.*]]) { ; CHECK-NEXT: call void @align4_callee(i8* align 4 [[P]]) ; CHECK-NEXT: ret void ; call void @align4_callee(i8* %p) ret void } declare void @align4_callee(i8* align(4) %p) @G = global i8 0, align 32 define internal i8* @aligned_8_return(i8* %a, i1 %c1, i1 %c2) norecurse { ; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@aligned_8_return ; IS__TUNIT____-SAME: (i8* noalias nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR9]] { ; IS__TUNIT____-NEXT: [[STACK:%.*]] = alloca i8*, align 8 ; IS__TUNIT____-NEXT: br i1 [[C1]], label [[T:%.*]], label [[F:%.*]] ; IS__TUNIT____: t: ; IS__TUNIT____-NEXT: [[GEP:%.*]] = getelementptr i8, i8* @G, i32 8 ; IS__TUNIT____-NEXT: [[SEL:%.*]] = select i1 [[C2]], i8* [[A]], i8* [[GEP]] ; IS__TUNIT____-NEXT: store i8* [[SEL]], i8** [[STACK]], align 8 ; IS__TUNIT____-NEXT: br label [[END:%.*]] ; IS__TUNIT____: f: ; IS__TUNIT____-NEXT: store i8* @G, i8** [[STACK]], align 8 ; IS__TUNIT____-NEXT: br label [[END]] ; IS__TUNIT____: end: ; IS__TUNIT____-NEXT: [[L:%.*]] = load i8*, i8** [[STACK]], align 8 ; IS__TUNIT____-NEXT: ret i8* [[L]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@aligned_8_return ; IS__CGSCC____-SAME: (i8* noalias nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR10]] { ; IS__CGSCC____-NEXT: [[STACK:%.*]] = alloca i8*, align 8 ; IS__CGSCC____-NEXT: br i1 [[C1]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: t: ; IS__CGSCC____-NEXT: [[GEP:%.*]] = getelementptr i8, i8* @G, i32 8 ; IS__CGSCC____-NEXT: [[SEL:%.*]] = select i1 [[C2]], i8* [[A]], i8* [[GEP]] ; IS__CGSCC____-NEXT: store i8* [[SEL]], i8** [[STACK]], align 8 ; IS__CGSCC____-NEXT: br label [[END:%.*]] ; IS__CGSCC____: f: ; IS__CGSCC____-NEXT: store i8* @G, i8** [[STACK]], align 8 ; IS__CGSCC____-NEXT: br label [[END]] ; IS__CGSCC____: end: ; IS__CGSCC____-NEXT: [[L:%.*]] = load i8*, i8** [[STACK]], align 8 ; IS__CGSCC____-NEXT: ret i8* [[L]] ; %stack = alloca i8* br i1 %c1, label %t, label %f t: %gep = getelementptr i8, i8* @G, i32 8 %sel = select i1 %c2, i8* %a, i8* %gep store i8* %sel, i8** %stack br label %end f: store i8* @G, i8** %stack br label %end end: %l = load i8*, i8** %stack ret i8* %l } define i8* @aligned_8_return_caller(i8* align(16) %a, i1 %c1, i1 %c2) { ; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@aligned_8_return_caller ; IS__TUNIT____-SAME: (i8* nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR9]] { ; IS__TUNIT____-NEXT: [[R:%.*]] = call align 8 i8* @aligned_8_return(i8* noalias nofree readnone align 16 "no-capture-maybe-returned" [[A]], i1 [[C1]], i1 [[C2]]) #[[ATTR12:[0-9]+]] ; IS__TUNIT____-NEXT: ret i8* [[R]] ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@aligned_8_return_caller ; IS__CGSCC____-SAME: (i8* nofree readnone align 16 [[A:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR12:[0-9]+]] { ; IS__CGSCC____-NEXT: [[R:%.*]] = call align 8 i8* @aligned_8_return(i8* noalias nofree readnone align 16 [[A]], i1 [[C1]], i1 [[C2]]) #[[ATTR13:[0-9]+]] ; IS__CGSCC____-NEXT: ret i8* [[R]] ; %r = call i8* @aligned_8_return(i8* %a, i1 %c1, i1 %c2) ret i8* %r } attributes #0 = { nounwind uwtable noinline } attributes #1 = { uwtable noinline } attributes #2 = { null_pointer_is_valid } ;. ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable } ; IS__TUNIT____: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone willreturn uwtable } ; IS__TUNIT____: attributes #[[ATTR2]] = { nounwind } ; IS__TUNIT____: attributes #[[ATTR3]] = { nofree nosync nounwind } ; IS__TUNIT____: attributes #[[ATTR4]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__TUNIT____: attributes #[[ATTR5]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } ; IS__TUNIT____: attributes #[[ATTR6]] = { nounwind willreturn } ; IS__TUNIT____: attributes #[[ATTR7]] = { argmemonly nofree noinline norecurse nosync nounwind willreturn writeonly uwtable } ; IS__TUNIT____: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__TUNIT____: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__TUNIT____: attributes #[[ATTR10]] = { nofree norecurse nosync nounwind readonly willreturn } ; IS__TUNIT____: attributes #[[ATTR11]] = { nofree nosync nounwind readonly willreturn } ; IS__TUNIT____: attributes #[[ATTR12]] = { nofree nosync nounwind readnone willreturn } ;. ; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable } ; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone willreturn uwtable } ; IS__CGSCC_OPM: attributes #[[ATTR2]] = { noinline nounwind uwtable } ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nounwind } ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nofree nosync nounwind } ; IS__CGSCC_OPM: attributes #[[ATTR5]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR6]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nounwind willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR8]] = { argmemonly nofree noinline norecurse nosync nounwind willreturn writeonly uwtable } ; IS__CGSCC_OPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR10]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR11]] = { nofree nosync nounwind readonly willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR12]] = { nofree nosync nounwind readnone willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR13]] = { readnone willreturn } ; IS__CGSCC_OPM: attributes #[[ATTR14]] = { readonly willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { noinline nounwind uwtable } ; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree noinline nosync nounwind readnone willreturn uwtable } ; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nounwind } ; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nofree nosync nounwind } ; IS__CGSCC_NPM: attributes #[[ATTR5]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR6]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR7]] = { nounwind willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR8]] = { argmemonly nofree noinline norecurse nosync nounwind willreturn writeonly uwtable } ; IS__CGSCC_NPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR10]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR11]] = { nofree nosync nounwind readonly willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR12]] = { nofree nosync nounwind readnone willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR13]] = { readnone willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR14]] = { readonly willreturn } ;.