1/*
2 * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "testb3.h"
28
29#if ENABLE(B3_JIT)
30
31void testStoreRelAddLoadAcq32(int amount)
32{
33 Procedure proc;
34 BasicBlock* root = proc.addBlock();
35 int slot = 37;
36 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
37 root->appendNew<MemoryValue>(
38 proc, Store, Origin(),
39 root->appendNew<Value>(
40 proc, Add, Origin(),
41 root->appendNew<MemoryValue>(
42 proc, Load, Int32, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
43 root->appendNew<Value>(
44 proc, Trunc, Origin(),
45 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
46 slotPtr, 0, HeapRange(42), HeapRange(42));
47 root->appendNewControlValue(
48 proc, Return, Origin(),
49 root->appendNew<Const32Value>(proc, Origin(), 0));
50
51 auto code = compileProc(proc);
52 if (isARM64()) {
53 checkUsesInstruction(*code, "lda");
54 checkUsesInstruction(*code, "stl");
55 }
56 if (isX86())
57 checkUsesInstruction(*code, "xchg");
58 CHECK(!invoke<int>(*code, amount));
59 CHECK(slot == 37 + amount);
60}
61
62void testStoreAddLoadImm32(int amount)
63{
64 Procedure proc;
65 BasicBlock* root = proc.addBlock();
66 int slot = 37;
67 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
68 root->appendNew<MemoryValue>(
69 proc, Store, Origin(),
70 root->appendNew<Value>(
71 proc, Add, Origin(),
72 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
73 root->appendNew<Const32Value>(proc, Origin(), amount)),
74 slotPtr, 0);
75 root->appendNewControlValue(
76 proc, Return, Origin(),
77 root->appendNew<Const32Value>(proc, Origin(), 0));
78
79 CHECK(!compileAndRun<int>(proc));
80 CHECK(slot == 37 + amount);
81}
82
83void testStoreAddLoad8(int amount, B3::Opcode loadOpcode)
84{
85 Procedure proc;
86 BasicBlock* root = proc.addBlock();
87 int8_t slot = 37;
88 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
89 root->appendNew<MemoryValue>(
90 proc, Store8, Origin(),
91 root->appendNew<Value>(
92 proc, Add, Origin(),
93 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
94 root->appendNew<Value>(
95 proc, Trunc, Origin(),
96 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
97 slotPtr, 0);
98 root->appendNewControlValue(
99 proc, Return, Origin(),
100 root->appendNew<Const32Value>(proc, Origin(), 0));
101
102 CHECK(!compileAndRun<int>(proc, amount));
103 CHECK(slot == 37 + amount);
104}
105
106void testStoreRelAddLoadAcq8(int amount, B3::Opcode loadOpcode)
107{
108 Procedure proc;
109 BasicBlock* root = proc.addBlock();
110 int8_t slot = 37;
111 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
112 root->appendNew<MemoryValue>(
113 proc, Store8, Origin(),
114 root->appendNew<Value>(
115 proc, Add, Origin(),
116 root->appendNew<MemoryValue>(
117 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
118 root->appendNew<Value>(
119 proc, Trunc, Origin(),
120 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
121 slotPtr, 0, HeapRange(42), HeapRange(42));
122 root->appendNewControlValue(
123 proc, Return, Origin(),
124 root->appendNew<Const32Value>(proc, Origin(), 0));
125
126 auto code = compileProc(proc);
127 if (isARM64()) {
128 checkUsesInstruction(*code, "lda");
129 checkUsesInstruction(*code, "stl");
130 }
131 if (isX86())
132 checkUsesInstruction(*code, "xchg");
133 CHECK(!invoke<int>(*code, amount));
134 CHECK(slot == 37 + amount);
135}
136
137void testStoreRelAddFenceLoadAcq8(int amount, B3::Opcode loadOpcode)
138{
139 Procedure proc;
140 BasicBlock* root = proc.addBlock();
141 int8_t slot = 37;
142 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
143 Value* loadedValue = root->appendNew<MemoryValue>(
144 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42));
145 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
146 patchpoint->clobber(RegisterSet::macroScratchRegisters());
147 patchpoint->setGenerator(
148 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
149 AllowMacroScratchRegisterUsage allowScratch(jit);
150 jit.store8(CCallHelpers::TrustedImm32(0xbeef), &slot);
151 });
152 patchpoint->effects = Effects::none();
153 patchpoint->effects.fence = true;
154 root->appendNew<MemoryValue>(
155 proc, Store8, Origin(),
156 root->appendNew<Value>(
157 proc, Add, Origin(),
158 loadedValue,
159 root->appendNew<Value>(
160 proc, Trunc, Origin(),
161 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
162 slotPtr, 0, HeapRange(42), HeapRange(42));
163 root->appendNewControlValue(
164 proc, Return, Origin(),
165 root->appendNew<Const32Value>(proc, Origin(), 0));
166
167 auto code = compileProc(proc);
168 if (isARM64()) {
169 checkUsesInstruction(*code, "lda");
170 checkUsesInstruction(*code, "stl");
171 }
172 if (isX86())
173 checkUsesInstruction(*code, "xchg");
174 CHECK(!invoke<int>(*code, amount));
175 CHECK(slot == 37 + amount);
176}
177
178void testStoreAddLoadImm8(int amount, B3::Opcode loadOpcode)
179{
180 Procedure proc;
181 BasicBlock* root = proc.addBlock();
182 int8_t slot = 37;
183 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
184 root->appendNew<MemoryValue>(
185 proc, Store8, Origin(),
186 root->appendNew<Value>(
187 proc, Add, Origin(),
188 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
189 root->appendNew<Const32Value>(proc, Origin(), amount)),
190 slotPtr, 0);
191 root->appendNewControlValue(
192 proc, Return, Origin(),
193 root->appendNew<Const32Value>(proc, Origin(), 0));
194
195 CHECK(!compileAndRun<int>(proc));
196 CHECK(slot == 37 + amount);
197}
198
199void testStoreAddLoad16(int amount, B3::Opcode loadOpcode)
200{
201 Procedure proc;
202 BasicBlock* root = proc.addBlock();
203 int16_t slot = 37;
204 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
205 root->appendNew<MemoryValue>(
206 proc, Store16, Origin(),
207 root->appendNew<Value>(
208 proc, Add, Origin(),
209 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
210 root->appendNew<Value>(
211 proc, Trunc, Origin(),
212 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
213 slotPtr, 0);
214 root->appendNewControlValue(
215 proc, Return, Origin(),
216 root->appendNew<Const32Value>(proc, Origin(), 0));
217
218 CHECK(!compileAndRun<int>(proc, amount));
219 CHECK(slot == 37 + amount);
220}
221
222void testStoreRelAddLoadAcq16(int amount, B3::Opcode loadOpcode)
223{
224 Procedure proc;
225 BasicBlock* root = proc.addBlock();
226 int16_t slot = 37;
227 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
228 root->appendNew<MemoryValue>(
229 proc, Store16, Origin(),
230 root->appendNew<Value>(
231 proc, Add, Origin(),
232 root->appendNew<MemoryValue>(
233 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
234 root->appendNew<Value>(
235 proc, Trunc, Origin(),
236 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
237 slotPtr, 0, HeapRange(42), HeapRange(42));
238 root->appendNewControlValue(
239 proc, Return, Origin(),
240 root->appendNew<Const32Value>(proc, Origin(), 0));
241
242 auto code = compileProc(proc);
243 if (isARM64()) {
244 checkUsesInstruction(*code, "lda");
245 checkUsesInstruction(*code, "stl");
246 }
247 if (isX86())
248 checkUsesInstruction(*code, "xchg");
249 CHECK(!invoke<int>(*code, amount));
250 CHECK(slot == 37 + amount);
251}
252
253void testStoreAddLoadImm16(int amount, B3::Opcode loadOpcode)
254{
255 Procedure proc;
256 BasicBlock* root = proc.addBlock();
257 int16_t slot = 37;
258 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
259 root->appendNew<MemoryValue>(
260 proc, Store16, Origin(),
261 root->appendNew<Value>(
262 proc, Add, Origin(),
263 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
264 root->appendNew<Const32Value>(proc, Origin(), amount)),
265 slotPtr, 0);
266 root->appendNewControlValue(
267 proc, Return, Origin(),
268 root->appendNew<Const32Value>(proc, Origin(), 0));
269
270 CHECK(!compileAndRun<int>(proc));
271 CHECK(slot == 37 + amount);
272}
273
274void testStoreAddLoad64(int amount)
275{
276 Procedure proc;
277 BasicBlock* root = proc.addBlock();
278 int64_t slot = 37000000000ll;
279 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
280 root->appendNew<MemoryValue>(
281 proc, Store, Origin(),
282 root->appendNew<Value>(
283 proc, Add, Origin(),
284 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
285 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
286 slotPtr, 0);
287 root->appendNewControlValue(
288 proc, Return, Origin(),
289 root->appendNew<Const32Value>(proc, Origin(), 0));
290
291 CHECK(!compileAndRun<int>(proc, amount));
292 CHECK(slot == 37000000000ll + amount);
293}
294
295void testStoreRelAddLoadAcq64(int amount)
296{
297 Procedure proc;
298 BasicBlock* root = proc.addBlock();
299 int64_t slot = 37000000000ll;
300 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
301 root->appendNew<MemoryValue>(
302 proc, Store, Origin(),
303 root->appendNew<Value>(
304 proc, Add, Origin(),
305 root->appendNew<MemoryValue>(
306 proc, Load, Int64, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
307 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
308 slotPtr, 0, HeapRange(42), HeapRange(42));
309 root->appendNewControlValue(
310 proc, Return, Origin(),
311 root->appendNew<Const32Value>(proc, Origin(), 0));
312
313 auto code = compileProc(proc);
314 if (isARM64()) {
315 checkUsesInstruction(*code, "lda");
316 checkUsesInstruction(*code, "stl");
317 }
318 if (isX86())
319 checkUsesInstruction(*code, "xchg");
320 CHECK(!invoke<int>(*code, amount));
321 CHECK(slot == 37000000000ll + amount);
322}
323
324void testStoreAddLoadImm64(int64_t amount)
325{
326 Procedure proc;
327 BasicBlock* root = proc.addBlock();
328 int64_t slot = 370000000000ll;
329 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
330 root->appendNew<MemoryValue>(
331 proc, Store, Origin(),
332 root->appendNew<Value>(
333 proc, Add, Origin(),
334 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
335 root->appendNew<Const64Value>(proc, Origin(), amount)),
336 slotPtr, 0);
337 root->appendNewControlValue(
338 proc, Return, Origin(),
339 root->appendNew<Const32Value>(proc, Origin(), 0));
340
341 CHECK(!compileAndRun<int>(proc));
342 CHECK(slot == 370000000000ll + amount);
343}
344
345void testStoreAddLoad32Index(int amount)
346{
347 Procedure proc;
348 BasicBlock* root = proc.addBlock();
349 int slot = 37;
350 int* ptr = &slot;
351 intptr_t zero = 0;
352 Value* slotPtr = root->appendNew<Value>(
353 proc, Add, Origin(),
354 root->appendNew<MemoryValue>(
355 proc, Load, pointerType(), Origin(),
356 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
357 root->appendNew<MemoryValue>(
358 proc, Load, pointerType(), Origin(),
359 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
360 root->appendNew<MemoryValue>(
361 proc, Store, Origin(),
362 root->appendNew<Value>(
363 proc, Add, Origin(),
364 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
365 root->appendNew<Value>(
366 proc, Trunc, Origin(),
367 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
368 slotPtr, 0);
369 root->appendNewControlValue(
370 proc, Return, Origin(),
371 root->appendNew<Const32Value>(proc, Origin(), 0));
372
373 CHECK(!compileAndRun<int>(proc, amount));
374 CHECK(slot == 37 + amount);
375}
376
377void testStoreAddLoadImm32Index(int amount)
378{
379 Procedure proc;
380 BasicBlock* root = proc.addBlock();
381 int slot = 37;
382 int* ptr = &slot;
383 intptr_t zero = 0;
384 Value* slotPtr = root->appendNew<Value>(
385 proc, Add, Origin(),
386 root->appendNew<MemoryValue>(
387 proc, Load, pointerType(), Origin(),
388 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
389 root->appendNew<MemoryValue>(
390 proc, Load, pointerType(), Origin(),
391 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
392 root->appendNew<MemoryValue>(
393 proc, Store, Origin(),
394 root->appendNew<Value>(
395 proc, Add, Origin(),
396 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
397 root->appendNew<Const32Value>(proc, Origin(), amount)),
398 slotPtr, 0);
399 root->appendNewControlValue(
400 proc, Return, Origin(),
401 root->appendNew<Const32Value>(proc, Origin(), 0));
402
403 CHECK(!compileAndRun<int>(proc));
404 CHECK(slot == 37 + amount);
405}
406
407void testStoreAddLoad8Index(int amount, B3::Opcode loadOpcode)
408{
409 Procedure proc;
410 BasicBlock* root = proc.addBlock();
411 int8_t slot = 37;
412 int8_t* ptr = &slot;
413 intptr_t zero = 0;
414 Value* slotPtr = root->appendNew<Value>(
415 proc, Add, Origin(),
416 root->appendNew<MemoryValue>(
417 proc, Load, pointerType(), Origin(),
418 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
419 root->appendNew<MemoryValue>(
420 proc, Load, pointerType(), Origin(),
421 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
422 root->appendNew<MemoryValue>(
423 proc, Store8, Origin(),
424 root->appendNew<Value>(
425 proc, Add, Origin(),
426 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
427 root->appendNew<Value>(
428 proc, Trunc, Origin(),
429 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
430 slotPtr);
431 root->appendNewControlValue(
432 proc, Return, Origin(),
433 root->appendNew<Const32Value>(proc, Origin(), 0));
434
435 CHECK(!compileAndRun<int>(proc, amount));
436 CHECK(slot == 37 + amount);
437}
438
439void testStoreAddLoadImm8Index(int amount, B3::Opcode loadOpcode)
440{
441 Procedure proc;
442 BasicBlock* root = proc.addBlock();
443 int8_t slot = 37;
444 int8_t* ptr = &slot;
445 intptr_t zero = 0;
446 Value* slotPtr = root->appendNew<Value>(
447 proc, Add, Origin(),
448 root->appendNew<MemoryValue>(
449 proc, Load, pointerType(), Origin(),
450 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
451 root->appendNew<MemoryValue>(
452 proc, Load, pointerType(), Origin(),
453 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
454 root->appendNew<MemoryValue>(
455 proc, Store8, Origin(),
456 root->appendNew<Value>(
457 proc, Add, Origin(),
458 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
459 root->appendNew<Const32Value>(proc, Origin(), amount)),
460 slotPtr);
461 root->appendNewControlValue(
462 proc, Return, Origin(),
463 root->appendNew<Const32Value>(proc, Origin(), 0));
464
465 CHECK(!compileAndRun<int>(proc));
466 CHECK(slot == 37 + amount);
467}
468
469void testStoreAddLoad16Index(int amount, B3::Opcode loadOpcode)
470{
471 Procedure proc;
472 BasicBlock* root = proc.addBlock();
473 int16_t slot = 37;
474 int16_t* ptr = &slot;
475 intptr_t zero = 0;
476 Value* slotPtr = root->appendNew<Value>(
477 proc, Add, Origin(),
478 root->appendNew<MemoryValue>(
479 proc, Load, pointerType(), Origin(),
480 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
481 root->appendNew<MemoryValue>(
482 proc, Load, pointerType(), Origin(),
483 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
484 root->appendNew<MemoryValue>(
485 proc, Store16, Origin(),
486 root->appendNew<Value>(
487 proc, Add, Origin(),
488 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
489 root->appendNew<Value>(
490 proc, Trunc, Origin(),
491 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
492 slotPtr);
493 root->appendNewControlValue(
494 proc, Return, Origin(),
495 root->appendNew<Const32Value>(proc, Origin(), 0));
496
497 CHECK(!compileAndRun<int>(proc, amount));
498 CHECK(slot == 37 + amount);
499}
500
501void testStoreAddLoadImm16Index(int amount, B3::Opcode loadOpcode)
502{
503 Procedure proc;
504 BasicBlock* root = proc.addBlock();
505 int16_t slot = 37;
506 int16_t* ptr = &slot;
507 intptr_t zero = 0;
508 Value* slotPtr = root->appendNew<Value>(
509 proc, Add, Origin(),
510 root->appendNew<MemoryValue>(
511 proc, Load, pointerType(), Origin(),
512 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
513 root->appendNew<MemoryValue>(
514 proc, Load, pointerType(), Origin(),
515 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
516 root->appendNew<MemoryValue>(
517 proc, Store16, Origin(),
518 root->appendNew<Value>(
519 proc, Add, Origin(),
520 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
521 root->appendNew<Const32Value>(proc, Origin(), amount)),
522 slotPtr);
523 root->appendNewControlValue(
524 proc, Return, Origin(),
525 root->appendNew<Const32Value>(proc, Origin(), 0));
526
527 CHECK(!compileAndRun<int>(proc));
528 CHECK(slot == 37 + amount);
529}
530
531void testStoreAddLoad64Index(int amount)
532{
533 Procedure proc;
534 BasicBlock* root = proc.addBlock();
535 int64_t slot = 37000000000ll;
536 int64_t* ptr = &slot;
537 intptr_t zero = 0;
538 Value* slotPtr = root->appendNew<Value>(
539 proc, Add, Origin(),
540 root->appendNew<MemoryValue>(
541 proc, Load, pointerType(), Origin(),
542 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
543 root->appendNew<MemoryValue>(
544 proc, Load, pointerType(), Origin(),
545 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
546 root->appendNew<MemoryValue>(
547 proc, Store, Origin(),
548 root->appendNew<Value>(
549 proc, Add, Origin(),
550 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
551 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
552 slotPtr, 0);
553 root->appendNewControlValue(
554 proc, Return, Origin(),
555 root->appendNew<Const32Value>(proc, Origin(), 0));
556
557 CHECK(!compileAndRun<int>(proc, amount));
558 CHECK(slot == 37000000000ll + amount);
559}
560
561void testStoreAddLoadImm64Index(int64_t amount)
562{
563 Procedure proc;
564 BasicBlock* root = proc.addBlock();
565 int64_t slot = 370000000000ll;
566 int64_t* ptr = &slot;
567 intptr_t zero = 0;
568 Value* slotPtr = root->appendNew<Value>(
569 proc, Add, Origin(),
570 root->appendNew<MemoryValue>(
571 proc, Load, pointerType(), Origin(),
572 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
573 root->appendNew<MemoryValue>(
574 proc, Load, pointerType(), Origin(),
575 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
576 root->appendNew<MemoryValue>(
577 proc, Store, Origin(),
578 root->appendNew<Value>(
579 proc, Add, Origin(),
580 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
581 root->appendNew<Const64Value>(proc, Origin(), amount)),
582 slotPtr, 0);
583 root->appendNewControlValue(
584 proc, Return, Origin(),
585 root->appendNew<Const32Value>(proc, Origin(), 0));
586
587 CHECK(!compileAndRun<int>(proc));
588 CHECK(slot == 370000000000ll + amount);
589}
590
591void testStoreSubLoad(int amount)
592{
593 Procedure proc;
594 BasicBlock* root = proc.addBlock();
595 int32_t startValue = std::numeric_limits<int32_t>::min();
596 int32_t slot = startValue;
597 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
598 root->appendNew<MemoryValue>(
599 proc, Store, Origin(),
600 root->appendNew<Value>(
601 proc, Sub, Origin(),
602 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
603 root->appendNew<Value>(
604 proc, Trunc, Origin(),
605 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
606 slotPtr, 0);
607 root->appendNewControlValue(
608 proc, Return, Origin(),
609 root->appendNew<Const32Value>(proc, Origin(), 0));
610
611 CHECK(!compileAndRun<int>(proc, amount));
612 CHECK(slot == startValue - amount);
613}
614
615void testStoreAddLoadInterference(int amount)
616{
617 Procedure proc;
618 BasicBlock* root = proc.addBlock();
619 int slot = 37;
620 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
621 ArgumentRegValue* otherSlotPtr =
622 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
623 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr);
624 root->appendNew<MemoryValue>(
625 proc, Store, Origin(),
626 root->appendNew<Const32Value>(proc, Origin(), 666),
627 otherSlotPtr, 0);
628 root->appendNew<MemoryValue>(
629 proc, Store, Origin(),
630 root->appendNew<Value>(
631 proc, Add, Origin(),
632 load, root->appendNew<Const32Value>(proc, Origin(), amount)),
633 slotPtr, 0);
634 root->appendNewControlValue(
635 proc, Return, Origin(),
636 root->appendNew<Const32Value>(proc, Origin(), 0));
637
638 CHECK(!compileAndRun<int>(proc, &slot));
639 CHECK(slot == 37 + amount);
640}
641
642void testStoreAddAndLoad(int amount, int mask)
643{
644 Procedure proc;
645 BasicBlock* root = proc.addBlock();
646 int slot = 37;
647 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
648 root->appendNew<MemoryValue>(
649 proc, Store, Origin(),
650 root->appendNew<Value>(
651 proc, BitAnd, Origin(),
652 root->appendNew<Value>(
653 proc, Add, Origin(),
654 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
655 root->appendNew<Const32Value>(proc, Origin(), amount)),
656 root->appendNew<Const32Value>(proc, Origin(), mask)),
657 slotPtr, 0);
658 root->appendNewControlValue(
659 proc, Return, Origin(),
660 root->appendNew<Const32Value>(proc, Origin(), 0));
661
662 CHECK(!compileAndRun<int>(proc));
663 CHECK(slot == ((37 + amount) & mask));
664}
665
666void testStoreNegLoad32(int32_t value)
667{
668 Procedure proc;
669 BasicBlock* root = proc.addBlock();
670
671 int32_t slot = value;
672
673 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
674
675 root->appendNew<MemoryValue>(
676 proc, Store, Origin(),
677 root->appendNew<Value>(
678 proc, Sub, Origin(),
679 root->appendNew<Const32Value>(proc, Origin(), 0),
680 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)),
681 slotPtr, 0);
682
683 root->appendNewControlValue(
684 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
685
686 CHECK(!compileAndRun<int32_t>(proc));
687 CHECK(slot == -value);
688}
689
690void testStoreNegLoadPtr(intptr_t value)
691{
692 Procedure proc;
693 BasicBlock* root = proc.addBlock();
694
695 intptr_t slot = value;
696
697 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
698
699 root->appendNew<MemoryValue>(
700 proc, Store, Origin(),
701 root->appendNew<Value>(
702 proc, Sub, Origin(),
703 root->appendNew<ConstPtrValue>(proc, Origin(), 0),
704 root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)),
705 slotPtr, 0);
706
707 root->appendNewControlValue(
708 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
709
710 CHECK(!compileAndRun<int32_t>(proc));
711 CHECK(slot == -value);
712}
713
714void testAdd1Uncommuted(int value)
715{
716 Procedure proc;
717 BasicBlock* root = proc.addBlock();
718 root->appendNewControlValue(
719 proc, Return, Origin(),
720 root->appendNew<Value>(
721 proc, Add, Origin(),
722 root->appendNew<Const32Value>(proc, Origin(), 1),
723 root->appendNew<Value>(
724 proc, Trunc, Origin(),
725 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
726
727 CHECK(compileAndRun<int>(proc, value) == value + 1);
728}
729
730void testLoadOffset()
731{
732 Procedure proc;
733 BasicBlock* root = proc.addBlock();
734 int array[] = { 1, 2 };
735 ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
736 root->appendNewControlValue(
737 proc, Return, Origin(),
738 root->appendNew<Value>(
739 proc, Add, Origin(),
740 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
741 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, static_cast<int32_t>(sizeof(int)))));
742
743 CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
744}
745
746void testLoadOffsetNotConstant()
747{
748 Procedure proc;
749 BasicBlock* root = proc.addBlock();
750 int array[] = { 1, 2 };
751 Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
752 root->appendNewControlValue(
753 proc, Return, Origin(),
754 root->appendNew<Value>(
755 proc, Add, Origin(),
756 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
757 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, static_cast<int32_t>(sizeof(int)))));
758
759 CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
760}
761
762void testLoadOffsetUsingAdd()
763{
764 Procedure proc;
765 BasicBlock* root = proc.addBlock();
766 int array[] = { 1, 2 };
767 ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
768 root->appendNewControlValue(
769 proc, Return, Origin(),
770 root->appendNew<Value>(
771 proc, Add, Origin(),
772 root->appendNew<MemoryValue>(
773 proc, Load, Int32, Origin(),
774 root->appendNew<Value>(
775 proc, Add, Origin(), arrayPtr,
776 root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
777 root->appendNew<MemoryValue>(
778 proc, Load, Int32, Origin(),
779 root->appendNew<Value>(
780 proc, Add, Origin(), arrayPtr,
781 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))))));
782
783 CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
784}
785
786void testLoadOffsetUsingAddInterference()
787{
788 Procedure proc;
789 BasicBlock* root = proc.addBlock();
790 int array[] = { 1, 2 };
791 ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
792 ArgumentRegValue* otherArrayPtr =
793 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
794 Const32Value* theNumberOfTheBeast = root->appendNew<Const32Value>(proc, Origin(), 666);
795 MemoryValue* left = root->appendNew<MemoryValue>(
796 proc, Load, Int32, Origin(),
797 root->appendNew<Value>(
798 proc, Add, Origin(), arrayPtr,
799 root->appendNew<ConstPtrValue>(proc, Origin(), 0)));
800 MemoryValue* right = root->appendNew<MemoryValue>(
801 proc, Load, Int32, Origin(),
802 root->appendNew<Value>(
803 proc, Add, Origin(), arrayPtr,
804 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))));
805 root->appendNew<MemoryValue>(
806 proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0);
807 root->appendNew<MemoryValue>(
808 proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, static_cast<int32_t>(sizeof(int)));
809 root->appendNewControlValue(
810 proc, Return, Origin(),
811 root->appendNew<Value>(
812 proc, Add, Origin(), left, right));
813
814 CHECK(compileAndRun<int>(proc, &array[0]) == 1 + 2);
815 CHECK(array[0] == 666);
816 CHECK(array[1] == 666);
817}
818
819void testLoadOffsetUsingAddNotConstant()
820{
821 Procedure proc;
822 BasicBlock* root = proc.addBlock();
823 int array[] = { 1, 2 };
824 Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
825 root->appendNewControlValue(
826 proc, Return, Origin(),
827 root->appendNew<Value>(
828 proc, Add, Origin(),
829 root->appendNew<MemoryValue>(
830 proc, Load, Int32, Origin(),
831 root->appendNew<Value>(
832 proc, Add, Origin(), arrayPtr,
833 root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
834 root->appendNew<MemoryValue>(
835 proc, Load, Int32, Origin(),
836 root->appendNew<Value>(
837 proc, Add, Origin(), arrayPtr,
838 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))))));
839
840 CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
841}
842
843void testLoadAddrShift(unsigned shift)
844{
845 Procedure proc;
846 BasicBlock* root = proc.addBlock();
847 int slots[2];
848
849 // Figure out which slot to use while having proper alignment for the shift.
850 int* slot;
851 uintptr_t arg;
852 for (unsigned i = sizeof(slots)/sizeof(slots[0]); i--;) {
853 slot = slots + i;
854 arg = bitwise_cast<uintptr_t>(slot) >> shift;
855 if (bitwise_cast<int*>(arg << shift) == slot)
856 break;
857 }
858
859 *slot = 8675309;
860
861 root->appendNewControlValue(
862 proc, Return, Origin(),
863 root->appendNew<MemoryValue>(
864 proc, Load, Int32, Origin(),
865 root->appendNew<Value>(
866 proc, Shl, Origin(),
867 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
868 root->appendNew<Const32Value>(proc, Origin(), shift))));
869
870 CHECK(compileAndRun<int>(proc, arg) == 8675309);
871}
872
873void testFramePointer()
874{
875 Procedure proc;
876 BasicBlock* root = proc.addBlock();
877 root->appendNewControlValue(
878 proc, Return, Origin(),
879 root->appendNew<Value>(proc, FramePointer, Origin()));
880
881 void* fp = compileAndRun<void*>(proc);
882 CHECK(fp < &proc);
883 CHECK(fp >= bitwise_cast<char*>(&proc) - 10000);
884}
885
886void testOverrideFramePointer()
887{
888 {
889 Procedure proc;
890 BasicBlock* root = proc.addBlock();
891
892 // Add a stack slot to make the frame non trivial.
893 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8));
894
895 // Sub on x86 UseDef the source. If FP is not protected correctly, it will be overridden since it is the last visible use.
896 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
897 Value* fp = root->appendNew<Value>(proc, FramePointer, Origin());
898 Value* result = root->appendNew<Value>(proc, Sub, Origin(), fp, offset);
899
900 root->appendNewControlValue(proc, Return, Origin(), result);
901 CHECK(compileAndRun<int64_t>(proc, 1));
902 }
903 {
904 Procedure proc;
905 BasicBlock* root = proc.addBlock();
906
907 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8));
908
909 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
910 Value* fp = root->appendNew<Value>(proc, FramePointer, Origin());
911 Value* offsetFP = root->appendNew<Value>(proc, BitAnd, Origin(), offset, fp);
912 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
913 Value* offsetArg = root->appendNew<Value>(proc, Add, Origin(), offset, arg);
914 Value* result = root->appendNew<Value>(proc, Add, Origin(), offsetArg, offsetFP);
915
916 root->appendNewControlValue(proc, Return, Origin(), result);
917 CHECK(compileAndRun<int64_t>(proc, 1, 2));
918 }
919}
920
921void testStackSlot()
922{
923 Procedure proc;
924 BasicBlock* root = proc.addBlock();
925 root->appendNewControlValue(
926 proc, Return, Origin(),
927 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(1)));
928
929 void* stackSlot = compileAndRun<void*>(proc);
930 CHECK(stackSlot < &proc);
931 CHECK(stackSlot >= bitwise_cast<char*>(&proc) - 10000);
932}
933
934void testLoadFromFramePointer()
935{
936 Procedure proc;
937 BasicBlock* root = proc.addBlock();
938 root->appendNewControlValue(
939 proc, Return, Origin(),
940 root->appendNew<MemoryValue>(
941 proc, Load, pointerType(), Origin(),
942 root->appendNew<Value>(proc, FramePointer, Origin())));
943
944 void* fp = compileAndRun<void*>(proc);
945 void* myFP = __builtin_frame_address(0);
946 CHECK(fp <= myFP);
947 CHECK(fp >= bitwise_cast<char*>(myFP) - 10000);
948}
949
950void testStoreLoadStackSlot(int value)
951{
952 Procedure proc;
953 BasicBlock* root = proc.addBlock();
954
955 SlotBaseValue* stack =
956 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(sizeof(int)));
957
958 root->appendNew<MemoryValue>(
959 proc, Store, Origin(),
960 root->appendNew<Value>(
961 proc, Trunc, Origin(),
962 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
963 stack, 0);
964
965 root->appendNewControlValue(
966 proc, Return, Origin(),
967 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), stack));
968
969 CHECK(compileAndRun<int>(proc, value) == value);
970}
971
972void testStoreFloat(double input)
973{
974 // Simple store from an address in a register.
975 {
976 Procedure proc;
977 BasicBlock* root = proc.addBlock();
978 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
979 Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
980
981 Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
982 root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
983
984 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
985
986 float output = 0.;
987 CHECK(!compileAndRun<int64_t>(proc, input, &output));
988 CHECK(isIdentical(static_cast<float>(input), output));
989 }
990
991 // Simple indexed store.
992 {
993 Procedure proc;
994 BasicBlock* root = proc.addBlock();
995 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
996 Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
997
998 Value* destinationBaseAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
999 Value* index = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1000 Value* scaledIndex = root->appendNew<Value>(
1001 proc, Shl, Origin(),
1002 index,
1003 root->appendNew<Const32Value>(proc, Origin(), 2));
1004 Value* destinationAddress = root->appendNew<Value>(proc, Add, Origin(), scaledIndex, destinationBaseAddress);
1005
1006 root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
1007
1008 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1009
1010 float output = 0.;
1011 CHECK(!compileAndRun<int64_t>(proc, input, &output - 1, 1));
1012 CHECK(isIdentical(static_cast<float>(input), output));
1013 }
1014}
1015
1016void testStoreDoubleConstantAsFloat(double input)
1017{
1018 // Simple store from an address in a register.
1019 Procedure proc;
1020 BasicBlock* root = proc.addBlock();
1021 Value* value = root->appendNew<ConstDoubleValue>(proc, Origin(), input);
1022 Value* valueAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), value);
1023
1024 Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1025
1026 root->appendNew<MemoryValue>(proc, Store, Origin(), valueAsFloat, destinationAddress);
1027
1028 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1029
1030 float output = 0.;
1031 CHECK(!compileAndRun<int64_t>(proc, input, &output));
1032 CHECK(isIdentical(static_cast<float>(input), output));
1033}
1034
1035void testSpillGP()
1036{
1037 Procedure proc;
1038 BasicBlock* root = proc.addBlock();
1039
1040 Vector<Value*> sources;
1041 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1042 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1043
1044 for (unsigned i = 0; i < 30; ++i) {
1045 sources.append(
1046 root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
1047 );
1048 }
1049
1050 Value* total = root->appendNew<Const64Value>(proc, Origin(), 0);
1051 for (Value* value : sources)
1052 total = root->appendNew<Value>(proc, Add, Origin(), total, value);
1053
1054 root->appendNewControlValue(proc, Return, Origin(), total);
1055 compileAndRun<int>(proc, 1, 2);
1056}
1057
1058void testSpillFP()
1059{
1060 Procedure proc;
1061 BasicBlock* root = proc.addBlock();
1062
1063 Vector<Value*> sources;
1064 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1065 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
1066
1067 for (unsigned i = 0; i < 30; ++i) {
1068 sources.append(
1069 root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
1070 );
1071 }
1072
1073 Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
1074 for (Value* value : sources)
1075 total = root->appendNew<Value>(proc, Add, Origin(), total, value);
1076
1077 root->appendNewControlValue(proc, Return, Origin(), total);
1078 compileAndRun<double>(proc, 1.1, 2.5);
1079}
1080
1081void testInt32ToDoublePartialRegisterStall()
1082{
1083 Procedure proc;
1084 BasicBlock* root = proc.addBlock();
1085 BasicBlock* loop = proc.addBlock();
1086 BasicBlock* done = proc.addBlock();
1087
1088 // Head.
1089 Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
1090 Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1091 UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total);
1092 UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter);
1093 root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop));
1094
1095 // Loop.
1096 Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin());
1097 Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin());
1098 originalCounter->setPhi(loopCounter);
1099 originalTotal->setPhi(loopTotal);
1100
1101 Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter);
1102 Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter);
1103 Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal);
1104 UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
1105 updatedTotalUpsilon->setPhi(loopTotal);
1106
1107 Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1));
1108 UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter);
1109 decCounterUpsilon->setPhi(loopCounter);
1110 loop->appendNewControlValue(
1111 proc, Branch, Origin(),
1112 decCounter,
1113 FrequentedBlock(loop), FrequentedBlock(done));
1114
1115 // Tail.
1116 done->appendNewControlValue(proc, Return, Origin(), updatedTotal);
1117 CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
1118}
1119
1120void testInt32ToDoublePartialRegisterWithoutStall()
1121{
1122 Procedure proc;
1123 BasicBlock* root = proc.addBlock();
1124 BasicBlock* loop = proc.addBlock();
1125 BasicBlock* done = proc.addBlock();
1126
1127 // Head.
1128 Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
1129 Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1130 UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total);
1131 UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter);
1132 uint64_t forPaddingInput;
1133 Value* forPaddingInputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingInput);
1134 uint64_t forPaddingOutput;
1135 Value* forPaddingOutputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingOutput);
1136 root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop));
1137
1138 // Loop.
1139 Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin());
1140 Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin());
1141 originalCounter->setPhi(loopCounter);
1142 originalTotal->setPhi(loopTotal);
1143
1144 Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter);
1145 Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter);
1146 Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal);
1147
1148 // Add enough padding instructions to avoid a stall.
1149 Value* loadPadding = loop->appendNew<MemoryValue>(proc, Load, Int64, Origin(), forPaddingInputAddress);
1150 Value* padding = loop->appendNew<Value>(proc, BitXor, Origin(), loadPadding, loopCounter);
1151 padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
1152 padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
1153 padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
1154 padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter);
1155 padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
1156 padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
1157 padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
1158 padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter);
1159 padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
1160 padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
1161 padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
1162 loop->appendNew<MemoryValue>(proc, Store, Origin(), padding, forPaddingOutputAddress);
1163
1164 UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
1165 updatedTotalUpsilon->setPhi(loopTotal);
1166
1167 Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1));
1168 UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter);
1169 decCounterUpsilon->setPhi(loopCounter);
1170 loop->appendNewControlValue(
1171 proc, Branch, Origin(),
1172 decCounter,
1173 FrequentedBlock(loop), FrequentedBlock(done));
1174
1175 // Tail.
1176 done->appendNewControlValue(proc, Return, Origin(), updatedTotal);
1177 CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
1178}
1179
1180void testBranch()
1181{
1182 Procedure proc;
1183 BasicBlock* root = proc.addBlock();
1184 BasicBlock* thenCase = proc.addBlock();
1185 BasicBlock* elseCase = proc.addBlock();
1186
1187 root->appendNewControlValue(
1188 proc, Branch, Origin(),
1189 root->appendNew<Value>(
1190 proc, Trunc, Origin(),
1191 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1192 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1193
1194 thenCase->appendNewControlValue(
1195 proc, Return, Origin(),
1196 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1197
1198 elseCase->appendNewControlValue(
1199 proc, Return, Origin(),
1200 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1201
1202 auto code = compileProc(proc);
1203 CHECK(invoke<int>(*code, 42) == 1);
1204 CHECK(invoke<int>(*code, 0) == 0);
1205}
1206
1207void testBranchPtr()
1208{
1209 Procedure proc;
1210 BasicBlock* root = proc.addBlock();
1211 BasicBlock* thenCase = proc.addBlock();
1212 BasicBlock* elseCase = proc.addBlock();
1213
1214 root->appendNewControlValue(
1215 proc, Branch, Origin(),
1216 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1217 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1218
1219 thenCase->appendNewControlValue(
1220 proc, Return, Origin(),
1221 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1222
1223 elseCase->appendNewControlValue(
1224 proc, Return, Origin(),
1225 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1226
1227 auto code = compileProc(proc);
1228 CHECK(invoke<int>(*code, static_cast<intptr_t>(42)) == 1);
1229 CHECK(invoke<int>(*code, static_cast<intptr_t>(0)) == 0);
1230}
1231
1232void testDiamond()
1233{
1234 Procedure proc;
1235 BasicBlock* root = proc.addBlock();
1236 BasicBlock* thenCase = proc.addBlock();
1237 BasicBlock* elseCase = proc.addBlock();
1238 BasicBlock* done = proc.addBlock();
1239
1240 root->appendNewControlValue(
1241 proc, Branch, Origin(),
1242 root->appendNew<Value>(
1243 proc, Trunc, Origin(),
1244 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1245 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1246
1247 UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
1248 proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1249 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1250
1251 UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
1252 proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1253 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1254
1255 Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
1256 thenResult->setPhi(phi);
1257 elseResult->setPhi(phi);
1258 done->appendNewControlValue(proc, Return, Origin(), phi);
1259
1260 auto code = compileProc(proc);
1261 CHECK(invoke<int>(*code, 42) == 1);
1262 CHECK(invoke<int>(*code, 0) == 0);
1263}
1264
1265void testBranchNotEqual()
1266{
1267 Procedure proc;
1268 BasicBlock* root = proc.addBlock();
1269 BasicBlock* thenCase = proc.addBlock();
1270 BasicBlock* elseCase = proc.addBlock();
1271
1272 root->appendNewControlValue(
1273 proc, Branch, Origin(),
1274 root->appendNew<Value>(
1275 proc, NotEqual, Origin(),
1276 root->appendNew<Value>(
1277 proc, Trunc, Origin(),
1278 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1279 root->appendNew<Const32Value>(proc, Origin(), 0)),
1280 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1281
1282 thenCase->appendNewControlValue(
1283 proc, Return, Origin(),
1284 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1285
1286 elseCase->appendNewControlValue(
1287 proc, Return, Origin(),
1288 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1289
1290 auto code = compileProc(proc);
1291 CHECK(invoke<int>(*code, 42) == 1);
1292 CHECK(invoke<int>(*code, 0) == 0);
1293}
1294
1295void testBranchNotEqualCommute()
1296{
1297 Procedure proc;
1298 BasicBlock* root = proc.addBlock();
1299 BasicBlock* thenCase = proc.addBlock();
1300 BasicBlock* elseCase = proc.addBlock();
1301
1302 root->appendNewControlValue(
1303 proc, Branch, Origin(),
1304 root->appendNew<Value>(
1305 proc, NotEqual, Origin(),
1306 root->appendNew<Const32Value>(proc, Origin(), 0),
1307 root->appendNew<Value>(
1308 proc, Trunc, Origin(),
1309 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
1310 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1311
1312 thenCase->appendNewControlValue(
1313 proc, Return, Origin(),
1314 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1315
1316 elseCase->appendNewControlValue(
1317 proc, Return, Origin(),
1318 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1319
1320 auto code = compileProc(proc);
1321 CHECK(invoke<int>(*code, 42) == 1);
1322 CHECK(invoke<int>(*code, 0) == 0);
1323}
1324
1325void testBranchNotEqualNotEqual()
1326{
1327 Procedure proc;
1328 BasicBlock* root = proc.addBlock();
1329 BasicBlock* thenCase = proc.addBlock();
1330 BasicBlock* elseCase = proc.addBlock();
1331
1332 root->appendNewControlValue(
1333 proc, Branch, Origin(),
1334 root->appendNew<Value>(
1335 proc, NotEqual, Origin(),
1336 root->appendNew<Value>(
1337 proc, NotEqual, Origin(),
1338 root->appendNew<Value>(
1339 proc, Trunc, Origin(),
1340 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1341 root->appendNew<Const32Value>(proc, Origin(), 0)),
1342 root->appendNew<Const32Value>(proc, Origin(), 0)),
1343 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1344
1345 thenCase->appendNewControlValue(
1346 proc, Return, Origin(),
1347 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1348
1349 elseCase->appendNewControlValue(
1350 proc, Return, Origin(),
1351 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1352
1353 auto code = compileProc(proc);
1354 CHECK(invoke<int>(*code, 42) == 1);
1355 CHECK(invoke<int>(*code, 0) == 0);
1356}
1357
1358void testBranchEqual()
1359{
1360 Procedure proc;
1361 BasicBlock* root = proc.addBlock();
1362 BasicBlock* thenCase = proc.addBlock();
1363 BasicBlock* elseCase = proc.addBlock();
1364
1365 root->appendNewControlValue(
1366 proc, Branch, Origin(),
1367 root->appendNew<Value>(
1368 proc, Equal, Origin(),
1369 root->appendNew<Value>(
1370 proc, Trunc, Origin(),
1371 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1372 root->appendNew<Const32Value>(proc, Origin(), 0)),
1373 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1374
1375 thenCase->appendNewControlValue(
1376 proc, Return, Origin(),
1377 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1378
1379 elseCase->appendNewControlValue(
1380 proc, Return, Origin(),
1381 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1382
1383 auto code = compileProc(proc);
1384 CHECK(invoke<int>(*code, 42) == 1);
1385 CHECK(invoke<int>(*code, 0) == 0);
1386}
1387
1388void testBranchEqualEqual()
1389{
1390 Procedure proc;
1391 BasicBlock* root = proc.addBlock();
1392 BasicBlock* thenCase = proc.addBlock();
1393 BasicBlock* elseCase = proc.addBlock();
1394
1395 root->appendNewControlValue(
1396 proc, Branch, Origin(),
1397 root->appendNew<Value>(
1398 proc, Equal, Origin(),
1399 root->appendNew<Value>(
1400 proc, Equal, Origin(),
1401 root->appendNew<Value>(
1402 proc, Trunc, Origin(),
1403 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1404 root->appendNew<Const32Value>(proc, Origin(), 0)),
1405 root->appendNew<Const32Value>(proc, Origin(), 0)),
1406 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1407
1408 thenCase->appendNewControlValue(
1409 proc, Return, Origin(),
1410 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1411
1412 elseCase->appendNewControlValue(
1413 proc, Return, Origin(),
1414 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1415
1416 auto code = compileProc(proc);
1417 CHECK(invoke<int>(*code, 42) == 1);
1418 CHECK(invoke<int>(*code, 0) == 0);
1419}
1420
1421void testBranchEqualCommute()
1422{
1423 Procedure proc;
1424 BasicBlock* root = proc.addBlock();
1425 BasicBlock* thenCase = proc.addBlock();
1426 BasicBlock* elseCase = proc.addBlock();
1427
1428 root->appendNewControlValue(
1429 proc, Branch, Origin(),
1430 root->appendNew<Value>(
1431 proc, Equal, Origin(),
1432 root->appendNew<Const32Value>(proc, Origin(), 0),
1433 root->appendNew<Value>(
1434 proc, Trunc, Origin(),
1435 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
1436 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1437
1438 thenCase->appendNewControlValue(
1439 proc, Return, Origin(),
1440 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1441
1442 elseCase->appendNewControlValue(
1443 proc, Return, Origin(),
1444 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1445
1446 auto code = compileProc(proc);
1447 CHECK(invoke<int>(*code, 42) == 1);
1448 CHECK(invoke<int>(*code, 0) == 0);
1449}
1450
1451void testBranchEqualEqual1()
1452{
1453 Procedure proc;
1454 BasicBlock* root = proc.addBlock();
1455 BasicBlock* thenCase = proc.addBlock();
1456 BasicBlock* elseCase = proc.addBlock();
1457
1458 root->appendNewControlValue(
1459 proc, Branch, Origin(),
1460 root->appendNew<Value>(
1461 proc, Equal, Origin(),
1462 root->appendNew<Value>(
1463 proc, Equal, Origin(),
1464 root->appendNew<Value>(
1465 proc, Trunc, Origin(),
1466 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1467 root->appendNew<Const32Value>(proc, Origin(), 0)),
1468 root->appendNew<Const32Value>(proc, Origin(), 1)),
1469 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1470
1471 thenCase->appendNewControlValue(
1472 proc, Return, Origin(),
1473 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1474
1475 elseCase->appendNewControlValue(
1476 proc, Return, Origin(),
1477 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1478
1479 auto code = compileProc(proc);
1480 CHECK(invoke<int>(*code, 42) == 1);
1481 CHECK(invoke<int>(*code, 0) == 0);
1482}
1483
1484void testBranchEqualOrUnorderedArgs(double a, double b)
1485{
1486 Procedure proc;
1487 BasicBlock* root = proc.addBlock();
1488 BasicBlock* thenCase = proc.addBlock();
1489 BasicBlock* elseCase = proc.addBlock();
1490
1491 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1492 Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1493 root->appendNewControlValue(
1494 proc, Branch, Origin(),
1495 root->appendNew<Value>(
1496 proc, EqualOrUnordered, Origin(),
1497 argumentA,
1498 argumentB),
1499 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1500
1501 thenCase->appendNewControlValue(
1502 proc, Return, Origin(),
1503 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1504
1505 elseCase->appendNewControlValue(
1506 proc, Return, Origin(),
1507 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1508
1509 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1510 CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
1511}
1512
1513void testBranchEqualOrUnorderedArgs(float a, float b)
1514{
1515 Procedure proc;
1516 BasicBlock* root = proc.addBlock();
1517 BasicBlock* thenCase = proc.addBlock();
1518 BasicBlock* elseCase = proc.addBlock();
1519
1520 Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1521 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1522 Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1523 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1524
1525 root->appendNewControlValue(
1526 proc, Branch, Origin(),
1527 root->appendNew<Value>(
1528 proc, EqualOrUnordered, Origin(),
1529 argumentA,
1530 argumentB),
1531 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1532
1533 thenCase->appendNewControlValue(
1534 proc, Return, Origin(),
1535 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1536
1537 elseCase->appendNewControlValue(
1538 proc, Return, Origin(),
1539 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1540
1541 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1542 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1543}
1544
1545void testBranchNotEqualAndOrderedArgs(double a, double b)
1546{
1547 Procedure proc;
1548 BasicBlock* root = proc.addBlock();
1549 BasicBlock* thenCase = proc.addBlock();
1550 BasicBlock* elseCase = proc.addBlock();
1551
1552 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1553 Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1554 Value* equalOrUnordered = root->appendNew<Value>(
1555 proc, EqualOrUnordered, Origin(),
1556 argumentA,
1557 argumentB);
1558 Value* notEqualAndOrdered = root->appendNew<Value>(
1559 proc, Equal, Origin(),
1560 root->appendNew<Const32Value>(proc, Origin(), 0),
1561 equalOrUnordered);
1562 root->appendNewControlValue(
1563 proc, Branch, Origin(),
1564 notEqualAndOrdered,
1565 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1566
1567 thenCase->appendNewControlValue(
1568 proc, Return, Origin(),
1569 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1570
1571 elseCase->appendNewControlValue(
1572 proc, Return, Origin(),
1573 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1574
1575 int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
1576 CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
1577}
1578
1579void testBranchNotEqualAndOrderedArgs(float a, float b)
1580{
1581 Procedure proc;
1582 BasicBlock* root = proc.addBlock();
1583 BasicBlock* thenCase = proc.addBlock();
1584 BasicBlock* elseCase = proc.addBlock();
1585
1586 Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1587 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1588 Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1589 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1590 Value* equalOrUnordered = root->appendNew<Value>(
1591 proc, EqualOrUnordered, Origin(),
1592 argumentA,
1593 argumentB);
1594 Value* notEqualAndOrdered = root->appendNew<Value>(
1595 proc, Equal, Origin(),
1596 root->appendNew<Const32Value>(proc, Origin(), 0),
1597 equalOrUnordered);
1598 root->appendNewControlValue(
1599 proc, Branch, Origin(),
1600 notEqualAndOrdered,
1601 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1602
1603 thenCase->appendNewControlValue(
1604 proc, Return, Origin(),
1605 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1606
1607 elseCase->appendNewControlValue(
1608 proc, Return, Origin(),
1609 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1610
1611 int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
1612 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1613}
1614
1615void testBranchEqualOrUnorderedDoubleArgImm(double a, double b)
1616{
1617 Procedure proc;
1618 BasicBlock* root = proc.addBlock();
1619 BasicBlock* thenCase = proc.addBlock();
1620 BasicBlock* elseCase = proc.addBlock();
1621
1622 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1623 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1624 root->appendNewControlValue(
1625 proc, Branch, Origin(),
1626 root->appendNew<Value>(
1627 proc, EqualOrUnordered, Origin(),
1628 argumentA,
1629 argumentB),
1630 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1631
1632 thenCase->appendNewControlValue(
1633 proc, Return, Origin(),
1634 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1635
1636 elseCase->appendNewControlValue(
1637 proc, Return, Origin(),
1638 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1639
1640 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1641 CHECK(compileAndRun<int64_t>(proc, a) == expected);
1642}
1643
1644void testBranchEqualOrUnorderedFloatArgImm(float a, float b)
1645{
1646 Procedure proc;
1647 BasicBlock* root = proc.addBlock();
1648 BasicBlock* thenCase = proc.addBlock();
1649 BasicBlock* elseCase = proc.addBlock();
1650
1651 Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1652 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1653 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1654
1655 root->appendNewControlValue(
1656 proc, Branch, Origin(),
1657 root->appendNew<Value>(
1658 proc, EqualOrUnordered, Origin(),
1659 argumentA,
1660 argumentB),
1661 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1662
1663 thenCase->appendNewControlValue(
1664 proc, Return, Origin(),
1665 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1666
1667 elseCase->appendNewControlValue(
1668 proc, Return, Origin(),
1669 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1670
1671 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1672 CHECK(compileAndRun<int64_t>(proc, &a) == expected);
1673}
1674
1675void testBranchEqualOrUnorderedDoubleImms(double a, double b)
1676{
1677 Procedure proc;
1678 BasicBlock* root = proc.addBlock();
1679 BasicBlock* thenCase = proc.addBlock();
1680 BasicBlock* elseCase = proc.addBlock();
1681
1682 Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1683 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1684 root->appendNewControlValue(
1685 proc, Branch, Origin(),
1686 root->appendNew<Value>(
1687 proc, EqualOrUnordered, Origin(),
1688 argumentA,
1689 argumentB),
1690 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1691
1692 thenCase->appendNewControlValue(
1693 proc, Return, Origin(),
1694 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1695
1696 elseCase->appendNewControlValue(
1697 proc, Return, Origin(),
1698 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1699
1700 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1701 CHECK(compileAndRun<int64_t>(proc) == expected);
1702}
1703
1704void testBranchEqualOrUnorderedFloatImms(float a, float b)
1705{
1706 Procedure proc;
1707 BasicBlock* root = proc.addBlock();
1708 BasicBlock* thenCase = proc.addBlock();
1709 BasicBlock* elseCase = proc.addBlock();
1710
1711 Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1712 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1713
1714 root->appendNewControlValue(
1715 proc, Branch, Origin(),
1716 root->appendNew<Value>(
1717 proc, EqualOrUnordered, Origin(),
1718 argumentA,
1719 argumentB),
1720 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1721
1722 thenCase->appendNewControlValue(
1723 proc, Return, Origin(),
1724 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1725
1726 elseCase->appendNewControlValue(
1727 proc, Return, Origin(),
1728 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1729
1730 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1731 CHECK(compileAndRun<int64_t>(proc) == expected);
1732}
1733
1734void testBranchEqualOrUnorderedFloatWithUselessDoubleConversion(float a, float b)
1735{
1736 Procedure proc;
1737 BasicBlock* root = proc.addBlock();
1738 BasicBlock* thenCase = proc.addBlock();
1739 BasicBlock* elseCase = proc.addBlock();
1740
1741 Value* argument1 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1742 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1743 Value* argument2 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
1744 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1745 Value* argument1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument1);
1746 Value* argument2AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument2);
1747
1748 root->appendNewControlValue(
1749 proc, Branch, Origin(),
1750 root->appendNew<Value>(
1751 proc, EqualOrUnordered, Origin(),
1752 argument1AsDouble,
1753 argument2AsDouble),
1754 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1755
1756 thenCase->appendNewControlValue(
1757 proc, Return, Origin(),
1758 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1759
1760 elseCase->appendNewControlValue(
1761 proc, Return, Origin(),
1762 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1763
1764 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1765 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1766}
1767
1768void testBranchFold(int value)
1769{
1770 Procedure proc;
1771 BasicBlock* root = proc.addBlock();
1772 BasicBlock* thenCase = proc.addBlock();
1773 BasicBlock* elseCase = proc.addBlock();
1774
1775 root->appendNewControlValue(
1776 proc, Branch, Origin(),
1777 root->appendNew<Const32Value>(proc, Origin(), value),
1778 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1779
1780 thenCase->appendNewControlValue(
1781 proc, Return, Origin(),
1782 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1783
1784 elseCase->appendNewControlValue(
1785 proc, Return, Origin(),
1786 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1787
1788 CHECK(compileAndRun<int>(proc) == !!value);
1789}
1790
1791void testDiamondFold(int value)
1792{
1793 Procedure proc;
1794 BasicBlock* root = proc.addBlock();
1795 BasicBlock* thenCase = proc.addBlock();
1796 BasicBlock* elseCase = proc.addBlock();
1797 BasicBlock* done = proc.addBlock();
1798
1799 root->appendNewControlValue(
1800 proc, Branch, Origin(),
1801 root->appendNew<Const32Value>(proc, Origin(), value),
1802 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1803
1804 UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
1805 proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1806 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1807
1808 UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
1809 proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1810 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1811
1812 Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
1813 thenResult->setPhi(phi);
1814 elseResult->setPhi(phi);
1815 done->appendNewControlValue(proc, Return, Origin(), phi);
1816
1817 CHECK(compileAndRun<int>(proc) == !!value);
1818}
1819
1820void testBranchNotEqualFoldPtr(intptr_t value)
1821{
1822 Procedure proc;
1823 BasicBlock* root = proc.addBlock();
1824 BasicBlock* thenCase = proc.addBlock();
1825 BasicBlock* elseCase = proc.addBlock();
1826
1827 root->appendNewControlValue(
1828 proc, Branch, Origin(),
1829 root->appendNew<Value>(
1830 proc, NotEqual, Origin(),
1831 root->appendNew<ConstPtrValue>(proc, Origin(), value),
1832 root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
1833 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1834
1835 thenCase->appendNewControlValue(
1836 proc, Return, Origin(),
1837 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1838
1839 elseCase->appendNewControlValue(
1840 proc, Return, Origin(),
1841 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1842
1843 CHECK(compileAndRun<int>(proc) == !!value);
1844}
1845
1846void testBranchEqualFoldPtr(intptr_t value)
1847{
1848 Procedure proc;
1849 BasicBlock* root = proc.addBlock();
1850 BasicBlock* thenCase = proc.addBlock();
1851 BasicBlock* elseCase = proc.addBlock();
1852
1853 root->appendNewControlValue(
1854 proc, Branch, Origin(),
1855 root->appendNew<Value>(
1856 proc, Equal, Origin(),
1857 root->appendNew<ConstPtrValue>(proc, Origin(), value),
1858 root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
1859 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1860
1861 thenCase->appendNewControlValue(
1862 proc, Return, Origin(),
1863 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1864
1865 elseCase->appendNewControlValue(
1866 proc, Return, Origin(),
1867 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1868
1869 CHECK(compileAndRun<int>(proc) == !value);
1870}
1871
1872void testBranchLoadPtr()
1873{
1874 Procedure proc;
1875 BasicBlock* root = proc.addBlock();
1876 BasicBlock* thenCase = proc.addBlock();
1877 BasicBlock* elseCase = proc.addBlock();
1878
1879 root->appendNewControlValue(
1880 proc, Branch, Origin(),
1881 root->appendNew<MemoryValue>(
1882 proc, Load, pointerType(), Origin(),
1883 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1884 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1885
1886 thenCase->appendNewControlValue(
1887 proc, Return, Origin(),
1888 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1889
1890 elseCase->appendNewControlValue(
1891 proc, Return, Origin(),
1892 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1893
1894 auto code = compileProc(proc);
1895 intptr_t cond;
1896 cond = 42;
1897 CHECK(invoke<int>(*code, &cond) == 1);
1898 cond = 0;
1899 CHECK(invoke<int>(*code, &cond) == 0);
1900}
1901
1902void testBranchLoad32()
1903{
1904 Procedure proc;
1905 BasicBlock* root = proc.addBlock();
1906 BasicBlock* thenCase = proc.addBlock();
1907 BasicBlock* elseCase = proc.addBlock();
1908
1909 root->appendNewControlValue(
1910 proc, Branch, Origin(),
1911 root->appendNew<MemoryValue>(
1912 proc, Load, Int32, Origin(),
1913 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1914 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1915
1916 thenCase->appendNewControlValue(
1917 proc, Return, Origin(),
1918 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1919
1920 elseCase->appendNewControlValue(
1921 proc, Return, Origin(),
1922 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1923
1924 auto code = compileProc(proc);
1925 int32_t cond;
1926 cond = 42;
1927 CHECK(invoke<int>(*code, &cond) == 1);
1928 cond = 0;
1929 CHECK(invoke<int>(*code, &cond) == 0);
1930}
1931
1932void testBranchLoad8S()
1933{
1934 Procedure proc;
1935 BasicBlock* root = proc.addBlock();
1936 BasicBlock* thenCase = proc.addBlock();
1937 BasicBlock* elseCase = proc.addBlock();
1938
1939 root->appendNewControlValue(
1940 proc, Branch, Origin(),
1941 root->appendNew<MemoryValue>(
1942 proc, Load8S, Origin(),
1943 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1944 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1945
1946 thenCase->appendNewControlValue(
1947 proc, Return, Origin(),
1948 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1949
1950 elseCase->appendNewControlValue(
1951 proc, Return, Origin(),
1952 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1953
1954 auto code = compileProc(proc);
1955 int8_t cond;
1956 cond = -1;
1957 CHECK(invoke<int>(*code, &cond) == 1);
1958 cond = 0;
1959 CHECK(invoke<int>(*code, &cond) == 0);
1960}
1961
1962void testBranchLoad8Z()
1963{
1964 Procedure proc;
1965 BasicBlock* root = proc.addBlock();
1966 BasicBlock* thenCase = proc.addBlock();
1967 BasicBlock* elseCase = proc.addBlock();
1968
1969 root->appendNewControlValue(
1970 proc, Branch, Origin(),
1971 root->appendNew<MemoryValue>(
1972 proc, Load8Z, Origin(),
1973 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1974 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1975
1976 thenCase->appendNewControlValue(
1977 proc, Return, Origin(),
1978 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1979
1980 elseCase->appendNewControlValue(
1981 proc, Return, Origin(),
1982 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1983
1984 auto code = compileProc(proc);
1985 uint8_t cond;
1986 cond = 1;
1987 CHECK(invoke<int>(*code, &cond) == 1);
1988 cond = 0;
1989 CHECK(invoke<int>(*code, &cond) == 0);
1990}
1991
1992void testBranchLoad16S()
1993{
1994 Procedure proc;
1995 BasicBlock* root = proc.addBlock();
1996 BasicBlock* thenCase = proc.addBlock();
1997 BasicBlock* elseCase = proc.addBlock();
1998
1999 root->appendNewControlValue(
2000 proc, Branch, Origin(),
2001 root->appendNew<MemoryValue>(
2002 proc, Load16S, Origin(),
2003 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2004 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2005
2006 thenCase->appendNewControlValue(
2007 proc, Return, Origin(),
2008 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2009
2010 elseCase->appendNewControlValue(
2011 proc, Return, Origin(),
2012 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2013
2014 auto code = compileProc(proc);
2015 int16_t cond;
2016 cond = -1;
2017 CHECK(invoke<int>(*code, &cond) == 1);
2018 cond = 0;
2019 CHECK(invoke<int>(*code, &cond) == 0);
2020}
2021
2022void testBranchLoad16Z()
2023{
2024 Procedure proc;
2025 BasicBlock* root = proc.addBlock();
2026 BasicBlock* thenCase = proc.addBlock();
2027 BasicBlock* elseCase = proc.addBlock();
2028
2029 root->appendNewControlValue(
2030 proc, Branch, Origin(),
2031 root->appendNew<MemoryValue>(
2032 proc, Load16Z, Origin(),
2033 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2034 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2035
2036 thenCase->appendNewControlValue(
2037 proc, Return, Origin(),
2038 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2039
2040 elseCase->appendNewControlValue(
2041 proc, Return, Origin(),
2042 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2043
2044 auto code = compileProc(proc);
2045 uint16_t cond;
2046 cond = 1;
2047 CHECK(invoke<int>(*code, &cond) == 1);
2048 cond = 0;
2049 CHECK(invoke<int>(*code, &cond) == 0);
2050}
2051
2052void testBranch8WithLoad8ZIndex()
2053{
2054 Procedure proc;
2055 BasicBlock* root = proc.addBlock();
2056 BasicBlock* thenCase = proc.addBlock();
2057 BasicBlock* elseCase = proc.addBlock();
2058
2059 int logScale = 1;
2060 root->appendNewControlValue(
2061 proc, Branch, Origin(),
2062 root->appendNew<Value>(
2063 proc, Above, Origin(),
2064 root->appendNew<MemoryValue>(
2065 proc, Load8Z, Origin(),
2066 root->appendNew<Value>(
2067 proc, Add, Origin(),
2068 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2069 root->appendNew<Value>(
2070 proc, Shl, Origin(),
2071 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
2072 root->appendNew<Const32Value>(proc, Origin(), logScale)))),
2073 root->appendNew<Const32Value>(proc, Origin(), 250)),
2074 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2075
2076 thenCase->appendNewControlValue(
2077 proc, Return, Origin(),
2078 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2079
2080 elseCase->appendNewControlValue(
2081 proc, Return, Origin(),
2082 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2083
2084 auto code = compileProc(proc);
2085 uint32_t cond;
2086 cond = 0xffffffffU; // All bytes are 0xff.
2087 CHECK(invoke<int>(*code, &cond - 2, (sizeof(uint32_t) * 2) >> logScale) == 1);
2088 cond = 0x00000000U; // All bytes are 0.
2089 CHECK(invoke<int>(*code, &cond - 2, (sizeof(uint32_t) * 2) >> logScale) == 0);
2090}
2091
2092void testComplex(unsigned numVars, unsigned numConstructs)
2093{
2094 MonotonicTime before = MonotonicTime::now();
2095
2096 Procedure proc;
2097 BasicBlock* current = proc.addBlock();
2098
2099 Const32Value* one = current->appendNew<Const32Value>(proc, Origin(), 1);
2100
2101 Vector<int32_t> varSlots;
2102 for (unsigned i = numVars; i--;)
2103 varSlots.append(i);
2104
2105 Vector<Value*> vars;
2106 for (int32_t& varSlot : varSlots) {
2107 Value* varSlotPtr = current->appendNew<ConstPtrValue>(proc, Origin(), &varSlot);
2108 vars.append(current->appendNew<MemoryValue>(proc, Load, Int32, Origin(), varSlotPtr));
2109 }
2110
2111 for (unsigned i = 0; i < numConstructs; ++i) {
2112 if (i & 1) {
2113 // Control flow diamond.
2114 unsigned predicateVarIndex = ((i >> 1) + 2) % numVars;
2115 unsigned thenIncVarIndex = ((i >> 1) + 0) % numVars;
2116 unsigned elseIncVarIndex = ((i >> 1) + 1) % numVars;
2117
2118 BasicBlock* thenBlock = proc.addBlock();
2119 BasicBlock* elseBlock = proc.addBlock();
2120 BasicBlock* continuation = proc.addBlock();
2121
2122 current->appendNewControlValue(
2123 proc, Branch, Origin(), vars[predicateVarIndex],
2124 FrequentedBlock(thenBlock), FrequentedBlock(elseBlock));
2125
2126 UpsilonValue* thenThenResult = thenBlock->appendNew<UpsilonValue>(
2127 proc, Origin(),
2128 thenBlock->appendNew<Value>(proc, Add, Origin(), vars[thenIncVarIndex], one));
2129 UpsilonValue* thenElseResult = thenBlock->appendNew<UpsilonValue>(
2130 proc, Origin(), vars[elseIncVarIndex]);
2131 thenBlock->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2132
2133 UpsilonValue* elseElseResult = elseBlock->appendNew<UpsilonValue>(
2134 proc, Origin(),
2135 elseBlock->appendNew<Value>(proc, Add, Origin(), vars[elseIncVarIndex], one));
2136 UpsilonValue* elseThenResult = elseBlock->appendNew<UpsilonValue>(
2137 proc, Origin(), vars[thenIncVarIndex]);
2138 elseBlock->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2139
2140 Value* thenPhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2141 thenThenResult->setPhi(thenPhi);
2142 elseThenResult->setPhi(thenPhi);
2143 vars[thenIncVarIndex] = thenPhi;
2144
2145 Value* elsePhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2146 thenElseResult->setPhi(elsePhi);
2147 elseElseResult->setPhi(elsePhi);
2148 vars[elseIncVarIndex] = thenPhi;
2149
2150 current = continuation;
2151 } else {
2152 // Loop.
2153
2154 BasicBlock* loopEntry = proc.addBlock();
2155 BasicBlock* loopReentry = proc.addBlock();
2156 BasicBlock* loopBody = proc.addBlock();
2157 BasicBlock* loopExit = proc.addBlock();
2158 BasicBlock* loopSkip = proc.addBlock();
2159 BasicBlock* continuation = proc.addBlock();
2160
2161 Value* startIndex = vars[((i >> 1) + 1) % numVars];
2162 Value* startSum = current->appendNew<Const32Value>(proc, Origin(), 0);
2163 current->appendNewControlValue(
2164 proc, Branch, Origin(), startIndex,
2165 FrequentedBlock(loopEntry), FrequentedBlock(loopSkip));
2166
2167 UpsilonValue* startIndexForBody = loopEntry->appendNew<UpsilonValue>(
2168 proc, Origin(), startIndex);
2169 UpsilonValue* startSumForBody = loopEntry->appendNew<UpsilonValue>(
2170 proc, Origin(), startSum);
2171 loopEntry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody));
2172
2173 Value* bodyIndex = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
2174 startIndexForBody->setPhi(bodyIndex);
2175 Value* bodySum = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
2176 startSumForBody->setPhi(bodySum);
2177 Value* newBodyIndex = loopBody->appendNew<Value>(proc, Sub, Origin(), bodyIndex, one);
2178 Value* newBodySum = loopBody->appendNew<Value>(
2179 proc, Add, Origin(),
2180 bodySum,
2181 loopBody->appendNew<MemoryValue>(
2182 proc, Load, Int32, Origin(),
2183 loopBody->appendNew<Value>(
2184 proc, Add, Origin(),
2185 loopBody->appendNew<ConstPtrValue>(proc, Origin(), varSlots.data()),
2186 loopBody->appendNew<Value>(
2187 proc, Shl, Origin(),
2188 loopBody->appendNew<Value>(
2189 proc, ZExt32, Origin(),
2190 loopBody->appendNew<Value>(
2191 proc, BitAnd, Origin(),
2192 newBodyIndex,
2193 loopBody->appendNew<Const32Value>(
2194 proc, Origin(), numVars - 1))),
2195 loopBody->appendNew<Const32Value>(proc, Origin(), 2)))));
2196 loopBody->appendNewControlValue(
2197 proc, Branch, Origin(), newBodyIndex,
2198 FrequentedBlock(loopReentry), FrequentedBlock(loopExit));
2199
2200 loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodyIndex, bodyIndex);
2201 loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodySum, bodySum);
2202 loopReentry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody));
2203
2204 UpsilonValue* exitSum = loopExit->appendNew<UpsilonValue>(proc, Origin(), newBodySum);
2205 loopExit->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2206
2207 UpsilonValue* skipSum = loopSkip->appendNew<UpsilonValue>(proc, Origin(), startSum);
2208 loopSkip->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2209
2210 Value* finalSum = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2211 exitSum->setPhi(finalSum);
2212 skipSum->setPhi(finalSum);
2213
2214 current = continuation;
2215 vars[((i >> 1) + 0) % numVars] = finalSum;
2216 }
2217 }
2218
2219 current->appendNewControlValue(proc, Return, Origin(), vars[0]);
2220
2221 compileProc(proc);
2222
2223 MonotonicTime after = MonotonicTime::now();
2224 dataLog(toCString(" That took ", (after - before).milliseconds(), " ms.\n"));
2225}
2226
2227void testBranchBitTest32TmpImm(uint32_t value, uint32_t imm)
2228{
2229 Procedure proc;
2230 BasicBlock* root = proc.addBlock();
2231 BasicBlock* thenCase = proc.addBlock();
2232 BasicBlock* elseCase = proc.addBlock();
2233
2234 Value* testValue = root->appendNew<Value>(
2235 proc, Trunc, Origin(),
2236 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2237 Value* bitOffset = root->appendNew<Const32Value>(proc, Origin(), imm);
2238
2239 Value* one = root->appendNew<Const32Value>(proc, Origin(), 1);
2240 Value* bitTest = root->appendNew<Value>(
2241 proc, BitAnd, Origin(),
2242 root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset),
2243 one);
2244
2245 root->appendNewControlValue(
2246 proc, Branch, Origin(),
2247 bitTest,
2248 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2249
2250 thenCase->appendNewControlValue(
2251 proc, Return, Origin(),
2252 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2253
2254 elseCase->appendNewControlValue(
2255 proc, Return, Origin(),
2256 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2257
2258 auto code = compileProc(proc);
2259 CHECK_EQ(invoke<uint32_t>(*code, value), (value>>(imm%32))&1);
2260}
2261
2262void testBranchBitTest32AddrImm(uint32_t value, uint32_t imm)
2263{
2264 Procedure proc;
2265 BasicBlock* root = proc.addBlock();
2266 BasicBlock* thenCase = proc.addBlock();
2267 BasicBlock* elseCase = proc.addBlock();
2268
2269 Value* testValue = root->appendNew<MemoryValue>(
2270 proc, Load, Int32, Origin(),
2271 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2272 Value* bitOffset = root->appendNew<Const32Value>(proc, Origin(), imm);
2273
2274 Value* one = root->appendNew<Const32Value>(proc, Origin(), 1);
2275 Value* bitTest = root->appendNew<Value>(
2276 proc, BitAnd, Origin(),
2277 root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset),
2278 one);
2279
2280 root->appendNewControlValue(
2281 proc, Branch, Origin(),
2282 bitTest,
2283 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2284
2285 thenCase->appendNewControlValue(
2286 proc, Return, Origin(),
2287 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2288
2289 elseCase->appendNewControlValue(
2290 proc, Return, Origin(),
2291 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2292
2293 auto code = compileProc(proc);
2294 CHECK_EQ(invoke<uint32_t>(*code, &value), (value>>(imm%32))&1);
2295}
2296
2297void testBranchBitTest32TmpTmp(uint32_t value, uint32_t value2)
2298{
2299 Procedure proc;
2300 BasicBlock* root = proc.addBlock();
2301 BasicBlock* thenCase = proc.addBlock();
2302 BasicBlock* elseCase = proc.addBlock();
2303
2304 Value* testValue = root->appendNew<Value>(
2305 proc, Trunc, Origin(),
2306 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2307 Value* bitOffset = root->appendNew<Value>(
2308 proc, Trunc, Origin(),
2309 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2310
2311 Value* one = root->appendNew<Const32Value>(proc, Origin(), 1);
2312 Value* bitTest = root->appendNew<Value>(
2313 proc, BitAnd, Origin(),
2314 root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset),
2315 one);
2316
2317 root->appendNewControlValue(
2318 proc, Branch, Origin(),
2319 bitTest,
2320 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2321
2322 thenCase->appendNewControlValue(
2323 proc, Return, Origin(),
2324 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2325
2326 elseCase->appendNewControlValue(
2327 proc, Return, Origin(),
2328 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2329
2330 auto code = compileProc(proc);
2331 CHECK_EQ(invoke<uint32_t>(*code, value, value2), (value>>(value2%32))&1);
2332}
2333
2334void testBranchBitTest64TmpTmp(uint64_t value, uint64_t value2)
2335{
2336 Procedure proc;
2337 BasicBlock* root = proc.addBlock();
2338 BasicBlock* thenCase = proc.addBlock();
2339 BasicBlock* elseCase = proc.addBlock();
2340
2341 Value* testValue = root->appendNew<Value>(proc, BitXor, Origin(),
2342 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2343 root->appendNew<Const64Value>(proc, Origin(), -1l));
2344 Value* bitOffset = root->appendNew<Value>(
2345 proc, Trunc, Origin(),
2346 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2347
2348 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2349 Value* bitTest = root->appendNew<Value>(
2350 proc, BitAnd, Origin(),
2351 testValue,
2352 root->appendNew<Value>(proc, Shl, Origin(), one, bitOffset));
2353
2354 root->appendNewControlValue(
2355 proc, Branch, Origin(),
2356 bitTest,
2357 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2358
2359 thenCase->appendNewControlValue(
2360 proc, Return, Origin(),
2361 thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2362
2363 elseCase->appendNewControlValue(
2364 proc, Return, Origin(),
2365 elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2366
2367 auto code = compileProc(proc);
2368 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2369}
2370
2371void testBranchBitTest64AddrTmp(uint64_t value, uint64_t value2)
2372{
2373 Procedure proc;
2374 BasicBlock* root = proc.addBlock();
2375 BasicBlock* thenCase = proc.addBlock();
2376 BasicBlock* elseCase = proc.addBlock();
2377
2378 Value* testValue = root->appendNew<MemoryValue>(
2379 proc, Load, Int64, Origin(),
2380 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2381 Value* bitOffset = root->appendNew<Value>(
2382 proc, Trunc, Origin(),
2383 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2384
2385 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2386 Value* bitTest = root->appendNew<Value>(
2387 proc, BitAnd, Origin(),
2388 testValue,
2389 root->appendNew<Value>(proc, Shl, Origin(), one, bitOffset));
2390
2391 root->appendNewControlValue(
2392 proc, Branch, Origin(),
2393 bitTest,
2394 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2395
2396 thenCase->appendNewControlValue(
2397 proc, Return, Origin(),
2398 thenCase->appendNew<Const64Value>(proc, Origin(), 1));
2399
2400 elseCase->appendNewControlValue(
2401 proc, Return, Origin(),
2402 elseCase->appendNew<Const64Value>(proc, Origin(), 0));
2403
2404 auto code = compileProc(proc);
2405 CHECK_EQ(invoke<uint64_t>(*code, &value, value2), (value>>(value2%64))&1);
2406}
2407
2408void testBranchBitTestNegation(uint64_t value, uint64_t value2)
2409{
2410 Procedure proc;
2411 BasicBlock* root = proc.addBlock();
2412 BasicBlock* thenCase = proc.addBlock();
2413 BasicBlock* elseCase = proc.addBlock();
2414
2415 Value* testValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2416 Value* bitOffset = root->appendNew<Value>(
2417 proc, Trunc, Origin(),
2418 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2419 Value* shift = root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset);
2420
2421 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2422 Value* bitTest = root->appendNew<Value>(
2423 proc, BitAnd, Origin(),
2424 root->appendNew<Value>(proc, BitXor, Origin(), shift, root->appendNew<Const64Value>(proc, Origin(), -1l)),
2425 one);
2426
2427 root->appendNewControlValue(
2428 proc, Branch, Origin(),
2429 bitTest,
2430 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2431
2432 thenCase->appendNewControlValue(
2433 proc, Return, Origin(),
2434 thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2435
2436 elseCase->appendNewControlValue(
2437 proc, Return, Origin(),
2438 elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2439
2440 auto code = compileProc(proc);
2441 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2442}
2443
2444void testBranchBitTestNegation2(uint64_t value, uint64_t value2)
2445{
2446 Procedure proc;
2447 BasicBlock* root = proc.addBlock();
2448 BasicBlock* thenCase = proc.addBlock();
2449 BasicBlock* elseCase = proc.addBlock();
2450
2451 Value* testValue = root->appendNew<Value>(proc, BitXor, Origin(),
2452 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2453 root->appendNew<Const64Value>(proc, Origin(), -1l));
2454 Value* bitOffset = root->appendNew<Value>(
2455 proc, Trunc, Origin(),
2456 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2457 Value* shift = root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset);
2458
2459 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2460 Value* bitTest = root->appendNew<Value>(
2461 proc, BitAnd, Origin(),
2462 shift,
2463 one);
2464
2465 root->appendNewControlValue(
2466 proc, Branch, Origin(),
2467 bitTest,
2468 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2469
2470 thenCase->appendNewControlValue(
2471 proc, Return, Origin(),
2472 thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2473
2474 elseCase->appendNewControlValue(
2475 proc, Return, Origin(),
2476 elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2477
2478 auto code = compileProc(proc);
2479 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2480}
2481
2482void testSimplePatchpoint()
2483{
2484 Procedure proc;
2485 BasicBlock* root = proc.addBlock();
2486 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2487 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2488 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2489 patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
2490 patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
2491 patchpoint->setGenerator(
2492 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2493 AllowMacroScratchRegisterUsage allowScratch(jit);
2494 CHECK(params.size() == 3);
2495 CHECK(params[0].isGPR());
2496 CHECK(params[1].isGPR());
2497 CHECK(params[2].isGPR());
2498 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2499 });
2500 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2501
2502 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2503}
2504
2505void testSimplePatchpointWithoutOuputClobbersGPArgs()
2506{
2507 Procedure proc;
2508 BasicBlock* root = proc.addBlock();
2509 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2510 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2511 Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42);
2512 Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
2513
2514 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
2515 patchpoint->clobberLate(RegisterSet(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1));
2516 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2517 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
2518 patchpoint->setGenerator(
2519 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2520 AllowMacroScratchRegisterUsage allowScratch(jit);
2521 CHECK(params.size() == 2);
2522 CHECK(params[0].isGPR());
2523 CHECK(params[1].isGPR());
2524 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params[0].gpr());
2525 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params[1].gpr());
2526 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR0);
2527 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR1);
2528 });
2529
2530 Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
2531 root->appendNewControlValue(proc, Return, Origin(), result);
2532
2533 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2534}
2535
2536void testSimplePatchpointWithOuputClobbersGPArgs()
2537{
2538 // We can't predict where the output will be but we want to be sure it is not
2539 // one of the clobbered registers which is a bit hard to test.
2540 //
2541 // What we do is force the hand of our register allocator by clobbering absolutely
2542 // everything but 1. The only valid allocation is to give it to the result and
2543 // spill everything else.
2544
2545 Procedure proc;
2546 if (proc.optLevel() < 1) {
2547 // FIXME: Air O0 allocator can't handle such programs. We rely on WasmAirIRGenerator
2548 // to not use any such constructs where the register allocator is cornered in such
2549 // a way.
2550 // https://bugs.webkit.org/show_bug.cgi?id=194633
2551 return;
2552 }
2553 BasicBlock* root = proc.addBlock();
2554 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2555 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2556 Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42);
2557 Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
2558
2559 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int64, Origin());
2560
2561 RegisterSet clobberAll = RegisterSet::allGPRs();
2562 clobberAll.exclude(RegisterSet::stackRegisters());
2563 clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
2564 clobberAll.clear(GPRInfo::argumentGPR2);
2565 patchpoint->clobberLate(clobberAll);
2566
2567 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2568 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
2569
2570 patchpoint->setGenerator(
2571 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2572 AllowMacroScratchRegisterUsage allowScratch(jit);
2573 CHECK(params.size() == 3);
2574 CHECK(params[0].isGPR());
2575 CHECK(params[1].isGPR());
2576 CHECK(params[2].isGPR());
2577 jit.move(params[1].gpr(), params[0].gpr());
2578 jit.add64(params[2].gpr(), params[0].gpr());
2579
2580 clobberAll.forEach([&] (Reg reg) {
2581 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), reg.gpr());
2582 });
2583 });
2584
2585 Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint,
2586 root->appendNew<Value>(proc, Add, Origin(), arg1, arg2));
2587 root->appendNewControlValue(proc, Return, Origin(), result);
2588
2589 CHECK(compileAndRun<int>(proc, 1, 2) == 58);
2590}
2591
2592void testSimplePatchpointWithoutOuputClobbersFPArgs()
2593{
2594 Procedure proc;
2595 BasicBlock* root = proc.addBlock();
2596 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2597 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2598 Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
2599 Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
2600
2601 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
2602 patchpoint->clobberLate(RegisterSet(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1));
2603 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2604 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
2605 patchpoint->setGenerator(
2606 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2607 AllowMacroScratchRegisterUsage allowScratch(jit);
2608 CHECK(params.size() == 2);
2609 CHECK(params[0].isFPR());
2610 CHECK(params[1].isFPR());
2611 jit.moveZeroToDouble(params[0].fpr());
2612 jit.moveZeroToDouble(params[1].fpr());
2613 jit.moveZeroToDouble(FPRInfo::argumentFPR0);
2614 jit.moveZeroToDouble(FPRInfo::argumentFPR1);
2615 });
2616
2617 Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
2618 root->appendNewControlValue(proc, Return, Origin(), result);
2619
2620 CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 4);
2621}
2622
2623void testSimplePatchpointWithOuputClobbersFPArgs()
2624{
2625 Procedure proc;
2626 if (proc.optLevel() < 1) {
2627 // FIXME: Air O0 allocator can't handle such programs. We rely on WasmAirIRGenerator
2628 // to not use any such constructs where the register allocator is cornered in such
2629 // a way.
2630 // https://bugs.webkit.org/show_bug.cgi?id=194633
2631 return;
2632 }
2633 BasicBlock* root = proc.addBlock();
2634 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2635 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2636 Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
2637 Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
2638
2639 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin());
2640
2641 RegisterSet clobberAll = RegisterSet::allFPRs();
2642 clobberAll.exclude(RegisterSet::stackRegisters());
2643 clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
2644 clobberAll.clear(FPRInfo::argumentFPR2);
2645 patchpoint->clobberLate(clobberAll);
2646
2647 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2648 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
2649
2650 patchpoint->setGenerator(
2651 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2652 AllowMacroScratchRegisterUsage allowScratch(jit);
2653 CHECK(params.size() == 3);
2654 CHECK(params[0].isFPR());
2655 CHECK(params[1].isFPR());
2656 CHECK(params[2].isFPR());
2657 jit.addDouble(params[1].fpr(), params[2].fpr(), params[0].fpr());
2658
2659 clobberAll.forEach([&] (Reg reg) {
2660 jit.moveZeroToDouble(reg.fpr());
2661 });
2662 });
2663
2664 Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint,
2665 root->appendNew<Value>(proc, Add, Origin(), arg1, arg2));
2666 root->appendNewControlValue(proc, Return, Origin(), result);
2667
2668 CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 59.6);
2669}
2670
2671void testPatchpointWithEarlyClobber()
2672{
2673 auto test = [] (GPRReg registerToClobber, bool arg1InArgGPR, bool arg2InArgGPR) {
2674 Procedure proc;
2675 BasicBlock* root = proc.addBlock();
2676 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2677 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2678
2679 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2680 patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
2681 patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
2682 patchpoint->clobberEarly(RegisterSet(registerToClobber));
2683 unsigned optLevel = proc.optLevel();
2684 patchpoint->setGenerator(
2685 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2686 if (optLevel > 1) {
2687 CHECK((params[1].gpr() == GPRInfo::argumentGPR0) == arg1InArgGPR);
2688 CHECK((params[2].gpr() == GPRInfo::argumentGPR1) == arg2InArgGPR);
2689 }
2690
2691 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2692 });
2693
2694 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2695
2696 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2697 };
2698
2699 test(GPRInfo::nonArgGPR0, true, true);
2700 test(GPRInfo::argumentGPR0, false, true);
2701 test(GPRInfo::argumentGPR1, true, false);
2702}
2703
2704void testPatchpointCallArg()
2705{
2706 Procedure proc;
2707 BasicBlock* root = proc.addBlock();
2708 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2709 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2710 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2711 patchpoint->append(ConstrainedValue(arg1, ValueRep::stackArgument(0)));
2712 patchpoint->append(ConstrainedValue(arg2, ValueRep::stackArgument(8)));
2713 patchpoint->setGenerator(
2714 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2715 AllowMacroScratchRegisterUsage allowScratch(jit);
2716 CHECK(params.size() == 3);
2717 CHECK(params[0].isGPR());
2718 CHECK(params[1].isStack());
2719 CHECK(params[2].isStack());
2720 jit.load32(
2721 CCallHelpers::Address(GPRInfo::callFrameRegister, params[1].offsetFromFP()),
2722 params[0].gpr());
2723 jit.add32(
2724 CCallHelpers::Address(GPRInfo::callFrameRegister, params[2].offsetFromFP()),
2725 params[0].gpr());
2726 });
2727 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2728
2729 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2730}
2731
2732void testPatchpointFixedRegister()
2733{
2734 Procedure proc;
2735 BasicBlock* root = proc.addBlock();
2736 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2737 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2738 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2739 patchpoint->append(ConstrainedValue(arg1, ValueRep(GPRInfo::regT0)));
2740 patchpoint->append(ConstrainedValue(arg2, ValueRep(GPRInfo::regT1)));
2741 patchpoint->setGenerator(
2742 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2743 AllowMacroScratchRegisterUsage allowScratch(jit);
2744 CHECK(params.size() == 3);
2745 CHECK(params[0].isGPR());
2746 CHECK(params[1] == ValueRep(GPRInfo::regT0));
2747 CHECK(params[2] == ValueRep(GPRInfo::regT1));
2748 add32(jit, GPRInfo::regT0, GPRInfo::regT1, params[0].gpr());
2749 });
2750 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2751
2752 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2753}
2754
2755void testPatchpointAny(ValueRep rep)
2756{
2757 Procedure proc;
2758 BasicBlock* root = proc.addBlock();
2759 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2760 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2761 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2762 patchpoint->append(ConstrainedValue(arg1, rep));
2763 patchpoint->append(ConstrainedValue(arg2, rep));
2764 patchpoint->setGenerator(
2765 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2766 AllowMacroScratchRegisterUsage allowScratch(jit);
2767 // We shouldn't have spilled the inputs, so we assert that they're in registers.
2768 CHECK(params.size() == 3);
2769 CHECK(params[0].isGPR());
2770 CHECK(params[1].isGPR());
2771 CHECK(params[2].isGPR());
2772 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2773 });
2774 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2775
2776 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2777}
2778
2779void testPatchpointGPScratch()
2780{
2781 Procedure proc;
2782 BasicBlock* root = proc.addBlock();
2783 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2784 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2785 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2786 patchpoint->append(arg1, ValueRep::SomeRegister);
2787 patchpoint->append(arg2, ValueRep::SomeRegister);
2788 patchpoint->numGPScratchRegisters = 2;
2789 patchpoint->setGenerator(
2790 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2791 AllowMacroScratchRegisterUsage allowScratch(jit);
2792 // We shouldn't have spilled the inputs, so we assert that they're in registers.
2793 CHECK(params.size() == 3);
2794 CHECK(params[0].isGPR());
2795 CHECK(params[1].isGPR());
2796 CHECK(params[2].isGPR());
2797 CHECK(params.gpScratch(0) != InvalidGPRReg);
2798 CHECK(params.gpScratch(0) != params[0].gpr());
2799 CHECK(params.gpScratch(0) != params[1].gpr());
2800 CHECK(params.gpScratch(0) != params[2].gpr());
2801 CHECK(params.gpScratch(1) != InvalidGPRReg);
2802 CHECK(params.gpScratch(1) != params.gpScratch(0));
2803 CHECK(params.gpScratch(1) != params[0].gpr());
2804 CHECK(params.gpScratch(1) != params[1].gpr());
2805 CHECK(params.gpScratch(1) != params[2].gpr());
2806 CHECK(!params.unavailableRegisters().get(params.gpScratch(0)));
2807 CHECK(!params.unavailableRegisters().get(params.gpScratch(1)));
2808 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2809 });
2810 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2811
2812 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2813}
2814
2815void testPatchpointFPScratch()
2816{
2817 Procedure proc;
2818 BasicBlock* root = proc.addBlock();
2819 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2820 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2821 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2822 patchpoint->append(arg1, ValueRep::SomeRegister);
2823 patchpoint->append(arg2, ValueRep::SomeRegister);
2824 patchpoint->numFPScratchRegisters = 2;
2825 patchpoint->setGenerator(
2826 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2827 AllowMacroScratchRegisterUsage allowScratch(jit);
2828 // We shouldn't have spilled the inputs, so we assert that they're in registers.
2829 CHECK(params.size() == 3);
2830 CHECK(params[0].isGPR());
2831 CHECK(params[1].isGPR());
2832 CHECK(params[2].isGPR());
2833 CHECK(params.fpScratch(0) != InvalidFPRReg);
2834 CHECK(params.fpScratch(1) != InvalidFPRReg);
2835 CHECK(params.fpScratch(1) != params.fpScratch(0));
2836 CHECK(!params.unavailableRegisters().get(params.fpScratch(0)));
2837 CHECK(!params.unavailableRegisters().get(params.fpScratch(1)));
2838 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2839 });
2840 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2841
2842 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2843}
2844
2845void testPatchpointLotsOfLateAnys()
2846{
2847 Procedure proc;
2848 BasicBlock* root = proc.addBlock();
2849 Vector<int> things;
2850 for (unsigned i = 200; i--;)
2851 things.append(i);
2852
2853 Vector<Value*> values;
2854 for (int& thing : things) {
2855 Value* value = root->appendNew<MemoryValue>(
2856 proc, Load, Int32, Origin(),
2857 root->appendNew<ConstPtrValue>(proc, Origin(), &thing));
2858 values.append(value);
2859 }
2860
2861 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2862 patchpoint->clobber(RegisterSet::macroScratchRegisters());
2863 for (Value* value : values)
2864 patchpoint->append(ConstrainedValue(value, ValueRep::LateColdAny));
2865 patchpoint->setGenerator(
2866 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2867 AllowMacroScratchRegisterUsage allowScratch(jit);
2868 // We shouldn't have spilled the inputs, so we assert that they're in registers.
2869 CHECK(params.size() == things.size() + 1);
2870 CHECK(params[0].isGPR());
2871 jit.move(CCallHelpers::TrustedImm32(0), params[0].gpr());
2872 for (unsigned i = 1; i < params.size(); ++i) {
2873 if (params[i].isGPR()) {
2874 CHECK(params[i] != params[0]);
2875 jit.add32(params[i].gpr(), params[0].gpr());
2876 } else {
2877 CHECK(params[i].isStack());
2878 jit.add32(CCallHelpers::Address(GPRInfo::callFrameRegister, params[i].offsetFromFP()), params[0].gpr());
2879 }
2880 }
2881 });
2882 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2883
2884 CHECK(static_cast<size_t>(compileAndRun<int>(proc)) == (things.size() * (things.size() - 1)) / 2);
2885}
2886
2887void testPatchpointAnyImm(ValueRep rep)
2888{
2889 Procedure proc;
2890 BasicBlock* root = proc.addBlock();
2891 Value* arg1 = root->appendNew<Value>(
2892 proc, Trunc, Origin(),
2893 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2894 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
2895 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
2896 patchpoint->append(ConstrainedValue(arg1, rep));
2897 patchpoint->append(ConstrainedValue(arg2, rep));
2898 patchpoint->setGenerator(
2899 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2900 AllowMacroScratchRegisterUsage allowScratch(jit);
2901 CHECK(params.size() == 3);
2902 CHECK(params[0].isGPR());
2903 CHECK(params[1].isGPR());
2904 CHECK(params[2].isConstant());
2905 CHECK(params[2].value() == 42);
2906 jit.add32(
2907 CCallHelpers::TrustedImm32(static_cast<int32_t>(params[2].value())),
2908 params[1].gpr(), params[0].gpr());
2909 });
2910 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2911
2912 CHECK(compileAndRun<int>(proc, 1) == 43);
2913}
2914
2915void addSExtTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks)
2916{
2917 RUN(testSExt8(0));
2918 RUN(testSExt8(1));
2919 RUN(testSExt8(42));
2920 RUN(testSExt8(-1));
2921 RUN(testSExt8(0xff));
2922 RUN(testSExt8(0x100));
2923 RUN(testSExt8Fold(0));
2924 RUN(testSExt8Fold(1));
2925 RUN(testSExt8Fold(42));
2926 RUN(testSExt8Fold(-1));
2927 RUN(testSExt8Fold(0xff));
2928 RUN(testSExt8Fold(0x100));
2929 RUN(testSExt8SExt8(0));
2930 RUN(testSExt8SExt8(1));
2931 RUN(testSExt8SExt8(42));
2932 RUN(testSExt8SExt8(-1));
2933 RUN(testSExt8SExt8(0xff));
2934 RUN(testSExt8SExt8(0x100));
2935 RUN(testSExt8SExt16(0));
2936 RUN(testSExt8SExt16(1));
2937 RUN(testSExt8SExt16(42));
2938 RUN(testSExt8SExt16(-1));
2939 RUN(testSExt8SExt16(0xff));
2940 RUN(testSExt8SExt16(0x100));
2941 RUN(testSExt8SExt16(0xffff));
2942 RUN(testSExt8SExt16(0x10000));
2943 RUN(testSExt8BitAnd(0, 0));
2944 RUN(testSExt8BitAnd(1, 0));
2945 RUN(testSExt8BitAnd(42, 0));
2946 RUN(testSExt8BitAnd(-1, 0));
2947 RUN(testSExt8BitAnd(0xff, 0));
2948 RUN(testSExt8BitAnd(0x100, 0));
2949 RUN(testSExt8BitAnd(0xffff, 0));
2950 RUN(testSExt8BitAnd(0x10000, 0));
2951 RUN(testSExt8BitAnd(0, 0xf));
2952 RUN(testSExt8BitAnd(1, 0xf));
2953 RUN(testSExt8BitAnd(42, 0xf));
2954 RUN(testSExt8BitAnd(-1, 0xf));
2955 RUN(testSExt8BitAnd(0xff, 0xf));
2956 RUN(testSExt8BitAnd(0x100, 0xf));
2957 RUN(testSExt8BitAnd(0xffff, 0xf));
2958 RUN(testSExt8BitAnd(0x10000, 0xf));
2959 RUN(testSExt8BitAnd(0, 0xff));
2960 RUN(testSExt8BitAnd(1, 0xff));
2961 RUN(testSExt8BitAnd(42, 0xff));
2962 RUN(testSExt8BitAnd(-1, 0xff));
2963 RUN(testSExt8BitAnd(0xff, 0xff));
2964 RUN(testSExt8BitAnd(0x100, 0xff));
2965 RUN(testSExt8BitAnd(0xffff, 0xff));
2966 RUN(testSExt8BitAnd(0x10000, 0xff));
2967 RUN(testSExt8BitAnd(0, 0x80));
2968 RUN(testSExt8BitAnd(1, 0x80));
2969 RUN(testSExt8BitAnd(42, 0x80));
2970 RUN(testSExt8BitAnd(-1, 0x80));
2971 RUN(testSExt8BitAnd(0xff, 0x80));
2972 RUN(testSExt8BitAnd(0x100, 0x80));
2973 RUN(testSExt8BitAnd(0xffff, 0x80));
2974 RUN(testSExt8BitAnd(0x10000, 0x80));
2975 RUN(testBitAndSExt8(0, 0xf));
2976 RUN(testBitAndSExt8(1, 0xf));
2977 RUN(testBitAndSExt8(42, 0xf));
2978 RUN(testBitAndSExt8(-1, 0xf));
2979 RUN(testBitAndSExt8(0xff, 0xf));
2980 RUN(testBitAndSExt8(0x100, 0xf));
2981 RUN(testBitAndSExt8(0xffff, 0xf));
2982 RUN(testBitAndSExt8(0x10000, 0xf));
2983 RUN(testBitAndSExt8(0, 0xff));
2984 RUN(testBitAndSExt8(1, 0xff));
2985 RUN(testBitAndSExt8(42, 0xff));
2986 RUN(testBitAndSExt8(-1, 0xff));
2987 RUN(testBitAndSExt8(0xff, 0xff));
2988 RUN(testBitAndSExt8(0x100, 0xff));
2989 RUN(testBitAndSExt8(0xffff, 0xff));
2990 RUN(testBitAndSExt8(0x10000, 0xff));
2991 RUN(testBitAndSExt8(0, 0xfff));
2992 RUN(testBitAndSExt8(1, 0xfff));
2993 RUN(testBitAndSExt8(42, 0xfff));
2994 RUN(testBitAndSExt8(-1, 0xfff));
2995 RUN(testBitAndSExt8(0xff, 0xfff));
2996 RUN(testBitAndSExt8(0x100, 0xfff));
2997 RUN(testBitAndSExt8(0xffff, 0xfff));
2998 RUN(testBitAndSExt8(0x10000, 0xfff));
2999
3000 RUN(testSExt16(0));
3001 RUN(testSExt16(1));
3002 RUN(testSExt16(42));
3003 RUN(testSExt16(-1));
3004 RUN(testSExt16(0xffff));
3005 RUN(testSExt16(0x10000));
3006 RUN(testSExt16Fold(0));
3007 RUN(testSExt16Fold(1));
3008 RUN(testSExt16Fold(42));
3009 RUN(testSExt16Fold(-1));
3010 RUN(testSExt16Fold(0xffff));
3011 RUN(testSExt16Fold(0x10000));
3012 RUN(testSExt16SExt8(0));
3013 RUN(testSExt16SExt8(1));
3014 RUN(testSExt16SExt8(42));
3015 RUN(testSExt16SExt8(-1));
3016 RUN(testSExt16SExt8(0xffff));
3017 RUN(testSExt16SExt8(0x10000));
3018 RUN(testSExt16SExt16(0));
3019 RUN(testSExt16SExt16(1));
3020 RUN(testSExt16SExt16(42));
3021 RUN(testSExt16SExt16(-1));
3022 RUN(testSExt16SExt16(0xffff));
3023 RUN(testSExt16SExt16(0x10000));
3024 RUN(testSExt16SExt16(0xffffff));
3025 RUN(testSExt16SExt16(0x1000000));
3026 RUN(testSExt16BitAnd(0, 0));
3027 RUN(testSExt16BitAnd(1, 0));
3028 RUN(testSExt16BitAnd(42, 0));
3029 RUN(testSExt16BitAnd(-1, 0));
3030 RUN(testSExt16BitAnd(0xffff, 0));
3031 RUN(testSExt16BitAnd(0x10000, 0));
3032 RUN(testSExt16BitAnd(0xffffff, 0));
3033 RUN(testSExt16BitAnd(0x1000000, 0));
3034 RUN(testSExt16BitAnd(0, 0xf));
3035 RUN(testSExt16BitAnd(1, 0xf));
3036 RUN(testSExt16BitAnd(42, 0xf));
3037 RUN(testSExt16BitAnd(-1, 0xf));
3038 RUN(testSExt16BitAnd(0xffff, 0xf));
3039 RUN(testSExt16BitAnd(0x10000, 0xf));
3040 RUN(testSExt16BitAnd(0xffffff, 0xf));
3041 RUN(testSExt16BitAnd(0x1000000, 0xf));
3042 RUN(testSExt16BitAnd(0, 0xffff));
3043 RUN(testSExt16BitAnd(1, 0xffff));
3044 RUN(testSExt16BitAnd(42, 0xffff));
3045 RUN(testSExt16BitAnd(-1, 0xffff));
3046 RUN(testSExt16BitAnd(0xffff, 0xffff));
3047 RUN(testSExt16BitAnd(0x10000, 0xffff));
3048 RUN(testSExt16BitAnd(0xffffff, 0xffff));
3049 RUN(testSExt16BitAnd(0x1000000, 0xffff));
3050 RUN(testSExt16BitAnd(0, 0x8000));
3051 RUN(testSExt16BitAnd(1, 0x8000));
3052 RUN(testSExt16BitAnd(42, 0x8000));
3053 RUN(testSExt16BitAnd(-1, 0x8000));
3054 RUN(testSExt16BitAnd(0xffff, 0x8000));
3055 RUN(testSExt16BitAnd(0x10000, 0x8000));
3056 RUN(testSExt16BitAnd(0xffffff, 0x8000));
3057 RUN(testSExt16BitAnd(0x1000000, 0x8000));
3058 RUN(testBitAndSExt16(0, 0xf));
3059 RUN(testBitAndSExt16(1, 0xf));
3060 RUN(testBitAndSExt16(42, 0xf));
3061 RUN(testBitAndSExt16(-1, 0xf));
3062 RUN(testBitAndSExt16(0xffff, 0xf));
3063 RUN(testBitAndSExt16(0x10000, 0xf));
3064 RUN(testBitAndSExt16(0xffffff, 0xf));
3065 RUN(testBitAndSExt16(0x1000000, 0xf));
3066 RUN(testBitAndSExt16(0, 0xffff));
3067 RUN(testBitAndSExt16(1, 0xffff));
3068 RUN(testBitAndSExt16(42, 0xffff));
3069 RUN(testBitAndSExt16(-1, 0xffff));
3070 RUN(testBitAndSExt16(0xffff, 0xffff));
3071 RUN(testBitAndSExt16(0x10000, 0xffff));
3072 RUN(testBitAndSExt16(0xffffff, 0xffff));
3073 RUN(testBitAndSExt16(0x1000000, 0xffff));
3074 RUN(testBitAndSExt16(0, 0xfffff));
3075 RUN(testBitAndSExt16(1, 0xfffff));
3076 RUN(testBitAndSExt16(42, 0xfffff));
3077 RUN(testBitAndSExt16(-1, 0xfffff));
3078 RUN(testBitAndSExt16(0xffff, 0xfffff));
3079 RUN(testBitAndSExt16(0x10000, 0xfffff));
3080 RUN(testBitAndSExt16(0xffffff, 0xfffff));
3081 RUN(testBitAndSExt16(0x1000000, 0xfffff));
3082
3083 RUN(testSExt32BitAnd(0, 0));
3084 RUN(testSExt32BitAnd(1, 0));
3085 RUN(testSExt32BitAnd(42, 0));
3086 RUN(testSExt32BitAnd(-1, 0));
3087 RUN(testSExt32BitAnd(0x80000000, 0));
3088 RUN(testSExt32BitAnd(0, 0xf));
3089 RUN(testSExt32BitAnd(1, 0xf));
3090 RUN(testSExt32BitAnd(42, 0xf));
3091 RUN(testSExt32BitAnd(-1, 0xf));
3092 RUN(testSExt32BitAnd(0x80000000, 0xf));
3093 RUN(testSExt32BitAnd(0, 0x80000000));
3094 RUN(testSExt32BitAnd(1, 0x80000000));
3095 RUN(testSExt32BitAnd(42, 0x80000000));
3096 RUN(testSExt32BitAnd(-1, 0x80000000));
3097 RUN(testSExt32BitAnd(0x80000000, 0x80000000));
3098 RUN(testBitAndSExt32(0, 0xf));
3099 RUN(testBitAndSExt32(1, 0xf));
3100 RUN(testBitAndSExt32(42, 0xf));
3101 RUN(testBitAndSExt32(-1, 0xf));
3102 RUN(testBitAndSExt32(0xffff, 0xf));
3103 RUN(testBitAndSExt32(0x10000, 0xf));
3104 RUN(testBitAndSExt32(0xffffff, 0xf));
3105 RUN(testBitAndSExt32(0x1000000, 0xf));
3106 RUN(testBitAndSExt32(0, 0xffff00000000llu));
3107 RUN(testBitAndSExt32(1, 0xffff00000000llu));
3108 RUN(testBitAndSExt32(42, 0xffff00000000llu));
3109 RUN(testBitAndSExt32(-1, 0xffff00000000llu));
3110 RUN(testBitAndSExt32(0x80000000, 0xffff00000000llu));
3111}
3112
3113#endif // ENABLE(B3_JIT)
3114