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