1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
3 ; Verify the call site info. If the call site info is not
4 ; in the valid state, an assert should be triggered.
5 ; RUN: llc < %s -debug-entry-values -stop-after=machineverifier
8 ; RUN: llc -mcpu=haswell < %s -O2 2>&1 | FileCheck %s
10 ; 2 invariant loads, 1 for OBJC_SELECTOR_REFERENCES_
11 ; and 1 for objc_msgSend from the GOT
13 ; 2 invariant load (full multiply, both loads should be hoisted.)
15 ; 2 invariant load (full divide, both loads should be hoisted.) 1 additional instruction for a zeroing edx that gets hoisted and then rematerialized.
17 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
18 target triple = "x86_64-apple-macosx10.7.2"
20 @"\01L_OBJC_METH_VAR_NAME_" = internal global [4 x i8] c"foo\00", section "__TEXT,__objc_methname,cstring_literals", align 1
21 @"\01L_OBJC_SELECTOR_REFERENCES_" = internal global ptr @"\01L_OBJC_METH_VAR_NAME_", section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
22 @"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
23 @llvm.used = appending global [3 x ptr] [ptr @"\01L_OBJC_METH_VAR_NAME_", ptr @"\01L_OBJC_SELECTOR_REFERENCES_", ptr @"\01L_OBJC_IMAGE_INFO"], section "llvm.metadata"
25 define void @test(ptr %x) uwtable ssp {
27 ; CHECK: ## %bb.0: ## %entry
28 ; CHECK-NEXT: pushq %rbp
29 ; CHECK-NEXT: .cfi_def_cfa_offset 16
30 ; CHECK-NEXT: pushq %r15
31 ; CHECK-NEXT: .cfi_def_cfa_offset 24
32 ; CHECK-NEXT: pushq %r14
33 ; CHECK-NEXT: .cfi_def_cfa_offset 32
34 ; CHECK-NEXT: pushq %rbx
35 ; CHECK-NEXT: .cfi_def_cfa_offset 40
36 ; CHECK-NEXT: pushq %rax
37 ; CHECK-NEXT: .cfi_def_cfa_offset 48
38 ; CHECK-NEXT: .cfi_offset %rbx, -40
39 ; CHECK-NEXT: .cfi_offset %r14, -32
40 ; CHECK-NEXT: .cfi_offset %r15, -24
41 ; CHECK-NEXT: .cfi_offset %rbp, -16
42 ; CHECK-NEXT: movq %rdi, %rbx
43 ; CHECK-NEXT: movl $10000, %ebp ## imm = 0x2710
44 ; CHECK-NEXT: movq L_OBJC_SELECTOR_REFERENCES_(%rip), %r14
45 ; CHECK-NEXT: movq _objc_msgSend@GOTPCREL(%rip), %r15
46 ; CHECK-NEXT: .p2align 4, 0x90
47 ; CHECK-NEXT: LBB0_1: ## %for.body
48 ; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
49 ; CHECK-NEXT: movq %rbx, %rdi
50 ; CHECK-NEXT: movq %r14, %rsi
51 ; CHECK-NEXT: callq *%r15
52 ; CHECK-NEXT: decl %ebp
53 ; CHECK-NEXT: jne LBB0_1
54 ; CHECK-NEXT: ## %bb.2: ## %for.end
55 ; CHECK-NEXT: addq $8, %rsp
56 ; CHECK-NEXT: popq %rbx
57 ; CHECK-NEXT: popq %r14
58 ; CHECK-NEXT: popq %r15
59 ; CHECK-NEXT: popq %rbp
64 for.body: ; preds = %for.body, %entry
65 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
66 %0 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8, !invariant.load !0
67 %call = tail call ptr @objc_msgSend(ptr %x, ptr %0)
68 %inc = add i32 %i.01, 1
69 %exitcond = icmp eq i32 %inc, 10000
70 br i1 %exitcond, label %for.end, label %for.body
72 for.end: ; preds = %for.body
76 define void @test_unordered(ptr %x) uwtable ssp {
77 ; CHECK-LABEL: test_unordered:
78 ; CHECK: ## %bb.0: ## %entry
79 ; CHECK-NEXT: pushq %rbp
80 ; CHECK-NEXT: .cfi_def_cfa_offset 16
81 ; CHECK-NEXT: pushq %r15
82 ; CHECK-NEXT: .cfi_def_cfa_offset 24
83 ; CHECK-NEXT: pushq %r14
84 ; CHECK-NEXT: .cfi_def_cfa_offset 32
85 ; CHECK-NEXT: pushq %rbx
86 ; CHECK-NEXT: .cfi_def_cfa_offset 40
87 ; CHECK-NEXT: pushq %rax
88 ; CHECK-NEXT: .cfi_def_cfa_offset 48
89 ; CHECK-NEXT: .cfi_offset %rbx, -40
90 ; CHECK-NEXT: .cfi_offset %r14, -32
91 ; CHECK-NEXT: .cfi_offset %r15, -24
92 ; CHECK-NEXT: .cfi_offset %rbp, -16
93 ; CHECK-NEXT: movq %rdi, %rbx
94 ; CHECK-NEXT: movl $10000, %ebp ## imm = 0x2710
95 ; CHECK-NEXT: movq L_OBJC_SELECTOR_REFERENCES_(%rip), %r14
96 ; CHECK-NEXT: movq _objc_msgSend@GOTPCREL(%rip), %r15
97 ; CHECK-NEXT: .p2align 4, 0x90
98 ; CHECK-NEXT: LBB1_1: ## %for.body
99 ; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
100 ; CHECK-NEXT: movq %rbx, %rdi
101 ; CHECK-NEXT: movq %r14, %rsi
102 ; CHECK-NEXT: callq *%r15
103 ; CHECK-NEXT: decl %ebp
104 ; CHECK-NEXT: jne LBB1_1
105 ; CHECK-NEXT: ## %bb.2: ## %for.end
106 ; CHECK-NEXT: addq $8, %rsp
107 ; CHECK-NEXT: popq %rbx
108 ; CHECK-NEXT: popq %r14
109 ; CHECK-NEXT: popq %r15
110 ; CHECK-NEXT: popq %rbp
115 for.body: ; preds = %for.body, %entry
116 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
117 %0 = load atomic ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_" unordered, align 8, !invariant.load !0
118 %call = tail call ptr @objc_msgSend(ptr %x, ptr %0)
119 %inc = add i32 %i.01, 1
120 %exitcond = icmp eq i32 %inc, 10000
121 br i1 %exitcond, label %for.end, label %for.body
123 for.end: ; preds = %for.body
127 define void @test_volatile(ptr %x) uwtable ssp {
128 ; CHECK-LABEL: test_volatile:
129 ; CHECK: ## %bb.0: ## %entry
130 ; CHECK-NEXT: pushq %rbp
131 ; CHECK-NEXT: .cfi_def_cfa_offset 16
132 ; CHECK-NEXT: pushq %r14
133 ; CHECK-NEXT: .cfi_def_cfa_offset 24
134 ; CHECK-NEXT: pushq %rbx
135 ; CHECK-NEXT: .cfi_def_cfa_offset 32
136 ; CHECK-NEXT: .cfi_offset %rbx, -32
137 ; CHECK-NEXT: .cfi_offset %r14, -24
138 ; CHECK-NEXT: .cfi_offset %rbp, -16
139 ; CHECK-NEXT: movq %rdi, %rbx
140 ; CHECK-NEXT: movl $10000, %ebp ## imm = 0x2710
141 ; CHECK-NEXT: movq _objc_msgSend@GOTPCREL(%rip), %r14
142 ; CHECK-NEXT: .p2align 4, 0x90
143 ; CHECK-NEXT: LBB2_1: ## %for.body
144 ; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
145 ; CHECK-NEXT: movq L_OBJC_SELECTOR_REFERENCES_(%rip), %rsi
146 ; CHECK-NEXT: movq %rbx, %rdi
147 ; CHECK-NEXT: callq *%r14
148 ; CHECK-NEXT: decl %ebp
149 ; CHECK-NEXT: jne LBB2_1
150 ; CHECK-NEXT: ## %bb.2: ## %for.end
151 ; CHECK-NEXT: popq %rbx
152 ; CHECK-NEXT: popq %r14
153 ; CHECK-NEXT: popq %rbp
158 for.body: ; preds = %for.body, %entry
159 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
160 %0 = load volatile ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8, !invariant.load !0
161 %call = tail call ptr @objc_msgSend(ptr %x, ptr %0)
162 %inc = add i32 %i.01, 1
163 %exitcond = icmp eq i32 %inc, 10000
164 br i1 %exitcond, label %for.end, label %for.body
166 for.end: ; preds = %for.body
170 define void @test_seq_cst(ptr %x) uwtable ssp {
171 ; CHECK-LABEL: test_seq_cst:
172 ; CHECK: ## %bb.0: ## %entry
173 ; CHECK-NEXT: pushq %rbp
174 ; CHECK-NEXT: .cfi_def_cfa_offset 16
175 ; CHECK-NEXT: pushq %r14
176 ; CHECK-NEXT: .cfi_def_cfa_offset 24
177 ; CHECK-NEXT: pushq %rbx
178 ; CHECK-NEXT: .cfi_def_cfa_offset 32
179 ; CHECK-NEXT: .cfi_offset %rbx, -32
180 ; CHECK-NEXT: .cfi_offset %r14, -24
181 ; CHECK-NEXT: .cfi_offset %rbp, -16
182 ; CHECK-NEXT: movq %rdi, %rbx
183 ; CHECK-NEXT: movl $10000, %ebp ## imm = 0x2710
184 ; CHECK-NEXT: movq _objc_msgSend@GOTPCREL(%rip), %r14
185 ; CHECK-NEXT: .p2align 4, 0x90
186 ; CHECK-NEXT: LBB3_1: ## %for.body
187 ; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
188 ; CHECK-NEXT: movq L_OBJC_SELECTOR_REFERENCES_(%rip), %rsi
189 ; CHECK-NEXT: movq %rbx, %rdi
190 ; CHECK-NEXT: callq *%r14
191 ; CHECK-NEXT: decl %ebp
192 ; CHECK-NEXT: jne LBB3_1
193 ; CHECK-NEXT: ## %bb.2: ## %for.end
194 ; CHECK-NEXT: popq %rbx
195 ; CHECK-NEXT: popq %r14
196 ; CHECK-NEXT: popq %rbp
201 for.body: ; preds = %for.body, %entry
202 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
203 %0 = load atomic ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_" seq_cst, align 8, !invariant.load !0
204 %call = tail call ptr @objc_msgSend(ptr %x, ptr %0)
205 %inc = add i32 %i.01, 1
206 %exitcond = icmp eq i32 %inc, 10000
207 br i1 %exitcond, label %for.end, label %for.body
209 for.end: ; preds = %for.body
213 declare ptr @objc_msgSend(ptr, ptr, ...) nonlazybind
215 define void @test_multi_def(ptr dereferenceable(8) %x1,
216 ; CHECK-LABEL: test_multi_def:
217 ; CHECK: ## %bb.0: ## %entry
218 ; CHECK-NEXT: movq %rdx, %rax
219 ; CHECK-NEXT: xorl %r8d, %r8d
220 ; CHECK-NEXT: movq (%rdi), %rdx
221 ; CHECK-NEXT: movq (%rsi), %r9
222 ; CHECK-NEXT: .p2align 4, 0x90
223 ; CHECK-NEXT: LBB4_2: ## %for.body
224 ; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
225 ; CHECK-NEXT: mulxq %r9, %rsi, %rdi
226 ; CHECK-NEXT: addq %rsi, (%rax)
227 ; CHECK-NEXT: adcq %rdi, 8(%rax)
228 ; CHECK-NEXT: ## %bb.1: ## %for.check
229 ; CHECK-NEXT: ## in Loop: Header=BB4_2 Depth=1
230 ; CHECK-NEXT: incq %r8
231 ; CHECK-NEXT: addq $16, %rax
232 ; CHECK-NEXT: cmpq %rcx, %r8
233 ; CHECK-NEXT: jl LBB4_2
234 ; CHECK-NEXT: ## %bb.3: ## %exit
236 ptr dereferenceable(8) %x2,
237 ptr %y, i64 %count) nounwind nofree nosync {
242 %inc = add nsw i64 %i, 1
243 %done = icmp sge i64 %inc, %count
244 br i1 %done, label %exit, label %for.body
247 %i = phi i64 [ 0, %entry ], [ %inc, %for.check ]
248 %x1_load = load i64, ptr %x1, align 8, !invariant.load !0
249 %x1_zext = zext i64 %x1_load to i128
250 %x2_load = load i64, ptr %x2, align 8, !invariant.load !0
251 %x2_zext = zext i64 %x2_load to i128
252 %x_prod = mul i128 %x1_zext, %x2_zext
253 %y_elem = getelementptr inbounds i128, ptr %y, i64 %i
254 %y_load = load i128, ptr %y_elem, align 8
255 %y_plus = add i128 %x_prod, %y_load
256 store i128 %y_plus, ptr %y_elem, align 8
263 define void @test_div_def(ptr dereferenceable(8) %x1,
264 ; CHECK-LABEL: test_div_def:
265 ; CHECK: ## %bb.0: ## %entry
266 ; CHECK-NEXT: movq %rdx, %r8
267 ; CHECK-NEXT: xorl %r9d, %r9d
268 ; CHECK-NEXT: movl (%rdi), %edi
269 ; CHECK-NEXT: movl (%rsi), %esi
270 ; CHECK-NEXT: .p2align 4, 0x90
271 ; CHECK-NEXT: LBB5_2: ## %for.body
272 ; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
273 ; CHECK-NEXT: movl %edi, %eax
274 ; CHECK-NEXT: xorl %edx, %edx
275 ; CHECK-NEXT: divl %esi
276 ; CHECK-NEXT: addl %eax, (%r8,%r9,4)
277 ; CHECK-NEXT: ## %bb.1: ## %for.check
278 ; CHECK-NEXT: ## in Loop: Header=BB5_2 Depth=1
279 ; CHECK-NEXT: incq %r9
280 ; CHECK-NEXT: cmpl %ecx, %r9d
281 ; CHECK-NEXT: jl LBB5_2
282 ; CHECK-NEXT: ## %bb.3: ## %exit
284 ptr dereferenceable(8) %x2,
285 ptr %y, i32 %count) nounwind nofree nosync {
290 %inc = add nsw i32 %i, 1
291 %done = icmp sge i32 %inc, %count
292 br i1 %done, label %exit, label %for.body
295 %i = phi i32 [ 0, %entry ], [ %inc, %for.check ]
296 %x1_load = load i32, ptr %x1, align 8, !invariant.load !0
297 %x2_load = load i32, ptr %x2, align 8, !invariant.load !0
298 %x_quot = udiv i32 %x1_load, %x2_load
299 %y_elem = getelementptr inbounds i32, ptr %y, i32 %i
300 %y_load = load i32, ptr %y_elem, align 8
301 %y_plus = add i32 %x_quot, %y_load
302 store i32 %y_plus, ptr %y_elem, align 8