| ; 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 nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone [[PTR0]]) #[[ATTR2:[0-9]+]] |
| ; TUNIT-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 8 [[PTR2]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]]) #[[ATTR2]] |
| ; TUNIT-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 8 [[PTR2]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[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 nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone [[PTR0]]) #[[ATTR3:[0-9]+]] |
| ; CGSCC-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 8 [[PTR2]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]]) #[[ATTR3]] |
| ; CGSCC-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 8 [[PTR2]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[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 nocapture nofree readnone align 4 [[A:%.*]], ptr noalias nocapture nofree readnone align 4 [[B:%.*]], ptr noalias nocapture nofree readnone [[C:%.*]]) #[[ATTR2]] { |
| ; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone align 4 [[A]]) #[[ATTR2]] |
| ; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone align 4 [[B]]) #[[ATTR2]] |
| ; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR2]] |
| ; TUNIT-NEXT: ret void |
| ; |
| ; CGSCC: Function Attrs: nounwind |
| ; CGSCC-LABEL: define {{[^@]+}}@test8 |
| ; CGSCC-SAME: (ptr noalias nocapture nofree readnone align 4 [[A:%.*]], ptr noalias nocapture nofree readnone align 4 [[B:%.*]], ptr noalias nocapture nofree readnone [[C:%.*]]) #[[ATTR3]] { |
| ; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone align 4 [[A]]) #[[ATTR3]] |
| ; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone align 4 [[B]]) #[[ATTR3]] |
| ; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone [[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 |
| ; 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]]) #[[ATTR3]] |
| ; 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 |
| ; 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]]) #[[ATTR4]] |
| ; 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 |
| ; 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]]) #[[ATTR3]] |
| ; 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 |
| ; 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]]) #[[ATTR4]] |
| ; 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 nocapture nofree nonnull readonly align 8 dereferenceable(8) [[P:%.*]]) #[[ATTR4:[0-9]+]] { |
| ; TUNIT-NEXT: [[RET:%.*]] = load i64, ptr [[P]], align 8 |
| ; TUNIT-NEXT: ret i64 [[RET]] |
| ; |
| ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) |
| ; CGSCC-LABEL: define {{[^@]+}}@test11 |
| ; CGSCC-SAME: (ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[P:%.*]]) #[[ATTR5:[0-9]+]] { |
| ; CGSCC-NEXT: [[RET:%.*]] = load i64, ptr [[P]], align 8 |
| ; 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 nocapture nofree readonly align 16 [[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 |
| ; 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 nocapture nofree readonly align 16 [[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 |
| ; 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 nocapture nofree nonnull readonly align 16 dereferenceable(8) [[P:%.*]]) #[[ATTR4]] { |
| ; TUNIT-NEXT: [[RET:%.*]] = load i64, ptr [[P]], align 16 |
| ; 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 nocapture nofree nonnull readonly align 16 dereferenceable(8) [[P:%.*]]) #[[ATTR5]] { |
| ; CGSCC-NEXT: [[RET:%.*]] = load i64, ptr [[P]], align 16 |
| ; 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 nocapture nofree writeonly align 16 [[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 nocapture nofree writeonly align 16 [[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 nocapture nofree nonnull writeonly align 16 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 nocapture nofree nonnull writeonly align 16 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 nocapture nofree writeonly align 32 [[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 nocapture nofree writeonly align 32 [[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 nocapture nofree writeonly align 32 [[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 nocapture nofree writeonly align 32 [[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 nocapture nofree writeonly align 32 [[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 nocapture nofree writeonly align 32 [[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 nocapture nofree writeonly align 32 [[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 nocapture nofree writeonly align 32 [[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 nocapture nofree noundef nonnull writeonly align 32 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 nocapture nofree noundef nonnull writeonly align 32 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 nocapture nofree nonnull writeonly align 2048 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 nocapture nofree nonnull writeonly align 2048 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 nocapture nofree noundef nonnull readonly 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 nocapture nofree noundef nonnull readonly 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 nocapture nofree readonly [[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 nocapture nofree noundef readonly [[P]]) #[[ATTR13:[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 nocapture nofree readonly [[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 nocapture nofree noundef nonnull readonly dereferenceable(4) [[P]]) #[[ATTR16:[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 nocapture nofree nonnull readnone align 16 [[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 nocapture nofree nonnull readnone align 16 [[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]]) #[[ATTR14:[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 nofree norecurse nounwind willreturn memory(argmem: readwrite) |
| ; TUNIT-LABEL: define {{[^@]+}}@infer_align_atomicrmw |
| ; TUNIT-SAME: (ptr nocapture nofree align 16 [[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 nofree norecurse nounwind willreturn memory(argmem: readwrite) |
| ; CGSCC-LABEL: define {{[^@]+}}@infer_align_atomicrmw |
| ; CGSCC-SAME: (ptr nocapture nofree align 16 [[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 nofree norecurse nounwind willreturn memory(argmem: readwrite) |
| ; TUNIT-LABEL: define {{[^@]+}}@infer_align_atomicrmw_ptr |
| ; TUNIT-SAME: (ptr nocapture nofree align 16 [[P:%.*]], ptr nofree [[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 nofree norecurse nounwind willreturn memory(argmem: readwrite) |
| ; CGSCC-LABEL: define {{[^@]+}}@infer_align_atomicrmw_ptr |
| ; CGSCC-SAME: (ptr nocapture nofree align 16 [[P:%.*]], ptr nofree [[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 nofree norecurse nounwind willreturn memory(argmem: readwrite) |
| ; TUNIT-LABEL: define {{[^@]+}}@infer_align_cmpxchg |
| ; TUNIT-SAME: (ptr nocapture nofree align 16 [[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 nofree norecurse nounwind willreturn memory(argmem: readwrite) |
| ; CGSCC-LABEL: define {{[^@]+}}@infer_align_cmpxchg |
| ; CGSCC-SAME: (ptr nocapture nofree align 16 [[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 nofree norecurse nounwind willreturn memory(argmem: readwrite) |
| ; TUNIT-LABEL: define {{[^@]+}}@infer_align_cmpxchg_ptr |
| ; TUNIT-SAME: (ptr nocapture nofree align 16 [[P:%.*]], ptr nofree [[CMP0:%.*]], ptr nofree [[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 nofree norecurse nounwind willreturn memory(argmem: readwrite) |
| ; CGSCC-LABEL: define {{[^@]+}}@infer_align_cmpxchg_ptr |
| ; CGSCC-SAME: (ptr nocapture nofree align 16 [[P:%.*]], ptr nofree [[CMP0:%.*]], ptr nofree [[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 } |
| ; 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 nofree norecurse nounwind willreturn memory(argmem: readwrite) } |
| ; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn memory(read) } |
| ; TUNIT: attributes #[[ATTR14]] = { nofree 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 } |
| ; 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 nofree norecurse nounwind willreturn memory(argmem: readwrite) } |
| ; CGSCC: attributes #[[ATTR15]] = { nofree nosync willreturn } |
| ; CGSCC: attributes #[[ATTR16]] = { nofree willreturn memory(read) } |
| ;. |