1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
; RUN: not opt -S %s -verify 2>&1 | FileCheck %s
declare token @llvm.call.preallocated.setup(i32)
declare i8* @llvm.call.preallocated.arg(token, i32)
declare void @llvm.call.preallocated.teardown(token)
; Fake LLVM intrinsic to return a token
declare token @llvm.what()
declare void @foo0()
declare void @foo1(i32* preallocated(i32))
declare void @foo2(i32* preallocated(i32), i32*, i32* preallocated(i32))
declare i32 @blackbox()
; CHECK: llvm.call.preallocated.arg must be called with a "preallocated" call site attribute
define void @preallocated_arg_missing_preallocated_attribute() {
%cs = call token @llvm.call.preallocated.setup(i32 1)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0)
%y = bitcast i8* %x to i32*
call void @foo1(i32* preallocated(i32) %y) ["preallocated"(token %cs)]
ret void
}
; CHECK: preallocated as a call site attribute can only be on llvm.call.preallocated.arg
define void @preallocated_call_site_attribute_not_on_arg() {
call void @foo0() preallocated(i32)
ret void
}
; CHECK: "preallocated" argument must be a token from llvm.call.preallocated.setup
define void @preallocated_bundle_token() {
%i = call i32 @blackbox()
call void @foo0() ["preallocated"(i32 %i)]
ret void
}
; CHECK: "preallocated" argument must be a token from llvm.call.preallocated.setup
define void @preallocated_bundle_token_from_setup() {
%cs = call token @llvm.what()
call void @foo0() ["preallocated"(token %cs)]
ret void
}
; CHECK: Expected exactly one preallocated bundle operand
define void @preallocated_bundle_one_token() {
%cs0 = call token @llvm.call.preallocated.setup(i32 0)
%cs1 = call token @llvm.call.preallocated.setup(i32 0)
call void @foo0() ["preallocated"(token %cs0, token %cs1)]
ret void
}
; CHECK: Multiple preallocated operand bundles
define void @preallocated_multiple_bundles() {
%cs0 = call token @llvm.call.preallocated.setup(i32 0)
%cs1 = call token @llvm.call.preallocated.setup(i32 0)
call void @foo0() ["preallocated"(token %cs0), "preallocated"(token %cs1)]
ret void
}
; CHECK: Can have at most one call
define void @preallocated_one_call() {
%cs = call token @llvm.call.preallocated.setup(i32 1)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
%y = bitcast i8* %x to i32*
call void @foo1(i32* preallocated(i32) %y) ["preallocated"(token %cs)]
call void @foo1(i32* preallocated(i32) %y) ["preallocated"(token %cs)]
ret void
}
; CHECK: must be a constant
define void @preallocated_setup_constant() {
%ac = call i32 @blackbox()
%cs = call token @llvm.call.preallocated.setup(i32 %ac)
ret void
}
; CHECK: must be between 0 and corresponding
define void @preallocated_setup_arg_index_in_bounds() {
%cs = call token @llvm.call.preallocated.setup(i32 2)
%a0 = call i8* @llvm.call.preallocated.arg(token %cs, i32 2) preallocated(i32)
ret void
}
; CHECK: Attribute 'preallocated' type does not match parameter
define void @preallocated_attribute_type_mismatch() {
%cs = call token @llvm.call.preallocated.setup(i32 1)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
%y = bitcast i8* %x to i32*
call void @foo1(i32* preallocated(i8) %y) ["preallocated"(token %cs)]
ret void
}
; CHECK: preallocated operand either requires a preallocated bundle or the call to be musttail
define void @preallocated_require_bundle() {
%cs = call token @llvm.call.preallocated.setup(i32 1)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
%y = bitcast i8* %x to i32*
call void @foo1(i32* preallocated(i32) %y)
ret void
}
; CHECK: arg size must be equal to number of preallocated arguments
define void @preallocated_num_args() {
%cs = call token @llvm.call.preallocated.setup(i32 3)
%x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
%x1 = bitcast i8* %x to i32*
%y = call i8* @llvm.call.preallocated.arg(token %cs, i32 1) preallocated(i32)
%y1 = bitcast i8* %y to i32*
%a = inttoptr i32 0 to i32*
call void @foo2(i32* preallocated(i32) %x1, i32* %a, i32* preallocated(i32) %y1) ["preallocated"(token %cs)]
ret void
}
; CHECK: token argument must be a llvm.call.preallocated.setup
define void @preallocated_arg_token() {
%t = call token @llvm.what()
%x = call i8* @llvm.call.preallocated.arg(token %t, i32 1) preallocated(i32)
ret void
}
; CHECK: cannot use preallocated intrinsics on a call without preallocated arguments
define void @preallocated_no_preallocated_args() {
%cs = call token @llvm.call.preallocated.setup(i32 0)
call void @foo0() ["preallocated"(token %cs)]
ret void
}
; CHECK: preallocated operand either requires a preallocated bundle or the call to be musttail
define void @musttail_and_bundle(i32* preallocated(i32) %a) {
%cs = call token @llvm.call.preallocated.setup(i32 0)
musttail call void @musttail_and_bundle(i32* preallocated(i32) %a) ["preallocated"(token %cs)]
ret void
}
; CHECK: cannot guarantee tail call due to mismatched ABI impacting function attributes
define void @musttail_attr_no_match(i32* preallocated(i32) %a) {
musttail call void @musttail_and_bundle(i32* %a)
ret void
}
; CHECK: token argument must be a llvm.call.preallocated.setup
define void @teardown_token_not_from_setup() {
%cs = call token @llvm.what()
call void @llvm.call.preallocated.teardown(token %cs)
ret void
}
; CHECK: Attribute 'preallocated(i32)' applied to incompatible type!
; CHECK-NEXT: void (i32)* @not_pointer
declare void @not_pointer(i32 preallocated(i32))
|