blob: 9880e53fd43a59c07a9c8653a6b6d1b6e26352a9 [file] [log] [blame]
; 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) }
;.