aboutsummaryrefslogtreecommitdiff
path: root/llvm/test/Verifier/preallocated-invalid.ll
blob: 38ed1067c497d4f9aa8b980a2a78be8c0efdbd8a (plain)
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
; RUN: not opt -S %s -passes=verify 2>&1 | FileCheck %s

declare token @llvm.call.preallocated.setup(i32)
declare ptr @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(ptr preallocated(i32))
declare void @foo2(ptr preallocated(i32), ptr, ptr 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 ptr @llvm.call.preallocated.arg(token %cs, i32 0)
    call void @foo1(ptr preallocated(i32) %x) ["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 ptr @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
    call void @foo1(ptr preallocated(i32) %x) ["preallocated"(token %cs)]
    call void @foo1(ptr preallocated(i32) %x) ["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 ptr @llvm.call.preallocated.arg(token %cs, i32 2) preallocated(i32)
    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 ptr @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
    call void @foo1(ptr preallocated(i32) %x)
    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 ptr @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)
    %y = call ptr @llvm.call.preallocated.arg(token %cs, i32 1) preallocated(i32)
    %a = inttoptr i32 0 to ptr
    call void @foo2(ptr preallocated(i32) %x, ptr %a, ptr preallocated(i32) %y) ["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 ptr @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(ptr preallocated(i32) %a) {
    %cs = call token @llvm.call.preallocated.setup(i32 0)
    musttail call void @musttail_and_bundle(ptr 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(ptr preallocated(i32) %a) {
    musttail call void @musttail_and_bundle(ptr %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: ptr @not_pointer
declare void @not_pointer(i32 preallocated(i32))