These should not really have uselists, and it's not worth the compile time of looking at all uses of trivial constants. The main observable change of this is it no longer adds align attributes on constant null uses, but those are not useful. Some of these cases should potentially be more aggressive and not look at any Constant users.
1714 lines
61 KiB
LLVM
1714 lines
61 KiB
LLVM
; 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:o-i64:64-f80:128-n8:16:32:64-S128"
|
|
declare void @f(i32)
|
|
declare token @llvm.call.preallocated.setup(i32)
|
|
declare ptr @llvm.call.preallocated.arg(token, i32)
|
|
|
|
@str = private unnamed_addr addrspace(4) constant [1 x i8] c"\00", align 1
|
|
@ConstAS3Ptr = addrspace(3) global i32 0, align 4
|
|
@ConstPtr = constant i32 0, align 4
|
|
@ConstWeakPtr = weak constant i32 0, align 4
|
|
@ConstWeakODRPtr = weak_odr constant i32 0, align 4
|
|
@ExtInitZeroInit = externally_initialized constant i32 zeroinitializer, align 4
|
|
|
|
;.
|
|
; CHECK: @str = private unnamed_addr addrspace(4) constant [1 x i8] zeroinitializer, align 1
|
|
; CHECK: @ConstAS3Ptr = addrspace(3) global i32 0, align 4
|
|
; CHECK: @ConstPtr = constant i32 0, align 4
|
|
; CHECK: @ConstWeakPtr = weak constant i32 0, align 4
|
|
; CHECK: @ConstWeakODRPtr = weak_odr constant i32 0, align 4
|
|
; CHECK: @ExtInitZeroInit = externally_initialized constant i32 0, align 4
|
|
; CHECK: @S = external global %struct.X
|
|
; CHECK: @g = internal constant { [2 x ptr] } { [2 x ptr] [ptr @f1, ptr @f2] }
|
|
; CHECK: @x = external global i32
|
|
;.
|
|
define internal ptr addrspace(3) @const_ptr_return_as3() {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@const_ptr_return_as3
|
|
; CGSCC-SAME: () #[[ATTR1:[0-9]+]] {
|
|
; CGSCC-NEXT: ret ptr addrspace(3) @ConstAS3Ptr
|
|
;
|
|
ret ptr addrspace(3) @ConstAS3Ptr
|
|
}
|
|
define internal ptr @const_ptr_return() {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@const_ptr_return
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret ptr addrspacecast (ptr addrspace(3) @ConstAS3Ptr to ptr)
|
|
;
|
|
ret ptr addrspacecast (ptr addrspace(3) @ConstAS3Ptr to ptr)
|
|
}
|
|
|
|
; Test1: Replace argument with constant
|
|
define internal void @test1(i32 %a) {
|
|
; TUNIT: Function Attrs: memory(readwrite, argmem: none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test1
|
|
; TUNIT-SAME: () #[[ATTR1:[0-9]+]] {
|
|
; TUNIT-NEXT: tail call void @f(i32 noundef 1)
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: memory(readwrite, argmem: none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test1
|
|
; CGSCC-SAME: () #[[ATTR2:[0-9]+]] {
|
|
; CGSCC-NEXT: tail call void @f(i32 noundef 1)
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
tail call void @f(i32 %a)
|
|
ret void
|
|
}
|
|
|
|
define void @test1_helper() {
|
|
; CHECK-LABEL: define {{[^@]+}}@test1_helper() {
|
|
; CHECK-NEXT: tail call void @test1()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
tail call void @test1(i32 1)
|
|
ret void
|
|
}
|
|
|
|
; TEST 2 : Simplify return value
|
|
define i32 @return0() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@return0
|
|
; TUNIT-SAME: () #[[ATTR2:[0-9]+]] {
|
|
; TUNIT-NEXT: ret i32 0
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@return0
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret i32 0
|
|
;
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @return1() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@return1
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i32 1
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@return1
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret i32 1
|
|
;
|
|
ret i32 1
|
|
}
|
|
|
|
define i32 @test2_1(i1 %c) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test2_1
|
|
; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
|
|
; TUNIT: if.true:
|
|
; TUNIT-NEXT: [[RET0:%.*]] = add i32 0, 1
|
|
; TUNIT-NEXT: br label [[END:%.*]]
|
|
; TUNIT: if.false:
|
|
; TUNIT-NEXT: br label [[END]]
|
|
; TUNIT: end:
|
|
; TUNIT-NEXT: [[RET:%.*]] = phi i32 [ [[RET0]], [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ]
|
|
; TUNIT-NEXT: ret i32 1
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test2_1
|
|
; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3:[0-9]+]] {
|
|
; CGSCC-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
|
|
; CGSCC: if.true:
|
|
; CGSCC-NEXT: [[CALL:%.*]] = tail call i32 @return0() #[[ATTR12:[0-9]+]]
|
|
; CGSCC-NEXT: [[RET0:%.*]] = add i32 [[CALL]], 1
|
|
; CGSCC-NEXT: br label [[END:%.*]]
|
|
; CGSCC: if.false:
|
|
; CGSCC-NEXT: [[RET1:%.*]] = tail call i32 @return1() #[[ATTR12]]
|
|
; CGSCC-NEXT: br label [[END]]
|
|
; CGSCC: end:
|
|
; CGSCC-NEXT: [[RET:%.*]] = phi i32 [ [[RET0]], [[IF_TRUE]] ], [ [[RET1]], [[IF_FALSE]] ]
|
|
; CGSCC-NEXT: ret i32 1
|
|
;
|
|
br i1 %c, label %if.true, label %if.false
|
|
if.true:
|
|
%call = tail call i32 @return0()
|
|
%ret0 = add i32 %call, 1
|
|
br label %end
|
|
if.false:
|
|
%ret1 = tail call i32 @return1()
|
|
br label %end
|
|
end:
|
|
|
|
%ret = phi i32 [ %ret0, %if.true ], [ %ret1, %if.false ]
|
|
|
|
ret i32 1
|
|
}
|
|
|
|
|
|
|
|
define i32 @test2_2(i1 %c) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test2_2
|
|
; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i32 1
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test2_2
|
|
; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[RET:%.*]] = tail call noundef i32 @test2_1(i1 noundef [[C]]) #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i32 [[RET]]
|
|
;
|
|
%ret = tail call i32 @test2_1(i1 %c)
|
|
ret i32 %ret
|
|
}
|
|
|
|
declare void @use(i32)
|
|
define void @test3(i1 %c) {
|
|
; TUNIT-LABEL: define {{[^@]+}}@test3
|
|
; TUNIT-SAME: (i1 noundef [[C:%.*]]) {
|
|
; TUNIT-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
|
|
; TUNIT: if.true:
|
|
; TUNIT-NEXT: br label [[END:%.*]]
|
|
; TUNIT: if.false:
|
|
; TUNIT-NEXT: br label [[END]]
|
|
; TUNIT: end:
|
|
; TUNIT-NEXT: [[R:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ]
|
|
; TUNIT-NEXT: tail call void @use(i32 noundef 1)
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC-LABEL: define {{[^@]+}}@test3
|
|
; CGSCC-SAME: (i1 noundef [[C:%.*]]) {
|
|
; CGSCC-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
|
|
; CGSCC: if.true:
|
|
; CGSCC-NEXT: br label [[END:%.*]]
|
|
; CGSCC: if.false:
|
|
; CGSCC-NEXT: [[RET1:%.*]] = tail call i32 @return1() #[[ATTR13:[0-9]+]]
|
|
; CGSCC-NEXT: br label [[END]]
|
|
; CGSCC: end:
|
|
; CGSCC-NEXT: [[R:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ [[RET1]], [[IF_FALSE]] ]
|
|
; CGSCC-NEXT: tail call void @use(i32 noundef [[R]])
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
br i1 %c, label %if.true, label %if.false
|
|
if.true:
|
|
br label %end
|
|
if.false:
|
|
%ret1 = tail call i32 @return1()
|
|
br label %end
|
|
end:
|
|
|
|
%r = phi i32 [ 1, %if.true ], [ %ret1, %if.false ]
|
|
|
|
tail call void @use(i32 %r)
|
|
ret void
|
|
}
|
|
|
|
define void @test-select-phi(i1 %c) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test-select-phi
|
|
; CHECK-SAME: (i1 [[C:%.*]]) {
|
|
; CHECK-NEXT: tail call void @use(i32 noundef 1)
|
|
; CHECK-NEXT: [[SELECT_NOT_SAME:%.*]] = select i1 [[C]], i32 1, i32 0
|
|
; CHECK-NEXT: tail call void @use(i32 noundef [[SELECT_NOT_SAME]])
|
|
; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
|
|
; CHECK: if-true:
|
|
; CHECK-NEXT: br label [[END:%.*]]
|
|
; CHECK: if-false:
|
|
; CHECK-NEXT: br label [[END]]
|
|
; CHECK: end:
|
|
; CHECK-NEXT: [[PHI_SAME:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ]
|
|
; CHECK-NEXT: [[PHI_NOT_SAME:%.*]] = phi i32 [ 0, [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ]
|
|
; CHECK-NEXT: [[PHI_SAME_PROP:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ]
|
|
; CHECK-NEXT: [[PHI_SAME_UNDEF:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ undef, [[IF_FALSE]] ]
|
|
; CHECK-NEXT: [[SELECT_NOT_SAME_UNDEF:%.*]] = select i1 [[C]], i32 [[PHI_NOT_SAME]], i32 undef
|
|
; CHECK-NEXT: tail call void @use(i32 noundef 1)
|
|
; CHECK-NEXT: tail call void @use(i32 noundef [[PHI_NOT_SAME]])
|
|
; CHECK-NEXT: tail call void @use(i32 noundef 1)
|
|
; CHECK-NEXT: tail call void @use(i32 1)
|
|
; CHECK-NEXT: tail call void @use(i32 [[SELECT_NOT_SAME_UNDEF]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%select-same = select i1 %c, i32 1, i32 1
|
|
tail call void @use(i32 %select-same)
|
|
|
|
%select-not-same = select i1 %c, i32 1, i32 0
|
|
tail call void @use(i32 %select-not-same)
|
|
br i1 %c, label %if-true, label %if-false
|
|
if-true:
|
|
br label %end
|
|
if-false:
|
|
br label %end
|
|
end:
|
|
%phi-same = phi i32 [ 1, %if-true ], [ 1, %if-false ]
|
|
%phi-not-same = phi i32 [ 0, %if-true ], [ 1, %if-false ]
|
|
%phi-same-prop = phi i32 [ 1, %if-true ], [ %select-same, %if-false ]
|
|
%phi-same-undef = phi i32 [ 1, %if-true ], [ undef, %if-false ]
|
|
%select-not-same-undef = select i1 %c, i32 %phi-not-same, i32 undef
|
|
|
|
|
|
tail call void @use(i32 %phi-same)
|
|
|
|
tail call void @use(i32 %phi-not-same)
|
|
|
|
tail call void @use(i32 %phi-same-prop)
|
|
|
|
tail call void @use(i32 %phi-same-undef)
|
|
|
|
tail call void @use(i32 %select-not-same-undef)
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
define i32 @ipccp1(i32 %a) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@ipccp1
|
|
; TUNIT-SAME: (i32 returned [[A:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: br i1 true, label [[T:%.*]], label [[F:%.*]]
|
|
; TUNIT: t:
|
|
; TUNIT-NEXT: ret i32 [[A]]
|
|
; TUNIT: f:
|
|
; TUNIT-NEXT: unreachable
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp1
|
|
; CGSCC-SAME: (i32 returned [[A:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: br i1 true, label [[T:%.*]], label [[F:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: ret i32 [[A]]
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: unreachable
|
|
;
|
|
br i1 true, label %t, label %f
|
|
t:
|
|
ret i32 %a
|
|
f:
|
|
%r = call i32 @ipccp1(i32 5)
|
|
ret i32 %r
|
|
}
|
|
|
|
define internal i1 @ipccp2i(i1 %a) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp2i
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: br label [[T:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: ret i1 true
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: unreachable
|
|
;
|
|
br i1 %a, label %t, label %f
|
|
t:
|
|
ret i1 %a
|
|
f:
|
|
%r = call i1 @ipccp2i(i1 false)
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @ipccp2() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@ipccp2
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i1 true
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp2
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[R:%.*]] = call noundef i1 @ipccp2i() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i1 [[R]]
|
|
;
|
|
%r = call i1 @ipccp2i(i1 true)
|
|
ret i1 %r
|
|
}
|
|
|
|
define internal i1 @ipccp2ib(i1 %a) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp2ib
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: br label [[T:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: ret i1 true
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: unreachable
|
|
;
|
|
br i1 %a, label %t, label %f
|
|
t:
|
|
ret i1 true
|
|
f:
|
|
%r = call i1 @ipccp2ib(i1 false)
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @ipccp2b() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@ipccp2b
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i1 true
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp2b
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[R:%.*]] = call noundef i1 @ipccp2ib() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i1 [[R]]
|
|
;
|
|
%r = call i1 @ipccp2ib(i1 true)
|
|
ret i1 %r
|
|
}
|
|
|
|
define internal i32 @ipccp3i(i32 %a) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp3i
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: br label [[T:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: ret i32 7
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: unreachable
|
|
;
|
|
%c = icmp eq i32 %a, 7
|
|
br i1 %c, label %t, label %f
|
|
t:
|
|
ret i32 %a
|
|
f:
|
|
%r = call i32 @ipccp3i(i32 5)
|
|
ret i32 %r
|
|
}
|
|
|
|
define i32 @ipccp3() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@ipccp3
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i32 7
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp3
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[R:%.*]] = call noundef i32 @ipccp3i() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i32 [[R]]
|
|
;
|
|
%r = call i32 @ipccp3i(i32 7)
|
|
ret i32 %r
|
|
}
|
|
|
|
define internal i32 @ipccp4ia(i1 %c) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp4ia
|
|
; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: ret i32 0
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: ret i32 1
|
|
;
|
|
br i1 %c, label %t, label %f
|
|
t:
|
|
ret i32 0
|
|
f:
|
|
ret i32 1
|
|
}
|
|
define internal i32 @ipccp4ib(i32 %a) {
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp4ib
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: br label [[T:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: [[R:%.*]] = call noundef i32 @ipccp4ia(i1 noundef true) #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i32 [[R]]
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: unreachable
|
|
;
|
|
%c = icmp eq i32 %a, 7
|
|
br i1 %c, label %t, label %f
|
|
t:
|
|
%r = call i32 @ipccp4ia(i1 %c)
|
|
ret i32 %r
|
|
f:
|
|
ret i32 1
|
|
}
|
|
|
|
define i32 @ipccp4(i1 %c) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@ipccp4
|
|
; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
|
; TUNIT: t:
|
|
; TUNIT-NEXT: br label [[F]]
|
|
; TUNIT: f:
|
|
; TUNIT-NEXT: ret i32 0
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ipccp4
|
|
; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: br label [[F]]
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: [[R:%.*]] = call noundef i32 @ipccp4ib() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i32 [[R]]
|
|
;
|
|
br i1 %c, label %t, label %f
|
|
t:
|
|
%q = call i32 @ipccp4ia(i1 undef)
|
|
br label %f
|
|
f:
|
|
%r = call i32 @ipccp4ib(i32 7)
|
|
ret i32 %r
|
|
}
|
|
|
|
; Do not touch complicated arguments (for now)
|
|
%struct.X = type { ptr }
|
|
define internal ptr @test_inalloca(ptr inalloca(i32) %a) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_inalloca
|
|
; TUNIT-SAME: (ptr noalias nofree nonnull returned writeonly inalloca(i32) dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret ptr [[A]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_inalloca
|
|
; CGSCC-SAME: (ptr noalias nofree noundef nonnull returned writeonly inalloca(i32) dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret ptr [[A]]
|
|
;
|
|
ret ptr %a
|
|
}
|
|
define ptr @complicated_args_inalloca(ptr %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@complicated_args_inalloca
|
|
; TUNIT-SAME: (ptr nofree nonnull readnone "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: [[CALL:%.*]] = call nonnull dereferenceable(4) ptr @test_inalloca(ptr noalias nofree nonnull writeonly inalloca(i32) "no-capture-maybe-returned" [[ARG]]) #[[ATTR9:[0-9]+]]
|
|
; TUNIT-NEXT: ret ptr [[CALL]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@complicated_args_inalloca
|
|
; CGSCC-SAME: (ptr nofree noundef nonnull readnone dereferenceable(4) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call noalias noundef nonnull dereferenceable(4) ptr @test_inalloca(ptr noalias nofree noundef nonnull writeonly inalloca(i32) dereferenceable(4) [[ARG]]) #[[ATTR12]]
|
|
; CGSCC-NEXT: ret ptr [[CALL]]
|
|
;
|
|
%call = call ptr @test_inalloca(ptr inalloca(i32) %arg)
|
|
ret ptr %call
|
|
}
|
|
|
|
define internal ptr @test_preallocated(ptr preallocated(i32) %a) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_preallocated
|
|
; TUNIT-SAME: (ptr noalias nofree noundef nonnull returned writeonly preallocated(i32) align 4294967296 dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret ptr [[A]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_preallocated
|
|
; CGSCC-SAME: (ptr noalias nofree noundef nonnull returned writeonly preallocated(i32) align 4294967296 dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret ptr [[A]]
|
|
;
|
|
ret ptr %a
|
|
}
|
|
define ptr @complicated_args_preallocated() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
|
|
; TUNIT-LABEL: define {{[^@]+}}@complicated_args_preallocated
|
|
; TUNIT-SAME: () #[[ATTR3:[0-9]+]] {
|
|
; TUNIT-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR10:[0-9]+]]
|
|
; TUNIT-NEXT: [[CALL:%.*]] = call noundef nonnull align 4294967296 dereferenceable(4) ptr @test_preallocated(ptr nofree noundef writeonly preallocated(i32) null) #[[ATTR9]] [ "preallocated"(token [[C]]) ]
|
|
; TUNIT-NEXT: ret ptr [[CALL]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
|
|
; CGSCC-LABEL: define {{[^@]+}}@complicated_args_preallocated
|
|
; CGSCC-SAME: () #[[ATTR4:[0-9]+]] {
|
|
; CGSCC-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR13]]
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call ptr @test_preallocated(ptr nofree noundef writeonly preallocated(i32) null) #[[ATTR14:[0-9]+]] [ "preallocated"(token [[C]]) ]
|
|
; CGSCC-NEXT: unreachable
|
|
;
|
|
%c = call token @llvm.call.preallocated.setup(i32 1)
|
|
%call = call ptr @test_preallocated(ptr preallocated(i32) null) ["preallocated"(token %c)]
|
|
ret ptr %call
|
|
}
|
|
|
|
define internal void @test_sret(ptr sret(%struct.X) %a, ptr %b) {
|
|
;
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_sret
|
|
; TUNIT-SAME: (ptr noalias nofree noundef writeonly sret([[STRUCT_X:%.*]]) align 4294967296 dereferenceable_or_null(8) [[A:%.*]], ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[B:%.*]]) #[[ATTR4:[0-9]+]] {
|
|
; TUNIT-NEXT: store ptr [[A]], ptr [[B]], align 8
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_sret
|
|
; CGSCC-SAME: (ptr noalias nofree noundef writeonly sret([[STRUCT_X:%.*]]) align 4294967296 dereferenceable_or_null(8) [[A:%.*]], ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[B:%.*]]) #[[ATTR5:[0-9]+]] {
|
|
; CGSCC-NEXT: store ptr [[A]], ptr [[B]], align 8
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
store ptr %a, ptr %b
|
|
ret void
|
|
}
|
|
; FIXME: Alignment and dereferenceability are not propagated to the argument
|
|
define void @complicated_args_sret(ptr %b) {
|
|
;
|
|
;
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@complicated_args_sret
|
|
; TUNIT-SAME: (ptr nofree writeonly captures(none) [[B:%.*]]) #[[ATTR4]] {
|
|
; TUNIT-NEXT: call void @test_sret(ptr nofree noundef writeonly sret([[STRUCT_X:%.*]]) null, ptr nofree noundef writeonly align 8 captures(none) [[B]]) #[[ATTR11:[0-9]+]]
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: write)
|
|
; CGSCC-LABEL: define {{[^@]+}}@complicated_args_sret
|
|
; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[B:%.*]]) #[[ATTR6:[0-9]+]] {
|
|
; CGSCC-NEXT: call void @test_sret(ptr nofree noundef writeonly sret([[STRUCT_X:%.*]]) dereferenceable_or_null(8) null, ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[B]]) #[[ATTR15:[0-9]+]]
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
call void @test_sret(ptr sret(%struct.X) null, ptr %b)
|
|
ret void
|
|
}
|
|
|
|
define internal ptr @test_nest(ptr nest %a) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_nest
|
|
; CGSCC-SAME: (ptr nest noalias nofree readnone align 4294967296 captures(none) [[A:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret ptr null
|
|
;
|
|
ret ptr %a
|
|
}
|
|
define ptr @complicated_args_nest() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@complicated_args_nest
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret ptr null
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@complicated_args_nest
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call noalias noundef align 4294967296 ptr @test_nest(ptr nofree noundef readnone null) #[[ATTR12]]
|
|
; CGSCC-NEXT: ret ptr [[CALL]]
|
|
;
|
|
%call = call ptr @test_nest(ptr null)
|
|
ret ptr %call
|
|
}
|
|
|
|
@S = external global %struct.X
|
|
define internal void @test_byval(ptr byval(%struct.X) %a) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_byval
|
|
; TUNIT-SAME: (ptr [[TMP0:%.*]]) #[[ATTR4]] {
|
|
; TUNIT-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8
|
|
; TUNIT-NEXT: store ptr [[TMP0]], ptr [[A_PRIV]], align 8
|
|
; TUNIT-NEXT: store ptr null, ptr [[A_PRIV]], align 8
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_byval
|
|
; CGSCC-SAME: (ptr nofree [[TMP0:%.*]]) #[[ATTR5]] {
|
|
; CGSCC-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8
|
|
; CGSCC-NEXT: store ptr [[TMP0]], ptr [[A_PRIV]], align 8
|
|
; CGSCC-NEXT: store ptr null, ptr [[A_PRIV]], align 8
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
store ptr null, ptr %a
|
|
ret void
|
|
}
|
|
define void @complicated_args_byval() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@complicated_args_byval
|
|
; TUNIT-SAME: () #[[ATTR5:[0-9]+]] {
|
|
; TUNIT-NEXT: [[TMP1:%.*]] = load ptr, ptr @S, align 8
|
|
; TUNIT-NEXT: call void @test_byval(ptr [[TMP1]]) #[[ATTR11]]
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
|
|
; CGSCC-LABEL: define {{[^@]+}}@complicated_args_byval
|
|
; CGSCC-SAME: () #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[TMP1:%.*]] = load ptr, ptr @S, align 8
|
|
; CGSCC-NEXT: call void @test_byval(ptr nofree writeonly [[TMP1]]) #[[ATTR15]]
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
call void @test_byval(ptr byval(%struct.X) @S)
|
|
ret void
|
|
}
|
|
|
|
declare void @sync()
|
|
; Make sure we *do not* load @S here!
|
|
define internal ptr @test_byval2(ptr byval(%struct.X) %a) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test_byval2
|
|
; CHECK-SAME: (ptr [[TMP0:%.*]]) {
|
|
; CHECK-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8
|
|
; CHECK-NEXT: store ptr [[TMP0]], ptr [[A_PRIV]], align 8
|
|
; CHECK-NEXT: call void @sync()
|
|
; CHECK-NEXT: [[L:%.*]] = load ptr, ptr [[A_PRIV]], align 8
|
|
; CHECK-NEXT: ret ptr [[L]]
|
|
;
|
|
call void @sync()
|
|
%l = load ptr, ptr %a
|
|
ret ptr %l
|
|
}
|
|
define ptr @complicated_args_byval2() {
|
|
;
|
|
; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval2() {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @S, align 8
|
|
; CHECK-NEXT: [[C:%.*]] = call ptr @test_byval2(ptr [[TMP1]])
|
|
; CHECK-NEXT: ret ptr [[C]]
|
|
;
|
|
%c = call ptr @test_byval2(ptr byval(%struct.X) @S)
|
|
ret ptr %c
|
|
}
|
|
|
|
define void @fixpoint_changed(ptr %p) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@fixpoint_changed
|
|
; TUNIT-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR4]] {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: br label [[FOR_COND:%.*]]
|
|
; TUNIT: for.cond:
|
|
; TUNIT-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ]
|
|
; TUNIT-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30
|
|
; TUNIT-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
|
|
; TUNIT: for.body:
|
|
; TUNIT-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [
|
|
; TUNIT-NEXT: i32 1, label [[SW_BB:%.*]]
|
|
; TUNIT-NEXT: ]
|
|
; TUNIT: sw.bb:
|
|
; TUNIT-NEXT: br label [[SW_EPILOG]]
|
|
; TUNIT: sw.epilog:
|
|
; TUNIT-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ]
|
|
; TUNIT-NEXT: store i32 [[X_0]], ptr [[P]], align 4
|
|
; TUNIT-NEXT: [[INC]] = add nsw i32 [[J_0]], 1
|
|
; TUNIT-NEXT: br label [[FOR_COND]]
|
|
; TUNIT: for.end:
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; CGSCC-LABEL: define {{[^@]+}}@fixpoint_changed
|
|
; CGSCC-SAME: (ptr nofree writeonly captures(none) [[P:%.*]]) #[[ATTR5]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: br label [[FOR_COND:%.*]]
|
|
; CGSCC: for.cond:
|
|
; CGSCC-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ]
|
|
; CGSCC-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30
|
|
; CGSCC-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
|
|
; CGSCC: for.body:
|
|
; CGSCC-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [
|
|
; CGSCC-NEXT: i32 1, label [[SW_BB:%.*]]
|
|
; CGSCC-NEXT: ]
|
|
; CGSCC: sw.bb:
|
|
; CGSCC-NEXT: br label [[SW_EPILOG]]
|
|
; CGSCC: sw.epilog:
|
|
; CGSCC-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ]
|
|
; CGSCC-NEXT: store i32 [[X_0]], ptr [[P]], align 4
|
|
; CGSCC-NEXT: [[INC]] = add nsw i32 [[J_0]], 1
|
|
; CGSCC-NEXT: br label [[FOR_COND]]
|
|
; CGSCC: for.end:
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond:
|
|
%j.0 = phi i32 [ 0, %entry ], [ %inc, %sw.epilog ]
|
|
%cmp = icmp slt i32 %j.0, 30
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
for.body:
|
|
switch i32 %j.0, label %sw.epilog [
|
|
i32 1, label %sw.bb
|
|
]
|
|
|
|
sw.bb:
|
|
br label %sw.epilog
|
|
|
|
sw.epilog:
|
|
%x.0 = phi i32 [ 255, %for.body ], [ 253, %sw.bb ]
|
|
store i32 %x.0, ptr %p
|
|
%inc = add nsw i32 %j.0, 1
|
|
br label %for.cond
|
|
|
|
for.end:
|
|
ret void
|
|
}
|
|
|
|
; Check we merge undef and a constant properly.
|
|
define i8 @caller0() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@caller0
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i8 49
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@caller0
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i8 [[C]]
|
|
;
|
|
%c = call i8 @callee(i8 undef)
|
|
ret i8 %c
|
|
}
|
|
define i8 @caller1() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@caller1
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i8 49
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@caller1
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i8 [[C]]
|
|
;
|
|
%c = call i8 @callee(i8 undef)
|
|
ret i8 %c
|
|
}
|
|
define i8 @caller2() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@caller2
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i8 49
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@caller2
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i8 [[C]]
|
|
;
|
|
%c = call i8 @callee(i8 undef)
|
|
ret i8 %c
|
|
}
|
|
define i8 @caller_middle() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@caller_middle
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i8 49
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@caller_middle
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i8 [[C]]
|
|
;
|
|
%c = call i8 @callee(i8 42)
|
|
ret i8 %c
|
|
}
|
|
define i8 @caller3() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@caller3
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i8 49
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@caller3
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i8 [[C]]
|
|
;
|
|
%c = call i8 @callee(i8 undef)
|
|
ret i8 %c
|
|
}
|
|
define i8 @caller4() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@caller4
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i8 49
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@caller4
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i8 [[C]]
|
|
;
|
|
%c = call i8 @callee(i8 undef)
|
|
ret i8 %c
|
|
}
|
|
define internal i8 @callee(i8 %a) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@callee
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret i8 49
|
|
;
|
|
%c = add i8 %a, 7
|
|
ret i8 %c
|
|
}
|
|
|
|
define void @user_as3() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@user_as3
|
|
; TUNIT-SAME: () #[[ATTR5]] {
|
|
; TUNIT-NEXT: store i32 0, ptr addrspace(3) @ConstAS3Ptr, align 4
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
|
|
; CGSCC-LABEL: define {{[^@]+}}@user_as3
|
|
; CGSCC-SAME: () #[[ATTR7:[0-9]+]] {
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call fastcc align 4 ptr addrspace(3) @const_ptr_return_as3() #[[ATTR12]]
|
|
; CGSCC-NEXT: store i32 0, ptr addrspace(3) [[CALL]], align 4
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
%call = call fastcc ptr addrspace(3) @const_ptr_return_as3()
|
|
store i32 0, ptr addrspace(3) %call
|
|
ret void
|
|
}
|
|
define void @user() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@user
|
|
; TUNIT-SAME: () #[[ATTR5]] {
|
|
; TUNIT-NEXT: store i32 0, ptr addrspacecast (ptr addrspace(3) @ConstAS3Ptr to ptr), align 4
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
|
|
; CGSCC-LABEL: define {{[^@]+}}@user
|
|
; CGSCC-SAME: () #[[ATTR7]] {
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call fastcc align 4 ptr @const_ptr_return() #[[ATTR12]]
|
|
; CGSCC-NEXT: store i32 0, ptr [[CALL]], align 4
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
%call = call fastcc ptr @const_ptr_return()
|
|
store i32 0, ptr %call
|
|
ret void
|
|
}
|
|
|
|
|
|
define i1 @test_merge_with_undef_values_ptr(i1 %c) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_merge_with_undef_values_ptr
|
|
; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i1 false
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_merge_with_undef_values_ptr
|
|
; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[R1:%.*]] = call i1 @undef_then_null(i1 [[C]]) #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i1 [[R1]]
|
|
;
|
|
%r1 = call i1 @undef_then_null(i1 %c, ptr undef, ptr undef)
|
|
ret i1 %r1
|
|
}
|
|
define internal i1 @undef_then_null(i1 %c, ptr %i32Aptr, ptr %i32Bptr) {
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@undef_then_null
|
|
; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[OR:%.*]] = or i1 false, [[C]]
|
|
; CGSCC-NEXT: br i1 [[OR]], label [[A:%.*]], label [[B:%.*]]
|
|
; CGSCC: a:
|
|
; CGSCC-NEXT: ret i1 false
|
|
; CGSCC: b:
|
|
; CGSCC-NEXT: ret i1 false
|
|
;
|
|
%cmp1 = icmp eq ptr %i32Aptr, %i32Bptr
|
|
%cmp2 = icmp eq i1 %cmp1, false
|
|
%or = or i1 %cmp2, %c
|
|
br i1 %or, label %a, label %b
|
|
a:
|
|
%r2 = call i1 @undef_then_null(i1 false, ptr null, ptr null)
|
|
ret i1 %r2
|
|
b:
|
|
ret i1 %cmp2
|
|
}
|
|
|
|
define i1 @test_merge_with_undef_values(i1 %c) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_merge_with_undef_values
|
|
; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i1 false
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_merge_with_undef_values
|
|
; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[R1:%.*]] = call i1 @undef_then_1(i1 [[C]]) #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i1 [[R1]]
|
|
;
|
|
%r1 = call i1 @undef_then_1(i1 %c, i32 undef, i32 undef)
|
|
ret i1 %r1
|
|
}
|
|
define internal i1 @undef_then_1(i1 %c, i32 %i32A, i32 %i32B) {
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@undef_then_1
|
|
; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[OR:%.*]] = or i1 false, [[C]]
|
|
; CGSCC-NEXT: br i1 [[OR]], label [[A:%.*]], label [[B:%.*]]
|
|
; CGSCC: a:
|
|
; CGSCC-NEXT: ret i1 false
|
|
; CGSCC: b:
|
|
; CGSCC-NEXT: ret i1 false
|
|
;
|
|
%cmp1 = icmp eq i32 %i32A, %i32B
|
|
%cmp2 = icmp eq i1 %cmp1, false
|
|
%or = or i1 %cmp2, %c
|
|
br i1 %or, label %a, label %b
|
|
a:
|
|
%r2 = call i1 @undef_then_1(i1 false, i32 1, i32 1)
|
|
ret i1 %r2
|
|
b:
|
|
ret i1 %cmp2
|
|
}
|
|
|
|
define i32 @test_select(i32 %c) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_select
|
|
; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i32 42
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_select
|
|
; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call noundef i32 @select() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i32 [[CALL]]
|
|
;
|
|
%call = call i32 @select(i1 1, i32 42, i32 %c)
|
|
ret i32 %call
|
|
}
|
|
|
|
define internal i32 @select(i1 %a, i32 %b, i32 %c) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@select
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret i32 42
|
|
;
|
|
%s = select i1 %a, i32 %b, i32 %c
|
|
ret i32 %s
|
|
}
|
|
|
|
define i1 @icmp() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@icmp
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i1 true
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@icmp
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret i1 true
|
|
;
|
|
%c = icmp eq ptr null, null
|
|
ret i1 %c
|
|
}
|
|
|
|
define void @test_callee_is_undef(ptr %fn) {
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_callee_is_undef
|
|
; TUNIT-SAME: (ptr nofree captures(none) [[FN:%.*]]) {
|
|
; TUNIT-NEXT: call void @unknown_calle_arg_is_undef(ptr nofree noundef captures(none) [[FN]])
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_callee_is_undef
|
|
; CGSCC-SAME: (ptr nofree noundef nonnull captures(none) [[FN:%.*]]) {
|
|
; CGSCC-NEXT: call void @unknown_calle_arg_is_undef(ptr nofree noundef nonnull captures(none) [[FN]])
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
call void @callee_is_undef(ptr undef)
|
|
call void @unknown_calle_arg_is_undef(ptr %fn, i32 undef)
|
|
ret void
|
|
}
|
|
define internal void @callee_is_undef(ptr %fn) {
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@callee_is_undef
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: unreachable
|
|
;
|
|
call void %fn()
|
|
ret void
|
|
}
|
|
define internal void @unknown_calle_arg_is_undef(ptr %fn, i32 %arg) {
|
|
;
|
|
; CHECK-LABEL: define {{[^@]+}}@unknown_calle_arg_is_undef
|
|
; CHECK-SAME: (ptr nofree noundef nonnull captures(none) [[FN:%.*]]) {
|
|
; CHECK-NEXT: call void [[FN]](i32 undef)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void %fn(i32 %arg)
|
|
ret void
|
|
}
|
|
|
|
; Taken from 50683
|
|
; {{{
|
|
|
|
@g = internal constant { [2 x ptr] } { [2 x ptr] [ptr @f1, ptr @f2] }
|
|
|
|
define internal void @f1(ptr %a) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@f1
|
|
; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[A:%.*]]) #[[ATTR4]] {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: store ptr @g, ptr [[A]], align 8
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; CGSCC-LABEL: define {{[^@]+}}@f1
|
|
; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[A:%.*]]) #[[ATTR5]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: store ptr @g, ptr [[A]], align 8
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
entry:
|
|
store ptr @g , ptr %a, align 8
|
|
ret void
|
|
}
|
|
|
|
define internal void @f2(ptr %a) {
|
|
; CHECK-LABEL: define {{[^@]+}}@f2
|
|
; CHECK-SAME: (ptr [[A:%.*]]) {
|
|
; CHECK-NEXT: cont461:
|
|
; CHECK-NEXT: call void @f3(ptr [[A]], ptr nofree captures(none) [[A]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
cont461:
|
|
call void @f3(ptr %a, ptr %a)
|
|
ret void
|
|
}
|
|
|
|
define internal void @f3(ptr %a1, ptr %a) {
|
|
; CHECK-LABEL: define {{[^@]+}}@f3
|
|
; CHECK-SAME: (ptr [[A1:%.*]], ptr nofree captures(none) [[A:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL20:%.*]] = call i1 @f9()
|
|
; CHECK-NEXT: br i1 [[CALL20]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END40:%.*]]
|
|
; CHECK: land.lhs.true:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = call i1 [[A]](ptr [[A1]])
|
|
; CHECK-NEXT: br label [[IF_END40]]
|
|
; CHECK: if.end40:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%call20 = call i1 @f9()
|
|
br i1 %call20, label %land.lhs.true, label %if.end40
|
|
|
|
land.lhs.true:
|
|
call i1 %a(ptr %a1)
|
|
br label %if.end40
|
|
|
|
if.end40:
|
|
ret void
|
|
}
|
|
|
|
define linkonce_odr i1 @f9() {
|
|
; CHECK-LABEL: define {{[^@]+}}@f9() {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
ret i1 false
|
|
}
|
|
|
|
; }}}
|
|
|
|
|
|
define i1 @test_cmp_null_after_cast() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_cmp_null_after_cast
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i1 true
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_cmp_null_after_cast
|
|
; CGSCC-SAME: () #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[C:%.*]] = call noundef i1 @cmp_null_after_cast() #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i1 [[C]]
|
|
;
|
|
%c = call i1 @cmp_null_after_cast(i32 0, i8 0)
|
|
ret i1 %c
|
|
}
|
|
define internal i1 @cmp_null_after_cast(i32 %a, i8 %b) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@cmp_null_after_cast
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret i1 true
|
|
;
|
|
%t = trunc i32 %a to i8
|
|
%c = icmp eq i8 %t, %b
|
|
ret i1 %c
|
|
}
|
|
|
|
|
|
declare ptr @m()
|
|
|
|
define i32 @test(i1 %c) {
|
|
; TUNIT-LABEL: define {{[^@]+}}@test
|
|
; TUNIT-SAME: (i1 [[C:%.*]]) {
|
|
; TUNIT-NEXT: [[R1:%.*]] = call i32 @ctx_test1(i1 noundef [[C]])
|
|
; TUNIT-NEXT: [[R2:%.*]] = call i32 @ctx_test2(i1 noundef [[C]]), !range [[RNG0:![0-9]+]]
|
|
; TUNIT-NEXT: [[ADD:%.*]] = add i32 [[R1]], [[R2]]
|
|
; TUNIT-NEXT: ret i32 [[ADD]]
|
|
;
|
|
; CGSCC-LABEL: define {{[^@]+}}@test
|
|
; CGSCC-SAME: (i1 noundef [[C:%.*]]) {
|
|
; CGSCC-NEXT: [[R1:%.*]] = call i32 @ctx_test1(i1 noundef [[C]])
|
|
; CGSCC-NEXT: [[R2:%.*]] = call i32 @ctx_test2(i1 noundef [[C]])
|
|
; CGSCC-NEXT: [[ADD:%.*]] = add i32 [[R1]], [[R2]]
|
|
; CGSCC-NEXT: ret i32 [[ADD]]
|
|
;
|
|
%r1 = call i32 @ctx_test1(i1 %c)
|
|
%r2 = call i32 @ctx_test2(i1 %c)
|
|
%add = add i32 %r1, %r2
|
|
ret i32 %add
|
|
}
|
|
|
|
define internal i32 @ctx_test1(i1 %c) {
|
|
; CHECK-LABEL: define {{[^@]+}}@ctx_test1
|
|
; CHECK-SAME: (i1 noundef [[C:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[JOIN:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[M:%.*]] = tail call ptr @m()
|
|
; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[M]] to i64
|
|
; CHECK-NEXT: br label [[JOIN]]
|
|
; CHECK: join:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[I]], [[THEN]] ], [ undef, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[RET:%.*]] = trunc i64 [[PHI]] to i32
|
|
; CHECK-NEXT: ret i32 [[RET]]
|
|
;
|
|
entry:
|
|
br i1 %c, label %then, label %join
|
|
|
|
then:
|
|
%m = tail call ptr @m()
|
|
%i = ptrtoint ptr %m to i64
|
|
br label %join
|
|
|
|
join:
|
|
%phi = phi i64 [ %i, %then ], [ undef, %entry ]
|
|
%ret = trunc i64 %phi to i32
|
|
ret i32 %ret
|
|
}
|
|
|
|
define internal i32 @ctx_test2(i1 %c) {
|
|
; CHECK-LABEL: define {{[^@]+}}@ctx_test2
|
|
; CHECK-SAME: (i1 noundef [[C:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[JOIN:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[M:%.*]] = tail call ptr @m()
|
|
; CHECK-NEXT: [[I:%.*]] = ptrtoint ptr [[M]] to i32
|
|
; CHECK-NEXT: br label [[JOIN]]
|
|
; CHECK: join:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[I]], [[THEN]] ], [ undef, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[RET:%.*]] = lshr i32 [[PHI]], 1
|
|
; CHECK-NEXT: ret i32 [[RET]]
|
|
;
|
|
entry:
|
|
br i1 %c, label %then, label %join
|
|
|
|
then:
|
|
%m = tail call ptr @m()
|
|
%i = ptrtoint ptr %m to i32
|
|
br label %join
|
|
|
|
join:
|
|
%phi = phi i32 [ %i, %then ], [ undef, %entry ]
|
|
%ret = lshr i32 %phi, 1
|
|
ret i32 %ret
|
|
|
|
uselistorder label %join, { 1, 0 }
|
|
}
|
|
|
|
define i1 @test_liveness(i1 %c) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_liveness
|
|
; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
|
; TUNIT: t:
|
|
; TUNIT-NEXT: br label [[F]]
|
|
; TUNIT: f:
|
|
; TUNIT-NEXT: ret i1 false
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_liveness
|
|
; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: br label [[F]]
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: [[P:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[T]] ]
|
|
; CGSCC-NEXT: [[RC1:%.*]] = call noundef i1 @ret(i1 noundef [[P]]) #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i1 [[RC1]]
|
|
;
|
|
entry:
|
|
br i1 %c, label %t, label %f
|
|
t:
|
|
br label %f
|
|
f:
|
|
%p = phi i1 [true, %entry], [false, %t]
|
|
%rc1 = call i1 @ret(i1 %p)
|
|
ret i1 %rc1
|
|
}
|
|
|
|
define internal i1 @ret(i1 %c) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ret
|
|
; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: br label [[F]]
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: [[P:%.*]] = phi i1 [ [[C]], [[ENTRY:%.*]] ], [ false, [[T]] ]
|
|
; CGSCC-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
br i1 %c, label %t, label %f
|
|
t:
|
|
br label %f
|
|
f:
|
|
%p = phi i1 [%c, %entry], [false, %t]
|
|
ret i1 %p
|
|
}
|
|
|
|
declare ptr @unknown()
|
|
define internal i8 @dead_ret() {
|
|
; CHECK-LABEL: define {{[^@]+}}@dead_ret() {
|
|
; CHECK-NEXT: [[R:%.*]] = call ptr @unknown()
|
|
; CHECK-NEXT: ret i8 undef
|
|
;
|
|
%r = call ptr @unknown()
|
|
%l = load i8, ptr %r
|
|
ret i8 %l
|
|
}
|
|
|
|
define void @dead_ret_caller() {
|
|
; CHECK-LABEL: define {{[^@]+}}@dead_ret_caller() {
|
|
; CHECK-NEXT: [[R:%.*]] = call i8 @dead_ret()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%r = call i8 @dead_ret()
|
|
ret void
|
|
}
|
|
|
|
declare void @llvm.memcpy(ptr %dest, ptr %src, i32 %len, i1 %isvolatile)
|
|
define internal i8 @memcpy_uses_store(i8 %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@memcpy_uses_store
|
|
; TUNIT-SAME: (i8 [[ARG:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: [[SRC:%.*]] = alloca i8, align 1
|
|
; TUNIT-NEXT: [[DST:%.*]] = alloca i8, align 1
|
|
; TUNIT-NEXT: store i8 [[ARG]], ptr [[SRC]], align 1
|
|
; TUNIT-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[DST]], ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[SRC]], i32 noundef 1, i1 noundef false) #[[ATTR12:[0-9]+]]
|
|
; TUNIT-NEXT: [[L:%.*]] = load i8, ptr [[DST]], align 1
|
|
; TUNIT-NEXT: ret i8 [[L]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@memcpy_uses_store
|
|
; CGSCC-SAME: (i8 [[ARG:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: [[SRC:%.*]] = alloca i8, align 1
|
|
; CGSCC-NEXT: [[DST:%.*]] = alloca i8, align 1
|
|
; CGSCC-NEXT: store i8 [[ARG]], ptr [[SRC]], align 1
|
|
; CGSCC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[DST]], ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[SRC]], i32 noundef 1, i1 noundef false) #[[ATTR16:[0-9]+]]
|
|
; CGSCC-NEXT: [[L:%.*]] = load i8, ptr [[DST]], align 1
|
|
; CGSCC-NEXT: ret i8 [[L]]
|
|
;
|
|
%src = alloca i8
|
|
%dst = alloca i8
|
|
store i8 %arg, ptr %src
|
|
call void @llvm.memcpy(ptr %dst, ptr %src, i32 1, i1 false)
|
|
%l = load i8, ptr %dst
|
|
ret i8 %l
|
|
}
|
|
|
|
define i8 @memcpy_uses_store_caller(i8 %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@memcpy_uses_store_caller
|
|
; TUNIT-SAME: (i8 [[ARG:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: [[R:%.*]] = call i8 @memcpy_uses_store(i8 [[ARG]]) #[[ATTR13:[0-9]+]]
|
|
; TUNIT-NEXT: ret i8 [[R]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@memcpy_uses_store_caller
|
|
; CGSCC-SAME: (i8 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[R:%.*]] = call i8 @memcpy_uses_store(i8 [[ARG]]) #[[ATTR12]]
|
|
; CGSCC-NEXT: ret i8 [[R]]
|
|
;
|
|
%r = call i8 @memcpy_uses_store(i8 %arg)
|
|
ret i8 %r
|
|
}
|
|
|
|
|
|
declare i32 @speculatable() speculatable readnone
|
|
|
|
define i32 @test_speculatable_expr() norecurse {
|
|
; TUNIT: Function Attrs: norecurse nosync memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@test_speculatable_expr
|
|
; TUNIT-SAME: () #[[ATTR7:[0-9]+]] {
|
|
; TUNIT-NEXT: [[STACK:%.*]] = alloca i32, align 4
|
|
; TUNIT-NEXT: [[SPEC_RESULT:%.*]] = call i32 @speculatable() #[[ATTR14:[0-9]+]]
|
|
; TUNIT-NEXT: [[PLUS1:%.*]] = add i32 [[SPEC_RESULT]], 1
|
|
; TUNIT-NEXT: store i32 [[PLUS1]], ptr [[STACK]], align 4
|
|
; TUNIT-NEXT: [[TMP1:%.*]] = load i32, ptr [[STACK]], align 4
|
|
; TUNIT-NEXT: [[RSPEC:%.*]] = call i32 @ret_speculatable_expr(i32 [[TMP1]]) #[[ATTR15:[0-9]+]]
|
|
; TUNIT-NEXT: ret i32 [[RSPEC]]
|
|
;
|
|
; CGSCC: Function Attrs: norecurse nosync memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@test_speculatable_expr
|
|
; CGSCC-SAME: () #[[ATTR9:[0-9]+]] {
|
|
; CGSCC-NEXT: [[STACK:%.*]] = alloca i32, align 4
|
|
; CGSCC-NEXT: [[SPEC_RESULT:%.*]] = call i32 @speculatable() #[[ATTR17:[0-9]+]]
|
|
; CGSCC-NEXT: [[PLUS1:%.*]] = add i32 [[SPEC_RESULT]], 1
|
|
; CGSCC-NEXT: store i32 [[PLUS1]], ptr [[STACK]], align 4
|
|
; CGSCC-NEXT: [[RSPEC:%.*]] = call i32 @ret_speculatable_expr(i32 [[PLUS1]]) #[[ATTR17]]
|
|
; CGSCC-NEXT: ret i32 [[RSPEC]]
|
|
;
|
|
%stack = alloca i32
|
|
%spec_result = call i32 @speculatable()
|
|
%plus1 = add i32 %spec_result, 1
|
|
store i32 %plus1, ptr %stack
|
|
%rspec = call i32 @ret_speculatable_expr(ptr %stack, i32 13)
|
|
ret i32 %rspec
|
|
}
|
|
|
|
define internal i32 @ret_speculatable_expr(ptr %mem, i32 %a2) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@ret_speculatable_expr
|
|
; TUNIT-SAME: (i32 [[TMP0:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: [[MEM_PRIV:%.*]] = alloca i32, align 4
|
|
; TUNIT-NEXT: store i32 [[TMP0]], ptr [[MEM_PRIV]], align 4
|
|
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr [[MEM_PRIV]], align 4
|
|
; TUNIT-NEXT: [[MUL:%.*]] = mul i32 [[L]], 13
|
|
; TUNIT-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 7
|
|
; TUNIT-NEXT: ret i32 [[ADD]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@ret_speculatable_expr
|
|
; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: [[MEM_PRIV:%.*]] = alloca i32, align 4
|
|
; CGSCC-NEXT: store i32 [[TMP0]], ptr [[MEM_PRIV]], align 4
|
|
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr [[MEM_PRIV]], align 4
|
|
; CGSCC-NEXT: [[MUL:%.*]] = mul i32 [[L]], 13
|
|
; CGSCC-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 7
|
|
; CGSCC-NEXT: ret i32 [[ADD]]
|
|
;
|
|
%l = load i32, ptr %mem
|
|
%mul = mul i32 %l, %a2
|
|
%add = add i32 %mul, 7
|
|
ret i32 %add
|
|
}
|
|
|
|
define internal void @not_called1() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@not_called1
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@not_called1
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
define internal void @not_called2() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@not_called2
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@not_called2
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
define internal void @not_called3() {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@not_called3
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
declare void @useFnDecl(ptr addrspace(42));
|
|
define void @useFnDef(ptr addrspace(42) %arg) {
|
|
; CHECK-LABEL: define {{[^@]+}}@useFnDef
|
|
; CHECK-SAME: (ptr addrspace(42) [[ARG:%.*]]) {
|
|
; CHECK-NEXT: call void @useFnDecl(ptr addrspace(42) [[ARG]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void @useFnDecl(ptr addrspace(42) %arg)
|
|
ret void
|
|
}
|
|
define i1 @user_of_not_called() {
|
|
; CHECK-LABEL: define {{[^@]+}}@user_of_not_called() {
|
|
; CHECK-NEXT: call void @useFnDecl(ptr addrspace(42) noundef nonnull addrspacecast (ptr @not_called1 to ptr addrspace(42)))
|
|
; CHECK-NEXT: call void @useFnDef(ptr addrspace(42) noundef nonnull addrspacecast (ptr @not_called2 to ptr addrspace(42)))
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
call void @useFnDecl(ptr addrspace(42) addrspacecast (ptr @not_called1 to ptr addrspace(42)))
|
|
call void @useFnDef(ptr addrspace(42) addrspacecast (ptr @not_called2 to ptr addrspace(42)))
|
|
%cmp = icmp eq ptr addrspace(42) addrspacecast (ptr @not_called3 to ptr addrspace(42)), null
|
|
ret i1 %cmp
|
|
}
|
|
|
|
@x = external global i32
|
|
define internal void @indirect() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
|
|
; TUNIT-LABEL: define {{[^@]+}}@indirect
|
|
; TUNIT-SAME: () #[[ATTR5]] {
|
|
; TUNIT-NEXT: store i32 0, ptr @x, align 4
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
|
|
; CGSCC-LABEL: define {{[^@]+}}@indirect
|
|
; CGSCC-SAME: () #[[ATTR10:[0-9]+]] {
|
|
; CGSCC-NEXT: store i32 0, ptr @x, align 4
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
store i32 0, ptr @x
|
|
ret void
|
|
}
|
|
|
|
define internal void @broker(ptr %ptr) {
|
|
; TUNIT: Function Attrs: memory(readwrite, argmem: none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@broker
|
|
; TUNIT-SAME: () #[[ATTR1]] {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: call void @indirect() #[[ATTR16:[0-9]+]]
|
|
; TUNIT-NEXT: call void @unknown()
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: memory(readwrite, argmem: none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@broker
|
|
; CGSCC-SAME: () #[[ATTR2]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: call void @indirect() #[[ATTR18:[0-9]+]]
|
|
; CGSCC-NEXT: call void @unknown()
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
entry:
|
|
call void %ptr()
|
|
call void @unknown()
|
|
ret void
|
|
}
|
|
|
|
define void @entry() {
|
|
; CHECK-LABEL: define {{[^@]+}}@entry() {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: call void @broker()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
call void @broker(ptr @indirect)
|
|
ret void
|
|
}
|
|
|
|
define i8 @switch(i1 %c1, i1 %c2) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@switch
|
|
; TUNIT-SAME: (i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR2]] {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: br i1 [[C1]], label [[T:%.*]], label [[F:%.*]]
|
|
; TUNIT: t:
|
|
; TUNIT-NEXT: br label [[M:%.*]]
|
|
; TUNIT: f:
|
|
; TUNIT-NEXT: br label [[M]]
|
|
; TUNIT: m:
|
|
; TUNIT-NEXT: [[J:%.*]] = phi i32 [ 0, [[T]] ], [ 4, [[F]] ]
|
|
; TUNIT-NEXT: switch i32 [[J]], label [[DEFAULT1:%.*]] [
|
|
; TUNIT-NEXT: i32 1, label [[DEAD1:%.*]]
|
|
; TUNIT-NEXT: i32 2, label [[DEAD2:%.*]]
|
|
; TUNIT-NEXT: i32 3, label [[DEAD3:%.*]]
|
|
; TUNIT-NEXT: i32 4, label [[ALIVE1:%.*]]
|
|
; TUNIT-NEXT: ]
|
|
; TUNIT: default1:
|
|
; TUNIT-NEXT: br label [[ALIVE1]]
|
|
; TUNIT: alive1:
|
|
; TUNIT-NEXT: [[K:%.*]] = phi i32 [ 1, [[M]] ], [ 4, [[DEFAULT1]] ]
|
|
; TUNIT-NEXT: switch i32 [[K]], label [[DEAD4:%.*]] [
|
|
; TUNIT-NEXT: i32 1, label [[END1:%.*]]
|
|
; TUNIT-NEXT: i32 2, label [[DEAD5:%.*]]
|
|
; TUNIT-NEXT: i32 4, label [[END2:%.*]]
|
|
; TUNIT-NEXT: ]
|
|
; TUNIT: end1:
|
|
; TUNIT-NEXT: ret i8 -1
|
|
; TUNIT: end2:
|
|
; TUNIT-NEXT: ret i8 -2
|
|
; TUNIT: dead1:
|
|
; TUNIT-NEXT: unreachable
|
|
; TUNIT: dead2:
|
|
; TUNIT-NEXT: unreachable
|
|
; TUNIT: dead3:
|
|
; TUNIT-NEXT: unreachable
|
|
; TUNIT: dead4:
|
|
; TUNIT-NEXT: unreachable
|
|
; TUNIT: dead5:
|
|
; TUNIT-NEXT: unreachable
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@switch
|
|
; CGSCC-SAME: (i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: br i1 [[C1]], label [[T:%.*]], label [[F:%.*]]
|
|
; CGSCC: t:
|
|
; CGSCC-NEXT: br label [[M:%.*]]
|
|
; CGSCC: f:
|
|
; CGSCC-NEXT: br label [[M]]
|
|
; CGSCC: m:
|
|
; CGSCC-NEXT: [[J:%.*]] = phi i32 [ 0, [[T]] ], [ 4, [[F]] ]
|
|
; CGSCC-NEXT: switch i32 [[J]], label [[DEFAULT1:%.*]] [
|
|
; CGSCC-NEXT: i32 1, label [[DEAD1:%.*]]
|
|
; CGSCC-NEXT: i32 2, label [[DEAD2:%.*]]
|
|
; CGSCC-NEXT: i32 3, label [[DEAD3:%.*]]
|
|
; CGSCC-NEXT: i32 4, label [[ALIVE1:%.*]]
|
|
; CGSCC-NEXT: ]
|
|
; CGSCC: default1:
|
|
; CGSCC-NEXT: br label [[ALIVE1]]
|
|
; CGSCC: alive1:
|
|
; CGSCC-NEXT: [[K:%.*]] = phi i32 [ 1, [[M]] ], [ 4, [[DEFAULT1]] ]
|
|
; CGSCC-NEXT: switch i32 [[K]], label [[DEAD4:%.*]] [
|
|
; CGSCC-NEXT: i32 1, label [[END1:%.*]]
|
|
; CGSCC-NEXT: i32 2, label [[DEAD5:%.*]]
|
|
; CGSCC-NEXT: i32 4, label [[END2:%.*]]
|
|
; CGSCC-NEXT: ]
|
|
; CGSCC: end1:
|
|
; CGSCC-NEXT: ret i8 -1
|
|
; CGSCC: end2:
|
|
; CGSCC-NEXT: ret i8 -2
|
|
; CGSCC: dead1:
|
|
; CGSCC-NEXT: unreachable
|
|
; CGSCC: dead2:
|
|
; CGSCC-NEXT: unreachable
|
|
; CGSCC: dead3:
|
|
; CGSCC-NEXT: unreachable
|
|
; CGSCC: dead4:
|
|
; CGSCC-NEXT: unreachable
|
|
; CGSCC: dead5:
|
|
; CGSCC-NEXT: unreachable
|
|
;
|
|
entry:
|
|
br i1 %c1, label %t, label %f
|
|
|
|
t:
|
|
br label %m
|
|
|
|
f:
|
|
br label %m
|
|
|
|
m:
|
|
%j = phi i32 [ 0, %t ], [ 4, %f ]
|
|
switch i32 %j, label %default1 [
|
|
i32 1, label %dead1
|
|
i32 2, label %dead2
|
|
i32 3, label %dead3
|
|
i32 4, label %alive1
|
|
]
|
|
|
|
default1:
|
|
br label %alive1
|
|
|
|
alive1:
|
|
%k = phi i32 [ 1, %m ], [ 4, %default1 ]
|
|
switch i32 %k, label %dead4 [
|
|
i32 1, label %end1
|
|
i32 2, label %dead5
|
|
i32 4, label %end2
|
|
]
|
|
|
|
end1:
|
|
ret i8 -1
|
|
end2:
|
|
ret i8 -2
|
|
dead1:
|
|
ret i8 1
|
|
dead2:
|
|
ret i8 2
|
|
dead3:
|
|
ret i8 3
|
|
dead4:
|
|
ret i8 4
|
|
dead5:
|
|
ret i8 5
|
|
}
|
|
|
|
define i32 @readConst() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@readConst
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i32 0
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@readConst
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret i32 0
|
|
;
|
|
%l = load i32, ptr @ConstPtr
|
|
ret i32 %l
|
|
}
|
|
|
|
define i32 @readWeakConst() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@readWeakConst
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr @ConstWeakPtr, align 4
|
|
; TUNIT-NEXT: ret i32 [[L]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@readWeakConst
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr @ConstWeakPtr, align 4
|
|
; CGSCC-NEXT: ret i32 [[L]]
|
|
;
|
|
%l = load i32, ptr @ConstWeakPtr
|
|
ret i32 %l
|
|
}
|
|
|
|
define i32 @readWeakOdrConst() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@readWeakOdrConst
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: ret i32 0
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@readWeakOdrConst
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: ret i32 0
|
|
;
|
|
%l = load i32, ptr @ConstWeakODRPtr
|
|
ret i32 %l
|
|
}
|
|
|
|
define i32 @readExtInitZeroInit() {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define {{[^@]+}}@readExtInitZeroInit
|
|
; TUNIT-SAME: () #[[ATTR2]] {
|
|
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr @ExtInitZeroInit, align 4
|
|
; TUNIT-NEXT: ret i32 [[L]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define {{[^@]+}}@readExtInitZeroInit
|
|
; CGSCC-SAME: () #[[ATTR1]] {
|
|
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr @ExtInitZeroInit, align 4
|
|
; CGSCC-NEXT: ret i32 [[L]]
|
|
;
|
|
%l = load i32, ptr @ExtInitZeroInit
|
|
ret i32 %l
|
|
}
|
|
|
|
;.
|
|
; TUNIT: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn }
|
|
; TUNIT: attributes #[[ATTR1]] = { memory(readwrite, argmem: none) }
|
|
; TUNIT: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
|
|
; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn }
|
|
; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
|
|
; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
|
|
; TUNIT: attributes #[[ATTR6:[0-9]+]] = { speculatable memory(none) }
|
|
; TUNIT: attributes #[[ATTR7]] = { norecurse nosync memory(none) }
|
|
; TUNIT: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
|
|
; TUNIT: attributes #[[ATTR9]] = { nofree nosync nounwind willreturn memory(none) }
|
|
; TUNIT: attributes #[[ATTR10]] = { nofree willreturn }
|
|
; TUNIT: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn memory(write) }
|
|
; TUNIT: attributes #[[ATTR12]] = { nofree willreturn memory(readwrite) }
|
|
; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn }
|
|
; TUNIT: attributes #[[ATTR14]] = { nosync }
|
|
; TUNIT: attributes #[[ATTR15]] = { nosync nounwind memory(read) }
|
|
; TUNIT: attributes #[[ATTR16]] = { nounwind memory(write) }
|
|
;.
|
|
; TUNIT: [[RNG0]] = !{i32 0, i32 -2147483648}
|
|
;.
|
|
; CGSCC: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn }
|
|
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
|
|
; CGSCC: attributes #[[ATTR2]] = { memory(readwrite, argmem: none) }
|
|
; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
|
|
; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree nosync nounwind willreturn }
|
|
; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
|
|
; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: write) }
|
|
; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree nosync nounwind willreturn memory(write) }
|
|
; CGSCC: attributes #[[ATTR8:[0-9]+]] = { speculatable memory(none) }
|
|
; CGSCC: attributes #[[ATTR9]] = { norecurse nosync memory(none) }
|
|
; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
|
|
; CGSCC: attributes #[[ATTR11:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
|
|
; CGSCC: attributes #[[ATTR12]] = { nofree nosync willreturn }
|
|
; CGSCC: attributes #[[ATTR13]] = { nofree willreturn }
|
|
; CGSCC: attributes #[[ATTR14]] = { nofree nounwind willreturn }
|
|
; CGSCC: attributes #[[ATTR15]] = { nofree nounwind willreturn memory(write) }
|
|
; CGSCC: attributes #[[ATTR16]] = { nofree willreturn memory(readwrite) }
|
|
; CGSCC: attributes #[[ATTR17]] = { nosync }
|
|
; CGSCC: attributes #[[ATTR18]] = { nounwind }
|
|
;.
|