| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals | |
| ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT | |
| ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC | |
| 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 = common global i8 0, align 8 | |
| ; CHECK: @a2 = common global i8 0, align 16 | |
| ; CHECK: @cnd = external global i1 | |
| ; CHECK: @G = global i8 0, align 32 | |
| ;. | |
| define ptr @test1(ptr align 8 %0) #0 { | |
| ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CHECK-LABEL: define {{[^@]+}}@test1 | |
| ; CHECK-SAME: (ptr nofree readnone returned align 8 "no-capture-maybe-returned" [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { | |
| ; CHECK-NEXT: ret ptr [[TMP0]] | |
| ; | |
| ret ptr %0 | |
| } | |
| ; TEST 2 | |
| define ptr @test2(ptr %0) #0 { | |
| ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CHECK-LABEL: define {{[^@]+}}@test2 | |
| ; CHECK-SAME: (ptr nofree readnone returned "no-capture-maybe-returned" [[TMP0:%.*]]) #[[ATTR0]] { | |
| ; CHECK-NEXT: ret ptr [[TMP0]] | |
| ; | |
| ret ptr %0 | |
| } | |
| ; TEST 3 | |
| define ptr @test3(ptr align 8 %0, ptr align 4 %1, i1 %2) #0 { | |
| ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CHECK-LABEL: define {{[^@]+}}@test3 | |
| ; CHECK-SAME: (ptr nofree readnone align 8 "no-capture-maybe-returned" [[TMP0:%.*]], ptr nofree readnone align 4 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) #[[ATTR0]] { | |
| ; CHECK-NEXT: [[RET:%.*]] = select i1 [[TMP2]], ptr [[TMP0]], ptr [[TMP1]] | |
| ; CHECK-NEXT: ret ptr [[RET]] | |
| ; | |
| %ret = select i1 %2, ptr %0, ptr %1 | |
| ret ptr %ret | |
| } | |
| ; TEST 4 | |
| define ptr @test4(ptr align 32 %0, ptr align 32 %1, i1 %2) #0 { | |
| ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CHECK-LABEL: define {{[^@]+}}@test4 | |
| ; CHECK-SAME: (ptr nofree readnone align 32 "no-capture-maybe-returned" [[TMP0:%.*]], ptr nofree readnone align 32 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) #[[ATTR0]] { | |
| ; CHECK-NEXT: [[RET:%.*]] = select i1 [[TMP2]], ptr [[TMP0]], ptr [[TMP1]] | |
| ; CHECK-NEXT: ret ptr [[RET]] | |
| ; | |
| %ret = select i1 %2, ptr %0, ptr %1 | |
| ret ptr %ret | |
| } | |
| ; TEST 5 | |
| declare ptr @unknown() | |
| declare align 8 ptr @align8() | |
| define ptr @test5_1() { | |
| ; CHECK-LABEL: define {{[^@]+}}@test5_1() { | |
| ; CHECK-NEXT: [[RET:%.*]] = tail call align 8 ptr @unknown() | |
| ; CHECK-NEXT: ret ptr [[RET]] | |
| ; | |
| %ret = tail call align 8 ptr @unknown() | |
| ret ptr %ret | |
| } | |
| define ptr @test5_2() { | |
| ; CHECK-LABEL: define {{[^@]+}}@test5_2() { | |
| ; CHECK-NEXT: [[RET:%.*]] = tail call align 8 ptr @align8() | |
| ; CHECK-NEXT: ret ptr [[RET]] | |
| ; | |
| %ret = tail call ptr @align8() | |
| ret ptr %ret | |
| } | |
| ; TEST 6 | |
| ; SCC | |
| define ptr @test6_1() #0 { | |
| ; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable | |
| ; TUNIT-LABEL: define {{[^@]+}}@test6_1 | |
| ; TUNIT-SAME: () #[[ATTR1:[0-9]+]] { | |
| ; TUNIT-NEXT: ret ptr undef | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@test6_1 | |
| ; CGSCC-SAME: () #[[ATTR0]] { | |
| ; CGSCC-NEXT: ret ptr undef | |
| ; | |
| %ret = tail call ptr @test6_2() | |
| ret ptr %ret | |
| } | |
| define ptr @test6_2() #0 { | |
| ; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable | |
| ; TUNIT-LABEL: define {{[^@]+}}@test6_2 | |
| ; TUNIT-SAME: () #[[ATTR1]] { | |
| ; TUNIT-NEXT: ret ptr undef | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@test6_2 | |
| ; CGSCC-SAME: () #[[ATTR0]] { | |
| ; CGSCC-NEXT: ret ptr undef | |
| ; | |
| %ret = tail call ptr @test6_1() | |
| ret ptr %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 ptr @f1(ptr readnone %0) local_unnamed_addr #0 { | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@f1 | |
| ; CGSCC-SAME: () local_unnamed_addr #[[ATTR0]] { | |
| ; CGSCC-NEXT: br label [[TMP2:%.*]] | |
| ; CGSCC: 1: | |
| ; CGSCC-NEXT: unreachable | |
| ; CGSCC: 2: | |
| ; CGSCC-NEXT: ret ptr @a1 | |
| ; | |
| %2 = icmp eq ptr %0, null | |
| br i1 %2, label %3, label %5 | |
| ; <label>:3: ; preds = %1 | |
| %4 = tail call ptr @f2(ptr nonnull @a1) | |
| %l = load i8, ptr %4 | |
| br label %5 | |
| ; <label>:5: ; preds = %1, %3 | |
| %6 = phi ptr [ %4, %3 ], [ %0, %1 ] | |
| ret ptr %6 | |
| } | |
| ; Function Attrs: nounwind readnone ssp uwtable | |
| define ptr @f2(ptr readnone %0) local_unnamed_addr #0 { | |
| ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; TUNIT-LABEL: define {{[^@]+}}@f2 | |
| ; TUNIT-SAME: (ptr nofree readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { | |
| ; TUNIT-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null | |
| ; TUNIT-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] | |
| ; TUNIT: 3: | |
| ; TUNIT-NEXT: br label [[TMP5:%.*]] | |
| ; TUNIT: 4: | |
| ; TUNIT-NEXT: br label [[TMP5]] | |
| ; TUNIT: 5: | |
| ; TUNIT-NEXT: [[TMP6:%.*]] = phi ptr [ [[TMP0]], [[TMP3]] ], [ @a1, [[TMP4]] ] | |
| ; TUNIT-NEXT: ret ptr [[TMP6]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@f2 | |
| ; CGSCC-SAME: (ptr nofree readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { | |
| ; CGSCC-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null | |
| ; CGSCC-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] | |
| ; CGSCC: 3: | |
| ; CGSCC-NEXT: br label [[TMP5:%.*]] | |
| ; CGSCC: 4: | |
| ; CGSCC-NEXT: br label [[TMP5]] | |
| ; CGSCC: 5: | |
| ; CGSCC-NEXT: [[TMP6:%.*]] = phi ptr [ [[TMP0]], [[TMP3]] ], [ @a1, [[TMP4]] ] | |
| ; CGSCC-NEXT: ret ptr [[TMP6]] | |
| ; | |
| %2 = icmp eq ptr %0, null | |
| br i1 %2, label %5, label %3 | |
| ; <label>:3: ; preds = %1 | |
| %4 = tail call ptr @f1(ptr nonnull %0) | |
| br label %7 | |
| ; <label>:5: ; preds = %1 | |
| %6 = tail call ptr @f3(ptr nonnull @a2) | |
| br label %7 | |
| ; <label>:7: ; preds = %5, %3 | |
| %8 = phi ptr [ %4, %3 ], [ %6, %5 ] | |
| ret ptr %8 | |
| } | |
| ; Function Attrs: nounwind readnone ssp uwtable | |
| define internal ptr @f3(ptr readnone %0) local_unnamed_addr #0 { | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@f3 | |
| ; CGSCC-SAME: () local_unnamed_addr #[[ATTR0]] { | |
| ; CGSCC-NEXT: br label [[TMP2:%.*]] | |
| ; CGSCC: 1: | |
| ; CGSCC-NEXT: unreachable | |
| ; CGSCC: 2: | |
| ; CGSCC-NEXT: ret ptr undef | |
| ; | |
| %2 = icmp eq ptr %0, null | |
| br i1 %2, label %3, label %5 | |
| ; <label>:3: ; preds = %1 | |
| %4 = tail call ptr @f1(ptr nonnull @a2) | |
| br label %5 | |
| ; <label>:5: ; preds = %1, %3 | |
| %6 = phi ptr [ %4, %3 ], [ @a1, %1 ] | |
| ret ptr %6 | |
| } | |
| ; TEST 7 | |
| ; Better than IR information | |
| define align 4 ptr @test7() #0 { | |
| ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; TUNIT-LABEL: define {{[^@]+}}@test7 | |
| ; TUNIT-SAME: () #[[ATTR0]] { | |
| ; TUNIT-NEXT: ret ptr @a1 | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@test7 | |
| ; CGSCC-SAME: () #[[ATTR1:[0-9]+]] { | |
| ; CGSCC-NEXT: [[C:%.*]] = tail call noundef nonnull align 8 dereferenceable(1) ptr @f1() #[[ATTR15:[0-9]+]] | |
| ; CGSCC-NEXT: ret ptr [[C]] | |
| ; | |
| %c = tail call ptr @f1(ptr align 8 dereferenceable(1) @a1) | |
| ret ptr %c | |
| } | |
| ; TEST 7b | |
| ; Function Attrs: nounwind readnone ssp uwtable | |
| define internal ptr @f1b(ptr readnone %0) local_unnamed_addr #0 { | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@f1b | |
| ; CGSCC-SAME: () local_unnamed_addr #[[ATTR0]] { | |
| ; CGSCC-NEXT: br label [[TMP2:%.*]] | |
| ; CGSCC: 1: | |
| ; CGSCC-NEXT: unreachable | |
| ; CGSCC: 2: | |
| ; CGSCC-NEXT: ret ptr undef | |
| ; | |
| %2 = icmp eq ptr %0, null | |
| br i1 %2, label %3, label %5 | |
| ; <label>:3: ; preds = %1 | |
| %4 = tail call ptr @f2b(ptr nonnull @a1) | |
| %l = load i8, ptr %4 | |
| store i8 %l, ptr @a1 | |
| br label %5 | |
| ; <label>:5: ; preds = %1, %3 | |
| %6 = phi ptr [ %4, %3 ], [ %0, %1 ] | |
| ret ptr %6 | |
| } | |
| ; Function Attrs: nounwind readnone ssp uwtable | |
| define internal ptr @f2b(ptr readnone %0) local_unnamed_addr #0 { | |
| ; | |
| ; CGSCC: Function Attrs: noinline nounwind uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@f2b | |
| ; CGSCC-SAME: (ptr readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { | |
| ; CGSCC-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null | |
| ; CGSCC-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] | |
| ; CGSCC: 3: | |
| ; CGSCC-NEXT: [[TMP4:%.*]] = tail call ptr @f1b() | |
| ; CGSCC-NEXT: br label [[TMP7:%.*]] | |
| ; CGSCC: 5: | |
| ; CGSCC-NEXT: [[TMP6:%.*]] = tail call ptr @f3b() | |
| ; CGSCC-NEXT: br label [[TMP7]] | |
| ; CGSCC: 7: | |
| ; CGSCC-NEXT: [[TMP8:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ] | |
| ; CGSCC-NEXT: ret ptr [[TMP8]] | |
| ; | |
| %2 = icmp eq ptr %0, null | |
| br i1 %2, label %5, label %3 | |
| ; <label>:3: ; preds = %1 | |
| %4 = tail call ptr @f1b(ptr nonnull %0) | |
| br label %7 | |
| ; <label>:5: ; preds = %1 | |
| %6 = tail call ptr @f3b(ptr nonnull @a2) | |
| br label %7 | |
| ; <label>:7: ; preds = %5, %3 | |
| %8 = phi ptr [ %4, %3 ], [ %6, %5 ] | |
| ret ptr %8 | |
| } | |
| ; Function Attrs: nounwind readnone ssp uwtable | |
| define internal ptr @f3b(ptr readnone %0) local_unnamed_addr #0 { | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@f3b | |
| ; CGSCC-SAME: () local_unnamed_addr #[[ATTR0]] { | |
| ; CGSCC-NEXT: br label [[TMP2:%.*]] | |
| ; CGSCC: 1: | |
| ; CGSCC-NEXT: unreachable | |
| ; CGSCC: 2: | |
| ; CGSCC-NEXT: ret ptr @a1 | |
| ; | |
| %2 = icmp eq ptr %0, null | |
| br i1 %2, label %3, label %5 | |
| ; <label>:3: ; preds = %1 | |
| %4 = tail call ptr @f1b(ptr nonnull @a2) | |
| br label %5 | |
| ; <label>:5: ; preds = %1, %3 | |
| %6 = phi ptr [ %4, %3 ], [ @a1, %1 ] | |
| ret ptr %6 | |
| } | |
| define align 4 ptr @test7b(ptr align 32 %p) #0 { | |
| ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable | |
| ; TUNIT-LABEL: define {{[^@]+}}@test7b | |
| ; TUNIT-SAME: (ptr nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR0]] { | |
| ; TUNIT-NEXT: ret ptr [[P]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@test7b | |
| ; CGSCC-SAME: (ptr nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] { | |
| ; CGSCC-NEXT: ret ptr [[P]] | |
| ; | |
| tail call ptr @f1b(ptr align 8 dereferenceable(1) @a1) | |
| ret ptr %p | |
| } | |
| ; TEST 8 | |
| define void @test8_helper() { | |
| ; TUNIT-LABEL: define {{[^@]+}}@test8_helper() { | |
| ; TUNIT-NEXT: [[PTR0:%.*]] = tail call ptr @unknown() | |
| ; TUNIT-NEXT: [[PTR1:%.*]] = tail call align 4 ptr @unknown() | |
| ; TUNIT-NEXT: [[PTR2:%.*]] = tail call align 8 ptr @unknown() | |
| ; TUNIT-NEXT: tail call void @test8(ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone captures(none) [[PTR0]]) #[[ATTR2:[0-9]+]] | |
| ; TUNIT-NEXT: tail call void @test8(ptr noalias nofree readnone align 8 captures(none) [[PTR2]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]]) #[[ATTR2]] | |
| ; TUNIT-NEXT: tail call void @test8(ptr noalias nofree readnone align 8 captures(none) [[PTR2]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]]) #[[ATTR2]] | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC-LABEL: define {{[^@]+}}@test8_helper() { | |
| ; CGSCC-NEXT: [[PTR0:%.*]] = tail call ptr @unknown() | |
| ; CGSCC-NEXT: [[PTR1:%.*]] = tail call align 4 ptr @unknown() | |
| ; CGSCC-NEXT: [[PTR2:%.*]] = tail call align 8 ptr @unknown() | |
| ; CGSCC-NEXT: tail call void @test8(ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone captures(none) [[PTR0]]) #[[ATTR3:[0-9]+]] | |
| ; CGSCC-NEXT: tail call void @test8(ptr noalias nofree readnone align 8 captures(none) [[PTR2]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]]) #[[ATTR3]] | |
| ; CGSCC-NEXT: tail call void @test8(ptr noalias nofree readnone align 8 captures(none) [[PTR2]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]], ptr noalias nofree readnone align 4 captures(none) [[PTR1]]) #[[ATTR3]] | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| %ptr0 = tail call ptr @unknown() | |
| %ptr1 = tail call align 4 ptr @unknown() | |
| %ptr2 = tail call align 8 ptr @unknown() | |
| tail call void @test8(ptr %ptr1, ptr %ptr1, ptr %ptr0) | |
| tail call void @test8(ptr %ptr2, ptr %ptr1, ptr %ptr1) | |
| tail call void @test8(ptr %ptr2, ptr %ptr1, ptr %ptr1) | |
| ret void | |
| } | |
| declare void @user_i32_ptr(ptr nocapture readnone) nounwind | |
| define internal void @test8(ptr %a, ptr %b, ptr %c) { | |
| ; TUNIT: Function Attrs: nounwind | |
| ; TUNIT-LABEL: define {{[^@]+}}@test8 | |
| ; TUNIT-SAME: (ptr noalias nofree readnone align 4 captures(none) [[A:%.*]], ptr noalias nofree readnone align 4 captures(none) [[B:%.*]], ptr noalias nofree readnone captures(none) [[C:%.*]]) #[[ATTR2]] { | |
| ; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nofree readnone align 4 captures(none) [[A]]) #[[ATTR2]] | |
| ; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nofree readnone align 4 captures(none) [[B]]) #[[ATTR2]] | |
| ; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nofree readnone captures(none) [[C]]) #[[ATTR2]] | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: nounwind | |
| ; CGSCC-LABEL: define {{[^@]+}}@test8 | |
| ; CGSCC-SAME: (ptr noalias nofree readnone align 4 captures(none) [[A:%.*]], ptr noalias nofree readnone align 4 captures(none) [[B:%.*]], ptr noalias nofree readnone captures(none) [[C:%.*]]) #[[ATTR3]] { | |
| ; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nofree readnone align 4 captures(none) [[A]]) #[[ATTR3]] | |
| ; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nofree readnone align 4 captures(none) [[B]]) #[[ATTR3]] | |
| ; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nofree readnone captures(none) [[C]]) #[[ATTR3]] | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| call void @user_i32_ptr(ptr %a) | |
| call void @user_i32_ptr(ptr %b) | |
| call void @user_i32_ptr(ptr %c) | |
| ret void | |
| } | |
| declare void @test9_helper(ptr %A) | |
| define void @test9_traversal(i1 %cnd, ptr align 4 %B, ptr align 8 %C) { | |
| ; CHECK-LABEL: define {{[^@]+}}@test9_traversal | |
| ; CHECK-SAME: (i1 [[CND:%.*]], ptr align 4 [[B:%.*]], ptr align 8 [[C:%.*]]) { | |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CND]], ptr [[B]], ptr [[C]] | |
| ; CHECK-NEXT: call void @test9_helper(ptr align 4 [[SEL]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %sel = select i1 %cnd, ptr %B, ptr %C | |
| call void @test9_helper(ptr %sel) | |
| ret void | |
| } | |
| ; FIXME: This will work with an upcoming patch (D66618 or similar) | |
| ; define align 32 ptr @test10a(ptr align 32 "no-capture-maybe-returned" %p) | |
| ; FIXME: This will work with an upcoming patch (D66618 or similar) | |
| ; store i32 1, ptr %r, align 32 | |
| ; FIXME: This will work with an upcoming patch (D66618 or similar) | |
| ; store i32 -1, ptr %g1, align 32 | |
| define ptr @test10a(ptr align 32 %p) { | |
| ; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: readwrite) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test10a | |
| ; TUNIT-SAME: (ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3:[0-9]+]] { | |
| ; TUNIT-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 32 | |
| ; TUNIT-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 | |
| ; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] | |
| ; TUNIT: t: | |
| ; TUNIT-NEXT: [[R:%.*]] = call align 32 ptr @test10a(ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR13:[0-9]+]] | |
| ; TUNIT-NEXT: store i32 1, ptr [[R]], align 32 | |
| ; TUNIT-NEXT: [[G0:%.*]] = getelementptr i32, ptr [[P]], i32 8 | |
| ; TUNIT-NEXT: br label [[E:%.*]] | |
| ; TUNIT: f: | |
| ; TUNIT-NEXT: [[G1:%.*]] = getelementptr i32, ptr [[P]], i32 8 | |
| ; TUNIT-NEXT: store i32 -1, ptr [[G1]], align 32 | |
| ; TUNIT-NEXT: br label [[E]] | |
| ; TUNIT: e: | |
| ; TUNIT-NEXT: [[PHI:%.*]] = phi ptr [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] | |
| ; TUNIT-NEXT: ret ptr [[PHI]] | |
| ; | |
| ; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: readwrite) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test10a | |
| ; CGSCC-SAME: (ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4:[0-9]+]] { | |
| ; CGSCC-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 32 | |
| ; CGSCC-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 | |
| ; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] | |
| ; CGSCC: t: | |
| ; CGSCC-NEXT: [[R:%.*]] = call align 32 ptr @test10a(ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR16:[0-9]+]] | |
| ; CGSCC-NEXT: store i32 1, ptr [[R]], align 32 | |
| ; CGSCC-NEXT: [[G0:%.*]] = getelementptr i32, ptr [[P]], i32 8 | |
| ; CGSCC-NEXT: br label [[E:%.*]] | |
| ; CGSCC: f: | |
| ; CGSCC-NEXT: [[G1:%.*]] = getelementptr i32, ptr [[P]], i32 8 | |
| ; CGSCC-NEXT: store i32 -1, ptr [[G1]], align 32 | |
| ; CGSCC-NEXT: br label [[E]] | |
| ; CGSCC: e: | |
| ; CGSCC-NEXT: [[PHI:%.*]] = phi ptr [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] | |
| ; CGSCC-NEXT: ret ptr [[PHI]] | |
| ; | |
| %l = load i32, ptr %p | |
| %c = icmp eq i32 %l, 0 | |
| br i1 %c, label %t, label %f | |
| t: | |
| %r = call ptr @test10a(ptr %p) | |
| store i32 1, ptr %r | |
| %g0 = getelementptr i32, ptr %p, i32 8 | |
| br label %e | |
| f: | |
| %g1 = getelementptr i32, ptr %p, i32 8 | |
| store i32 -1, ptr %g1 | |
| br label %e | |
| e: | |
| %phi = phi ptr [%g0, %t], [%g1, %f] | |
| ret ptr %phi | |
| } | |
| ; FIXME: This will work with an upcoming patch (D66618 or similar) | |
| ; define align 32 ptr @test10b(ptr align 32 "no-capture-maybe-returned" %p) | |
| ; FIXME: This will work with an upcoming patch (D66618 or similar) | |
| ; store i32 1, ptr %r, align 32 | |
| ; FIXME: This will work with an upcoming patch (D66618 or similar) | |
| ; store i32 -1, ptr %g1, align 32 | |
| define ptr @test10b(ptr align 32 %p) { | |
| ; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: readwrite) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test10b | |
| ; TUNIT-SAME: (ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3]] { | |
| ; TUNIT-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 32 | |
| ; TUNIT-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 | |
| ; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] | |
| ; TUNIT: t: | |
| ; TUNIT-NEXT: [[R:%.*]] = call align 32 ptr @test10b(ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR13]] | |
| ; TUNIT-NEXT: store i32 1, ptr [[R]], align 32 | |
| ; TUNIT-NEXT: [[G0:%.*]] = getelementptr i32, ptr [[P]], i32 8 | |
| ; TUNIT-NEXT: br label [[E:%.*]] | |
| ; TUNIT: f: | |
| ; TUNIT-NEXT: [[G1:%.*]] = getelementptr i32, ptr [[P]], i32 -8 | |
| ; TUNIT-NEXT: store i32 -1, ptr [[G1]], align 32 | |
| ; TUNIT-NEXT: br label [[E]] | |
| ; TUNIT: e: | |
| ; TUNIT-NEXT: [[PHI:%.*]] = phi ptr [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] | |
| ; TUNIT-NEXT: ret ptr [[PHI]] | |
| ; | |
| ; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: readwrite) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test10b | |
| ; CGSCC-SAME: (ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4]] { | |
| ; CGSCC-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 32 | |
| ; CGSCC-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 | |
| ; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] | |
| ; CGSCC: t: | |
| ; CGSCC-NEXT: [[R:%.*]] = call align 32 ptr @test10b(ptr nofree noundef nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) #[[ATTR16]] | |
| ; CGSCC-NEXT: store i32 1, ptr [[R]], align 32 | |
| ; CGSCC-NEXT: [[G0:%.*]] = getelementptr i32, ptr [[P]], i32 8 | |
| ; CGSCC-NEXT: br label [[E:%.*]] | |
| ; CGSCC: f: | |
| ; CGSCC-NEXT: [[G1:%.*]] = getelementptr i32, ptr [[P]], i32 -8 | |
| ; CGSCC-NEXT: store i32 -1, ptr [[G1]], align 32 | |
| ; CGSCC-NEXT: br label [[E]] | |
| ; CGSCC: e: | |
| ; CGSCC-NEXT: [[PHI:%.*]] = phi ptr [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] | |
| ; CGSCC-NEXT: ret ptr [[PHI]] | |
| ; | |
| %l = load i32, ptr %p | |
| %c = icmp eq i32 %l, 0 | |
| br i1 %c, label %t, label %f | |
| t: | |
| %r = call ptr @test10b(ptr %p) | |
| store i32 1, ptr %r | |
| %g0 = getelementptr i32, ptr %p, i32 8 | |
| br label %e | |
| f: | |
| %g1 = getelementptr i32, ptr %p, i32 -8 | |
| store i32 -1, ptr %g1 | |
| br label %e | |
| e: | |
| %phi = phi ptr [%g0, %t], [%g1, %f] | |
| ret ptr %phi | |
| } | |
| define i64 @test11(ptr %p) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test11 | |
| ; TUNIT-SAME: (ptr nofree nonnull readonly align 8 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR4:[0-9]+]] { | |
| ; TUNIT-NEXT: [[RET:%.*]] = load i64, ptr [[P]], align 8, !invariant.load [[META0:![0-9]+]] | |
| ; TUNIT-NEXT: ret i64 [[RET]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test11 | |
| ; CGSCC-SAME: (ptr nofree nonnull readonly align 8 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR5:[0-9]+]] { | |
| ; CGSCC-NEXT: [[RET:%.*]] = load i64, ptr [[P]], align 8, !invariant.load [[META0:![0-9]+]] | |
| ; CGSCC-NEXT: ret i64 [[RET]] | |
| ; | |
| %p-cast = bitcast ptr %p to ptr | |
| %ret = load i64, ptr %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(ptr align 4 %p) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test12-1 | |
| ; TUNIT-SAME: (ptr nofree readonly align 16 captures(none) [[P:%.*]]) #[[ATTR4]] { | |
| ; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; TUNIT-NEXT: [[RET:%.*]] = load i64, ptr [[ARRAYIDX1]], align 16, !invariant.load [[META0]] | |
| ; TUNIT-NEXT: ret i64 [[RET]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test12-1 | |
| ; CGSCC-SAME: (ptr nofree readonly align 16 captures(none) [[P:%.*]]) #[[ATTR5]] { | |
| ; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; CGSCC-NEXT: [[RET:%.*]] = load i64, ptr [[ARRAYIDX1]], align 16, !invariant.load [[META0]] | |
| ; CGSCC-NEXT: ret i64 [[RET]] | |
| ; | |
| %p-cast = bitcast ptr %p to ptr | |
| %arrayidx0 = getelementptr i64, ptr %p-cast, i64 1 | |
| %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 | |
| %ret = load i64, ptr %arrayidx1, align 16 | |
| ret i64 %ret | |
| } | |
| define i64 @test12-2(ptr align 4 %p) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test12-2 | |
| ; TUNIT-SAME: (ptr nofree nonnull readonly align 16 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR4]] { | |
| ; TUNIT-NEXT: [[RET:%.*]] = load i64, ptr [[P]], align 16, !invariant.load [[META0]] | |
| ; TUNIT-NEXT: ret i64 [[RET]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test12-2 | |
| ; CGSCC-SAME: (ptr nofree nonnull readonly align 16 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR5]] { | |
| ; CGSCC-NEXT: [[RET:%.*]] = load i64, ptr [[P]], align 16, !invariant.load [[META0]] | |
| ; CGSCC-NEXT: ret i64 [[RET]] | |
| ; | |
| %p-cast = bitcast ptr %p to ptr | |
| %ret = load i64, ptr %p-cast, align 16 | |
| ret i64 %ret | |
| } | |
| ; FXIME: %p should have nonnull | |
| define void @test12-3(ptr align 4 %p) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test12-3 | |
| ; TUNIT-SAME: (ptr nofree writeonly align 16 captures(none) [[P:%.*]]) #[[ATTR5:[0-9]+]] { | |
| ; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; TUNIT-NEXT: store i64 0, ptr [[ARRAYIDX1]], align 16 | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test12-3 | |
| ; CGSCC-SAME: (ptr nofree writeonly align 16 captures(none) [[P:%.*]]) #[[ATTR6:[0-9]+]] { | |
| ; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; CGSCC-NEXT: store i64 0, ptr [[ARRAYIDX1]], align 16 | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| %p-cast = bitcast ptr %p to ptr | |
| %arrayidx0 = getelementptr i64, ptr %p-cast, i64 1 | |
| %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 | |
| store i64 0, ptr %arrayidx1, align 16 | |
| ret void | |
| } | |
| define void @test12-4(ptr align 4 %p) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test12-4 | |
| ; TUNIT-SAME: (ptr nofree nonnull writeonly align 16 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR5]] { | |
| ; TUNIT-NEXT: store i64 0, ptr [[P]], align 16 | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test12-4 | |
| ; CGSCC-SAME: (ptr nofree nonnull writeonly align 16 captures(none) dereferenceable(8) [[P:%.*]]) #[[ATTR6]] { | |
| ; CGSCC-NEXT: store i64 0, ptr [[P]], align 16 | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| %p-cast = bitcast ptr %p to ptr | |
| store i64 0, ptr %p-cast, align 16 | |
| ret void | |
| } | |
| declare void @use(ptr) willreturn nounwind | |
| define void @test12-5(ptr align 4 %p) { | |
| ; TUNIT: Function Attrs: mustprogress nounwind willreturn | |
| ; TUNIT-LABEL: define {{[^@]+}}@test12-5 | |
| ; TUNIT-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR7:[0-9]+]] { | |
| ; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; TUNIT-NEXT: tail call void @use(ptr align 16 [[ARRAYIDX1]]) #[[ATTR6:[0-9]+]] | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nounwind willreturn | |
| ; CGSCC-LABEL: define {{[^@]+}}@test12-5 | |
| ; CGSCC-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR8:[0-9]+]] { | |
| ; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; CGSCC-NEXT: tail call void @use(ptr align 16 [[ARRAYIDX1]]) #[[ATTR7:[0-9]+]] | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| %p-cast = bitcast ptr %p to ptr | |
| %arrayidx0 = getelementptr i64, ptr %p-cast, i64 1 | |
| %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 | |
| tail call void @use(ptr align 16 %arrayidx1) | |
| ret void | |
| } | |
| define void @test12-6(ptr align 4 %p) { | |
| ; TUNIT: Function Attrs: mustprogress nounwind willreturn | |
| ; TUNIT-LABEL: define {{[^@]+}}@test12-6 | |
| ; TUNIT-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR7]] { | |
| ; TUNIT-NEXT: tail call void @use(ptr align 16 [[P]]) #[[ATTR6]] | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nounwind willreturn | |
| ; CGSCC-LABEL: define {{[^@]+}}@test12-6 | |
| ; CGSCC-SAME: (ptr align 16 [[P:%.*]]) #[[ATTR8]] { | |
| ; CGSCC-NEXT: tail call void @use(ptr align 16 [[P]]) #[[ATTR7]] | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| %p-cast = bitcast ptr %p to ptr | |
| tail call void @use(ptr align 16 %p-cast) | |
| ret void | |
| } | |
| define void @test13(i1 %c, ptr align 32 %dst) #0 { | |
| ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable | |
| ; TUNIT-LABEL: define {{[^@]+}}@test13 | |
| ; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR8:[0-9]+]] { | |
| ; TUNIT-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] | |
| ; TUNIT: truebb: | |
| ; TUNIT-NEXT: br label [[END:%.*]] | |
| ; TUNIT: falsebb: | |
| ; TUNIT-NEXT: br label [[END]] | |
| ; TUNIT: end: | |
| ; TUNIT-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] | |
| ; TUNIT-NEXT: store i32 0, ptr [[PTR]], align 32 | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable | |
| ; CGSCC-LABEL: define {{[^@]+}}@test13 | |
| ; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR9:[0-9]+]] { | |
| ; CGSCC-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] | |
| ; CGSCC: truebb: | |
| ; CGSCC-NEXT: br label [[END:%.*]] | |
| ; CGSCC: falsebb: | |
| ; CGSCC-NEXT: br label [[END]] | |
| ; CGSCC: end: | |
| ; CGSCC-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] | |
| ; CGSCC-NEXT: store i32 0, ptr [[PTR]], align 32 | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| br i1 %c, label %truebb, label %falsebb | |
| truebb: | |
| br label %end | |
| falsebb: | |
| br label %end | |
| end: | |
| %ptr = phi ptr [ %dst, %truebb ], [ null, %falsebb ] | |
| store i32 0, ptr %ptr | |
| ret void | |
| } | |
| define void @test13-1(i1 %c, ptr align 32 %dst) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test13-1 | |
| ; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR9:[0-9]+]] { | |
| ; TUNIT-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] | |
| ; TUNIT: truebb: | |
| ; TUNIT-NEXT: br label [[END:%.*]] | |
| ; TUNIT: falsebb: | |
| ; TUNIT-NEXT: br label [[END]] | |
| ; TUNIT: end: | |
| ; TUNIT-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to ptr), [[FALSEBB]] ] | |
| ; TUNIT-NEXT: store i32 0, ptr [[PTR]], align 16 | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test13-1 | |
| ; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR10:[0-9]+]] { | |
| ; CGSCC-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] | |
| ; CGSCC: truebb: | |
| ; CGSCC-NEXT: br label [[END:%.*]] | |
| ; CGSCC: falsebb: | |
| ; CGSCC-NEXT: br label [[END]] | |
| ; CGSCC: end: | |
| ; CGSCC-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to ptr), [[FALSEBB]] ] | |
| ; CGSCC-NEXT: store i32 0, ptr [[PTR]], align 16 | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| br i1 %c, label %truebb, label %falsebb | |
| truebb: | |
| br label %end | |
| falsebb: | |
| br label %end | |
| end: | |
| %ptr = phi ptr [ %dst, %truebb ], [ inttoptr (i64 48 to ptr), %falsebb ] | |
| store i32 0, ptr %ptr | |
| ret void | |
| } | |
| define void @test13-2(i1 %c, ptr align 32 %dst) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test13-2 | |
| ; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR9]] { | |
| ; TUNIT-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] | |
| ; TUNIT: truebb: | |
| ; TUNIT-NEXT: br label [[END:%.*]] | |
| ; TUNIT: falsebb: | |
| ; TUNIT-NEXT: br label [[END]] | |
| ; TUNIT: end: | |
| ; TUNIT-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to ptr), [[FALSEBB]] ] | |
| ; TUNIT-NEXT: store i32 0, ptr [[PTR]], align 32 | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test13-2 | |
| ; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR10]] { | |
| ; CGSCC-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] | |
| ; CGSCC: truebb: | |
| ; CGSCC-NEXT: br label [[END:%.*]] | |
| ; CGSCC: falsebb: | |
| ; CGSCC-NEXT: br label [[END]] | |
| ; CGSCC: end: | |
| ; CGSCC-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to ptr), [[FALSEBB]] ] | |
| ; CGSCC-NEXT: store i32 0, ptr [[PTR]], align 32 | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| br i1 %c, label %truebb, label %falsebb | |
| truebb: | |
| br label %end | |
| falsebb: | |
| br label %end | |
| end: | |
| %ptr = phi ptr [ %dst, %truebb ], [ inttoptr (i64 160 to ptr), %falsebb ] | |
| store i32 0, ptr %ptr | |
| ret void | |
| } | |
| define void @test13-3(i1 %c, ptr align 32 %dst) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) | |
| ; TUNIT-LABEL: define {{[^@]+}}@test13-3 | |
| ; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR9]] { | |
| ; TUNIT-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] | |
| ; TUNIT: truebb: | |
| ; TUNIT-NEXT: br label [[END:%.*]] | |
| ; TUNIT: falsebb: | |
| ; TUNIT-NEXT: br label [[END]] | |
| ; TUNIT: end: | |
| ; TUNIT-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to ptr), [[FALSEBB]] ] | |
| ; TUNIT-NEXT: store i32 0, ptr [[PTR]], align 32 | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) | |
| ; CGSCC-LABEL: define {{[^@]+}}@test13-3 | |
| ; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree writeonly align 32 captures(none) [[DST:%.*]]) #[[ATTR10]] { | |
| ; CGSCC-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] | |
| ; CGSCC: truebb: | |
| ; CGSCC-NEXT: br label [[END:%.*]] | |
| ; CGSCC: falsebb: | |
| ; CGSCC-NEXT: br label [[END]] | |
| ; CGSCC: end: | |
| ; CGSCC-NEXT: [[PTR:%.*]] = phi ptr [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to ptr), [[FALSEBB]] ] | |
| ; CGSCC-NEXT: store i32 0, ptr [[PTR]], align 32 | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| br i1 %c, label %truebb, label %falsebb | |
| truebb: | |
| br label %end | |
| falsebb: | |
| br label %end | |
| end: | |
| %ptr = phi ptr [ %dst, %truebb ], [ inttoptr (i64 128 to ptr), %falsebb ] | |
| store i32 0, ptr %ptr | |
| ret void | |
| } | |
| ; Don't crash on ptr2int/int2ptr uses. | |
| define i64 @ptr2int(ptr %p) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) | |
| ; TUNIT-LABEL: define {{[^@]+}}@ptr2int | |
| ; TUNIT-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR10:[0-9]+]] { | |
| ; TUNIT-NEXT: [[P2I:%.*]] = ptrtoint ptr [[P]] to i64 | |
| ; TUNIT-NEXT: ret i64 [[P2I]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) | |
| ; CGSCC-LABEL: define {{[^@]+}}@ptr2int | |
| ; CGSCC-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR11:[0-9]+]] { | |
| ; CGSCC-NEXT: [[P2I:%.*]] = ptrtoint ptr [[P]] to i64 | |
| ; CGSCC-NEXT: ret i64 [[P2I]] | |
| ; | |
| %p2i = ptrtoint ptr %p to i64 | |
| ret i64 %p2i | |
| } | |
| define ptr @int2ptr(i64 %i) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) | |
| ; TUNIT-LABEL: define {{[^@]+}}@int2ptr | |
| ; TUNIT-SAME: (i64 [[I:%.*]]) #[[ATTR10]] { | |
| ; TUNIT-NEXT: [[I2P:%.*]] = inttoptr i64 [[I]] to ptr | |
| ; TUNIT-NEXT: ret ptr [[I2P]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) | |
| ; CGSCC-LABEL: define {{[^@]+}}@int2ptr | |
| ; CGSCC-SAME: (i64 [[I:%.*]]) #[[ATTR11]] { | |
| ; CGSCC-NEXT: [[I2P:%.*]] = inttoptr i64 [[I]] to ptr | |
| ; CGSCC-NEXT: ret ptr [[I2P]] | |
| ; | |
| %i2p = inttoptr i64 %i to ptr | |
| ret ptr %i2p | |
| } | |
| ; Use the store alignment only for the pointer operand. | |
| define void @aligned_store(ptr %Value, ptr %Ptr) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) | |
| ; TUNIT-LABEL: define {{[^@]+}}@aligned_store | |
| ; TUNIT-SAME: (ptr nofree writeonly [[VALUE:%.*]], ptr nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(8) [[PTR:%.*]]) #[[ATTR5]] { | |
| ; TUNIT-NEXT: store ptr [[VALUE]], ptr [[PTR]], align 32 | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) | |
| ; CGSCC-LABEL: define {{[^@]+}}@aligned_store | |
| ; CGSCC-SAME: (ptr nofree writeonly [[VALUE:%.*]], ptr nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(8) [[PTR:%.*]]) #[[ATTR6]] { | |
| ; CGSCC-NEXT: store ptr [[VALUE]], ptr [[PTR]], align 32 | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| store ptr %Value, ptr %Ptr, align 32 | |
| ret void | |
| } | |
| declare ptr @some_func(ptr) | |
| define void @align_call_op_not_store(ptr align 2048 %arg) { | |
| ; CHECK-LABEL: define {{[^@]+}}@align_call_op_not_store | |
| ; CHECK-SAME: (ptr align 2048 [[ARG:%.*]]) { | |
| ; CHECK-NEXT: [[UNKNOWN:%.*]] = call ptr @some_func(ptr align 2048 [[ARG]]) | |
| ; CHECK-NEXT: store i8 0, ptr [[UNKNOWN]], align 1 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %unknown = call ptr @some_func(ptr %arg) | |
| store i8 0, ptr %unknown | |
| ret void | |
| } | |
| define void @align_store_after_bc(ptr align 2048 %arg) { | |
| ; | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) | |
| ; TUNIT-LABEL: define {{[^@]+}}@align_store_after_bc | |
| ; TUNIT-SAME: (ptr nofree nonnull writeonly align 2048 captures(none) dereferenceable(1) [[ARG:%.*]]) #[[ATTR5]] { | |
| ; TUNIT-NEXT: store i8 0, ptr [[ARG]], align 2048 | |
| ; TUNIT-NEXT: ret void | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) | |
| ; CGSCC-LABEL: define {{[^@]+}}@align_store_after_bc | |
| ; CGSCC-SAME: (ptr nofree nonnull writeonly align 2048 captures(none) dereferenceable(1) [[ARG:%.*]]) #[[ATTR6]] { | |
| ; CGSCC-NEXT: store i8 0, ptr [[ARG]], align 2048 | |
| ; CGSCC-NEXT: ret void | |
| ; | |
| %bc = bitcast ptr %arg to ptr | |
| store i8 0, ptr %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(ptr %p) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) | |
| ; TUNIT-LABEL: define {{[^@]+}}@musttail_callee_1 | |
| ; TUNIT-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR4]] { | |
| ; TUNIT-NEXT: [[V:%.*]] = load i32, ptr [[P]], align 32 | |
| ; TUNIT-NEXT: ret i32 [[V]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) | |
| ; CGSCC-LABEL: define {{[^@]+}}@musttail_callee_1 | |
| ; CGSCC-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR5]] { | |
| ; CGSCC-NEXT: [[V:%.*]] = load i32, ptr [[P]], align 32 | |
| ; CGSCC-NEXT: ret i32 [[V]] | |
| ; | |
| %v = load i32, ptr %p, align 32 | |
| ret i32 %v | |
| } | |
| define i32 @musttail_caller_1(ptr %p) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read) | |
| ; TUNIT-LABEL: define {{[^@]+}}@musttail_caller_1 | |
| ; TUNIT-SAME: (ptr nofree readonly captures(none) [[P:%.*]]) #[[ATTR11:[0-9]+]] { | |
| ; TUNIT-NEXT: [[C:%.*]] = load i1, ptr @cnd, align 1 | |
| ; TUNIT-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] | |
| ; TUNIT: mt: | |
| ; TUNIT-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(ptr nofree noundef readonly captures(none) [[P]]) #[[ATTR14:[0-9]+]] | |
| ; TUNIT-NEXT: ret i32 [[V]] | |
| ; TUNIT: exit: | |
| ; TUNIT-NEXT: ret i32 0 | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read) | |
| ; CGSCC-LABEL: define {{[^@]+}}@musttail_caller_1 | |
| ; CGSCC-SAME: (ptr nofree readonly captures(none) [[P:%.*]]) #[[ATTR12:[0-9]+]] { | |
| ; CGSCC-NEXT: [[C:%.*]] = load i1, ptr @cnd, align 1 | |
| ; CGSCC-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] | |
| ; CGSCC: mt: | |
| ; CGSCC-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(ptr nofree noundef nonnull readonly captures(none) dereferenceable(4) [[P]]) #[[ATTR17:[0-9]+]] | |
| ; CGSCC-NEXT: ret i32 [[V]] | |
| ; CGSCC: exit: | |
| ; CGSCC-NEXT: ret i32 0 | |
| ; | |
| %c = load i1, ptr @cnd | |
| br i1 %c, label %mt, label %exit | |
| mt: | |
| %v = musttail call i32 @musttail_callee_1(ptr %p) | |
| ret i32 %v | |
| exit: | |
| ret i32 0 | |
| } | |
| define ptr @checkAndAdvance(ptr align(16) %p) { | |
| ; TUNIT: Function Attrs: nounwind | |
| ; TUNIT-LABEL: define {{[^@]+}}@checkAndAdvance | |
| ; TUNIT-SAME: (ptr nofree noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR2]] { | |
| ; TUNIT-NEXT: entry: | |
| ; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 16 | |
| ; TUNIT-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 | |
| ; TUNIT-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] | |
| ; TUNIT: if.then: | |
| ; TUNIT-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 4 | |
| ; TUNIT-NEXT: [[CALL:%.*]] = call ptr @checkAndAdvance(ptr nofree noundef nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR2]] | |
| ; TUNIT-NEXT: br label [[RETURN]] | |
| ; TUNIT: return: | |
| ; TUNIT-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[ADD_PTR]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ] | |
| ; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nofree nonnull readnone align 16 captures(none) [[RETVAL_0]]) #[[ATTR2]] | |
| ; TUNIT-NEXT: ret ptr [[RETVAL_0]] | |
| ; | |
| ; CGSCC: Function Attrs: nounwind | |
| ; CGSCC-LABEL: define {{[^@]+}}@checkAndAdvance | |
| ; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3]] { | |
| ; CGSCC-NEXT: entry: | |
| ; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 16 | |
| ; CGSCC-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 | |
| ; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] | |
| ; CGSCC: if.then: | |
| ; CGSCC-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 4 | |
| ; CGSCC-NEXT: [[CALL:%.*]] = call ptr @checkAndAdvance(ptr nofree noundef nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR3]] | |
| ; CGSCC-NEXT: br label [[RETURN]] | |
| ; CGSCC: return: | |
| ; CGSCC-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[ADD_PTR]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ] | |
| ; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nofree nonnull readnone align 16 captures(none) [[RETVAL_0]]) #[[ATTR3]] | |
| ; CGSCC-NEXT: ret ptr [[RETVAL_0]] | |
| ; | |
| entry: | |
| %0 = load i32, ptr %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, ptr %p, i64 4 | |
| %call = call ptr @checkAndAdvance(ptr nonnull %add.ptr) | |
| br label %return | |
| return: ; preds = %entry, %if.then | |
| %retval.0 = phi ptr [ %call, %if.then ], [ %p, %entry ] | |
| call void @user_i32_ptr(ptr %retval.0) | |
| ret ptr %retval.0 | |
| } | |
| ; FIXME: align 4 should not be propagated to the caller's p unless there is noundef | |
| define void @align4_caller(ptr %p) { | |
| ; CHECK-LABEL: define {{[^@]+}}@align4_caller | |
| ; CHECK-SAME: (ptr align 4 [[P:%.*]]) { | |
| ; CHECK-NEXT: call void @align4_callee(ptr align 4 [[P]]) | |
| ; CHECK-NEXT: ret void | |
| ; | |
| call void @align4_callee(ptr %p) | |
| ret void | |
| } | |
| declare void @align4_callee(ptr align(4) %p) | |
| @G = global i8 0, align 32 | |
| define internal ptr @aligned_8_return(ptr %a, i1 %c1, i1 %c2) norecurse { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) | |
| ; TUNIT-LABEL: define {{[^@]+}}@aligned_8_return | |
| ; TUNIT-SAME: (ptr noalias nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR10]] { | |
| ; TUNIT-NEXT: [[STACK:%.*]] = alloca ptr, align 8 | |
| ; TUNIT-NEXT: br i1 [[C1]], label [[T:%.*]], label [[F:%.*]] | |
| ; TUNIT: t: | |
| ; TUNIT-NEXT: [[GEP:%.*]] = getelementptr i8, ptr @G, i32 8 | |
| ; TUNIT-NEXT: [[SEL:%.*]] = select i1 [[C2]], ptr [[A]], ptr [[GEP]] | |
| ; TUNIT-NEXT: store ptr [[SEL]], ptr [[STACK]], align 8 | |
| ; TUNIT-NEXT: br label [[END:%.*]] | |
| ; TUNIT: f: | |
| ; TUNIT-NEXT: store ptr @G, ptr [[STACK]], align 8 | |
| ; TUNIT-NEXT: br label [[END]] | |
| ; TUNIT: end: | |
| ; TUNIT-NEXT: [[L:%.*]] = load ptr, ptr [[STACK]], align 8 | |
| ; TUNIT-NEXT: ret ptr [[L]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) | |
| ; CGSCC-LABEL: define {{[^@]+}}@aligned_8_return | |
| ; CGSCC-SAME: (ptr noalias nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR11]] { | |
| ; CGSCC-NEXT: [[STACK:%.*]] = alloca ptr, align 8 | |
| ; CGSCC-NEXT: br i1 [[C1]], label [[T:%.*]], label [[F:%.*]] | |
| ; CGSCC: t: | |
| ; CGSCC-NEXT: [[GEP:%.*]] = getelementptr i8, ptr @G, i32 8 | |
| ; CGSCC-NEXT: [[SEL:%.*]] = select i1 [[C2]], ptr [[A]], ptr [[GEP]] | |
| ; CGSCC-NEXT: store ptr [[SEL]], ptr [[STACK]], align 8 | |
| ; CGSCC-NEXT: br label [[END:%.*]] | |
| ; CGSCC: f: | |
| ; CGSCC-NEXT: store ptr @G, ptr [[STACK]], align 8 | |
| ; CGSCC-NEXT: br label [[END]] | |
| ; CGSCC: end: | |
| ; CGSCC-NEXT: [[L:%.*]] = load ptr, ptr [[STACK]], align 8 | |
| ; CGSCC-NEXT: ret ptr [[L]] | |
| ; | |
| %stack = alloca ptr | |
| br i1 %c1, label %t, label %f | |
| t: | |
| %gep = getelementptr i8, ptr @G, i32 8 | |
| %sel = select i1 %c2, ptr %a, ptr %gep | |
| store ptr %sel, ptr %stack | |
| br label %end | |
| f: | |
| store ptr @G, ptr %stack | |
| br label %end | |
| end: | |
| %l = load ptr, ptr %stack | |
| ret ptr %l | |
| } | |
| define ptr @aligned_8_return_caller(ptr align(16) %a, i1 %c1, i1 %c2) { | |
| ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) | |
| ; TUNIT-LABEL: define {{[^@]+}}@aligned_8_return_caller | |
| ; TUNIT-SAME: (ptr nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR10]] { | |
| ; TUNIT-NEXT: [[R:%.*]] = call align 8 ptr @aligned_8_return(ptr noalias nofree readnone align 16 "no-capture-maybe-returned" [[A]], i1 noundef [[C1]], i1 [[C2]]) #[[ATTR15:[0-9]+]] | |
| ; TUNIT-NEXT: ret ptr [[R]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) | |
| ; CGSCC-LABEL: define {{[^@]+}}@aligned_8_return_caller | |
| ; CGSCC-SAME: (ptr nofree readnone align 16 [[A:%.*]], i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR13:[0-9]+]] { | |
| ; CGSCC-NEXT: [[R:%.*]] = call align 8 ptr @aligned_8_return(ptr noalias nofree readnone align 16 [[A]], i1 noundef [[C1]], i1 [[C2]]) #[[ATTR15]] | |
| ; CGSCC-NEXT: ret ptr [[R]] | |
| ; | |
| %r = call ptr @aligned_8_return(ptr %a, i1 %c1, i1 %c2) | |
| ret ptr %r | |
| } | |
| define i32 @implicit_cast_caller(ptr %ptr) { | |
| ; CHECK-LABEL: define {{[^@]+}}@implicit_cast_caller | |
| ; CHECK-SAME: (ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @implicit_cast_callee(ptr [[PTR]]) | |
| ; CHECK-NEXT: ret i32 0 | |
| ; | |
| entry: | |
| %call = tail call i32 @implicit_cast_callee(ptr %ptr) | |
| ret i32 0 | |
| } | |
| define i64 @infer_align_atomicrmw(ptr align 4 %p) { | |
| ; TUNIT: Function Attrs: mustprogress norecurse nounwind willreturn memory(argmem: readwrite) | |
| ; TUNIT-LABEL: define {{[^@]+}}@infer_align_atomicrmw | |
| ; TUNIT-SAME: (ptr nofree align 16 captures(none) [[P:%.*]]) #[[ATTR12:[0-9]+]] { | |
| ; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; TUNIT-NEXT: [[RET:%.*]] = atomicrmw add ptr [[ARRAYIDX1]], i64 4 seq_cst, align 16 | |
| ; TUNIT-NEXT: ret i64 [[RET]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress norecurse nounwind willreturn memory(argmem: readwrite) | |
| ; CGSCC-LABEL: define {{[^@]+}}@infer_align_atomicrmw | |
| ; CGSCC-SAME: (ptr nofree align 16 captures(none) [[P:%.*]]) #[[ATTR14:[0-9]+]] { | |
| ; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; CGSCC-NEXT: [[RET:%.*]] = atomicrmw add ptr [[ARRAYIDX1]], i64 4 seq_cst, align 16 | |
| ; CGSCC-NEXT: ret i64 [[RET]] | |
| ; | |
| %arrayidx0 = getelementptr i64, ptr %p, i64 1 | |
| %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 | |
| %ret = atomicrmw add ptr %arrayidx1, i64 4 seq_cst, align 16 | |
| ret i64 %ret | |
| } | |
| define ptr @infer_align_atomicrmw_ptr(ptr align 4 %p, ptr %val) { | |
| ; TUNIT: Function Attrs: mustprogress norecurse nounwind willreturn memory(argmem: readwrite) | |
| ; TUNIT-LABEL: define {{[^@]+}}@infer_align_atomicrmw_ptr | |
| ; TUNIT-SAME: (ptr nofree align 16 captures(none) [[P:%.*]], ptr [[VAL:%.*]]) #[[ATTR12]] { | |
| ; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; TUNIT-NEXT: [[RET:%.*]] = atomicrmw xchg ptr [[ARRAYIDX1]], ptr [[VAL]] seq_cst, align 16 | |
| ; TUNIT-NEXT: ret ptr [[RET]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress norecurse nounwind willreturn memory(argmem: readwrite) | |
| ; CGSCC-LABEL: define {{[^@]+}}@infer_align_atomicrmw_ptr | |
| ; CGSCC-SAME: (ptr nofree align 16 captures(none) [[P:%.*]], ptr [[VAL:%.*]]) #[[ATTR14]] { | |
| ; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; CGSCC-NEXT: [[RET:%.*]] = atomicrmw xchg ptr [[ARRAYIDX1]], ptr [[VAL]] seq_cst, align 16 | |
| ; CGSCC-NEXT: ret ptr [[RET]] | |
| ; | |
| %arrayidx0 = getelementptr i64, ptr %p, i64 1 | |
| %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 | |
| %ret = atomicrmw xchg ptr %arrayidx1, ptr %val seq_cst, align 16 | |
| ret ptr %ret | |
| } | |
| define i64 @infer_align_cmpxchg(ptr align 4 %p) { | |
| ; TUNIT: Function Attrs: mustprogress norecurse nounwind willreturn memory(argmem: readwrite) | |
| ; TUNIT-LABEL: define {{[^@]+}}@infer_align_cmpxchg | |
| ; TUNIT-SAME: (ptr nofree align 16 captures(none) [[P:%.*]]) #[[ATTR12]] { | |
| ; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; TUNIT-NEXT: [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], i64 4, i64 1 seq_cst seq_cst, align 16 | |
| ; TUNIT-NEXT: [[RET:%.*]] = extractvalue { i64, i1 } [[CMPX]], 0 | |
| ; TUNIT-NEXT: ret i64 [[RET]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress norecurse nounwind willreturn memory(argmem: readwrite) | |
| ; CGSCC-LABEL: define {{[^@]+}}@infer_align_cmpxchg | |
| ; CGSCC-SAME: (ptr nofree align 16 captures(none) [[P:%.*]]) #[[ATTR14]] { | |
| ; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; CGSCC-NEXT: [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], i64 4, i64 1 seq_cst seq_cst, align 16 | |
| ; CGSCC-NEXT: [[RET:%.*]] = extractvalue { i64, i1 } [[CMPX]], 0 | |
| ; CGSCC-NEXT: ret i64 [[RET]] | |
| ; | |
| %arrayidx0 = getelementptr i64, ptr %p, i64 1 | |
| %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 | |
| %cmpx = cmpxchg ptr %arrayidx1, i64 4, i64 1 seq_cst seq_cst, align 16 | |
| %ret = extractvalue { i64, i1 } %cmpx, 0 | |
| ret i64 %ret | |
| } | |
| define ptr @infer_align_cmpxchg_ptr(ptr align 4 %p, ptr %cmp0, ptr %cmp1) { | |
| ; TUNIT: Function Attrs: mustprogress norecurse nounwind willreturn memory(argmem: readwrite) | |
| ; TUNIT-LABEL: define {{[^@]+}}@infer_align_cmpxchg_ptr | |
| ; TUNIT-SAME: (ptr nofree align 16 captures(none) [[P:%.*]], ptr [[CMP0:%.*]], ptr [[CMP1:%.*]]) #[[ATTR12]] { | |
| ; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; TUNIT-NEXT: [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], ptr [[CMP0]], ptr [[CMP1]] seq_cst seq_cst, align 16 | |
| ; TUNIT-NEXT: [[RET:%.*]] = extractvalue { ptr, i1 } [[CMPX]], 0 | |
| ; TUNIT-NEXT: ret ptr [[RET]] | |
| ; | |
| ; CGSCC: Function Attrs: mustprogress norecurse nounwind willreturn memory(argmem: readwrite) | |
| ; CGSCC-LABEL: define {{[^@]+}}@infer_align_cmpxchg_ptr | |
| ; CGSCC-SAME: (ptr nofree align 16 captures(none) [[P:%.*]], ptr [[CMP0:%.*]], ptr [[CMP1:%.*]]) #[[ATTR14]] { | |
| ; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 | |
| ; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 | |
| ; CGSCC-NEXT: [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], ptr [[CMP0]], ptr [[CMP1]] seq_cst seq_cst, align 16 | |
| ; CGSCC-NEXT: [[RET:%.*]] = extractvalue { ptr, i1 } [[CMPX]], 0 | |
| ; CGSCC-NEXT: ret ptr [[RET]] | |
| ; | |
| %arrayidx0 = getelementptr i64, ptr %p, i64 1 | |
| %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 | |
| %cmpx = cmpxchg ptr %arrayidx1, ptr %cmp0, ptr %cmp1 seq_cst seq_cst, align 16 | |
| %ret = extractvalue { ptr, i1 } %cmpx, 0 | |
| ret ptr %ret | |
| } | |
| declare void @implicit_cast_callee(i64) | |
| attributes #0 = { nounwind uwtable noinline } | |
| attributes #1 = { uwtable noinline } | |
| attributes #2 = { null_pointer_is_valid } | |
| ;. | |
| ; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable } | |
| ; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable } | |
| ; TUNIT: attributes #[[ATTR2]] = { nounwind } | |
| ; TUNIT: attributes #[[ATTR3]] = { nofree nosync nounwind memory(argmem: readwrite) } | |
| ; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } | |
| ; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) } | |
| ; TUNIT: attributes #[[ATTR6]] = { nounwind willreturn } | |
| ; TUNIT: attributes #[[ATTR7]] = { mustprogress nounwind willreturn } | |
| ; TUNIT: attributes #[[ATTR8]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable } | |
| ; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } | |
| ; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } | |
| ; TUNIT: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(read) } | |
| ; TUNIT: attributes #[[ATTR12]] = { mustprogress norecurse nounwind willreturn memory(argmem: readwrite) } | |
| ; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind } | |
| ; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind willreturn memory(read) } | |
| ; TUNIT: attributes #[[ATTR15]] = { nofree norecurse nosync nounwind willreturn } | |
| ;. | |
| ; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable } | |
| ; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable } | |
| ; CGSCC: attributes #[[ATTR2]] = { noinline nounwind uwtable } | |
| ; CGSCC: attributes #[[ATTR3]] = { nounwind } | |
| ; CGSCC: attributes #[[ATTR4]] = { nofree nosync nounwind memory(argmem: readwrite) } | |
| ; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } | |
| ; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) } | |
| ; CGSCC: attributes #[[ATTR7]] = { nounwind willreturn } | |
| ; CGSCC: attributes #[[ATTR8]] = { mustprogress nounwind willreturn } | |
| ; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable } | |
| ; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } | |
| ; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } | |
| ; CGSCC: attributes #[[ATTR12]] = { mustprogress nofree nosync nounwind willreturn memory(read) } | |
| ; CGSCC: attributes #[[ATTR13]] = { mustprogress nofree nosync nounwind willreturn memory(none) } | |
| ; CGSCC: attributes #[[ATTR14]] = { mustprogress norecurse nounwind willreturn memory(argmem: readwrite) } | |
| ; CGSCC: attributes #[[ATTR15]] = { nofree nosync willreturn } | |
| ; CGSCC: attributes #[[ATTR16]] = { nofree nosync nounwind } | |
| ; CGSCC: attributes #[[ATTR17]] = { nofree willreturn memory(read) } | |
| ;. | |
| ; TUNIT: [[META0]] = !{} | |
| ;. | |
| ; CGSCC: [[META0]] = !{} | |
| ;. |