2 * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
31 void testStoreRelAddLoadAcq32(int amount)
34 BasicBlock* root = proc.addBlock();
36 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
37 root->appendNew<MemoryValue>(
38 proc, Store, Origin(),
39 root->appendNew<Value>(
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));
51 auto code = compileProc(proc);
53 checkUsesInstruction(*code, "lda");
54 checkUsesInstruction(*code, "stl");
57 checkUsesInstruction(*code, "xchg");
58 CHECK(!invoke<int>(*code, amount));
59 CHECK(slot == 37 + amount);
62 void testStoreAddLoadImm32(int amount)
65 BasicBlock* root = proc.addBlock();
67 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
68 root->appendNew<MemoryValue>(
69 proc, Store, Origin(),
70 root->appendNew<Value>(
72 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
73 root->appendNew<Const32Value>(proc, Origin(), amount)),
75 root->appendNewControlValue(
76 proc, Return, Origin(),
77 root->appendNew<Const32Value>(proc, Origin(), 0));
79 CHECK(!compileAndRun<int>(proc));
80 CHECK(slot == 37 + amount);
83 void testStoreAddLoad8(int amount, B3::Opcode loadOpcode)
86 BasicBlock* root = proc.addBlock();
88 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
89 root->appendNew<MemoryValue>(
90 proc, Store8, Origin(),
91 root->appendNew<Value>(
93 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
94 root->appendNew<Value>(
95 proc, Trunc, Origin(),
96 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
98 root->appendNewControlValue(
99 proc, Return, Origin(),
100 root->appendNew<Const32Value>(proc, Origin(), 0));
102 CHECK(!compileAndRun<int>(proc, amount));
103 CHECK(slot == 37 + amount);
106 void testStoreRelAddLoadAcq8(int amount, B3::Opcode loadOpcode)
109 BasicBlock* root = proc.addBlock();
111 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
112 root->appendNew<MemoryValue>(
113 proc, Store8, Origin(),
114 root->appendNew<Value>(
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));
126 auto code = compileProc(proc);
128 checkUsesInstruction(*code, "lda");
129 checkUsesInstruction(*code, "stl");
132 checkUsesInstruction(*code, "xchg");
133 CHECK(!invoke<int>(*code, amount));
134 CHECK(slot == 37 + amount);
137 void testStoreRelAddFenceLoadAcq8(int amount, B3::Opcode loadOpcode)
140 BasicBlock* root = proc.addBlock();
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);
152 patchpoint->effects = Effects::none();
153 patchpoint->effects.fence = true;
154 root->appendNew<MemoryValue>(
155 proc, Store8, Origin(),
156 root->appendNew<Value>(
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));
167 auto code = compileProc(proc);
169 checkUsesInstruction(*code, "lda");
170 checkUsesInstruction(*code, "stl");
173 checkUsesInstruction(*code, "xchg");
174 CHECK(!invoke<int>(*code, amount));
175 CHECK(slot == 37 + amount);
178 void testStoreAddLoadImm8(int amount, B3::Opcode loadOpcode)
181 BasicBlock* root = proc.addBlock();
183 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
184 root->appendNew<MemoryValue>(
185 proc, Store8, Origin(),
186 root->appendNew<Value>(
188 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
189 root->appendNew<Const32Value>(proc, Origin(), amount)),
191 root->appendNewControlValue(
192 proc, Return, Origin(),
193 root->appendNew<Const32Value>(proc, Origin(), 0));
195 CHECK(!compileAndRun<int>(proc));
196 CHECK(slot == 37 + amount);
199 void testStoreAddLoad16(int amount, B3::Opcode loadOpcode)
202 BasicBlock* root = proc.addBlock();
204 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
205 root->appendNew<MemoryValue>(
206 proc, Store16, Origin(),
207 root->appendNew<Value>(
209 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
210 root->appendNew<Value>(
211 proc, Trunc, Origin(),
212 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
214 root->appendNewControlValue(
215 proc, Return, Origin(),
216 root->appendNew<Const32Value>(proc, Origin(), 0));
218 CHECK(!compileAndRun<int>(proc, amount));
219 CHECK(slot == 37 + amount);
222 void testStoreRelAddLoadAcq16(int amount, B3::Opcode loadOpcode)
225 BasicBlock* root = proc.addBlock();
227 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
228 root->appendNew<MemoryValue>(
229 proc, Store16, Origin(),
230 root->appendNew<Value>(
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));
242 auto code = compileProc(proc);
244 checkUsesInstruction(*code, "lda");
245 checkUsesInstruction(*code, "stl");
248 checkUsesInstruction(*code, "xchg");
249 CHECK(!invoke<int>(*code, amount));
250 CHECK(slot == 37 + amount);
253 void testStoreAddLoadImm16(int amount, B3::Opcode loadOpcode)
256 BasicBlock* root = proc.addBlock();
258 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
259 root->appendNew<MemoryValue>(
260 proc, Store16, Origin(),
261 root->appendNew<Value>(
263 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
264 root->appendNew<Const32Value>(proc, Origin(), amount)),
266 root->appendNewControlValue(
267 proc, Return, Origin(),
268 root->appendNew<Const32Value>(proc, Origin(), 0));
270 CHECK(!compileAndRun<int>(proc));
271 CHECK(slot == 37 + amount);
274 void testStoreAddLoad64(int amount)
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>(
284 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
285 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
287 root->appendNewControlValue(
288 proc, Return, Origin(),
289 root->appendNew<Const32Value>(proc, Origin(), 0));
291 CHECK(!compileAndRun<int>(proc, amount));
292 CHECK(slot == 37000000000ll + amount);
295 void testStoreRelAddLoadAcq64(int amount)
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>(
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));
313 auto code = compileProc(proc);
315 checkUsesInstruction(*code, "lda");
316 checkUsesInstruction(*code, "stl");
319 checkUsesInstruction(*code, "xchg");
320 CHECK(!invoke<int>(*code, amount));
321 CHECK(slot == 37000000000ll + amount);
324 void testStoreAddLoadImm64(int64_t amount)
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>(
334 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
335 root->appendNew<Const64Value>(proc, Origin(), amount)),
337 root->appendNewControlValue(
338 proc, Return, Origin(),
339 root->appendNew<Const32Value>(proc, Origin(), 0));
341 CHECK(!compileAndRun<int>(proc));
342 CHECK(slot == 370000000000ll + amount);
345 void testStoreAddLoad32Index(int amount)
348 BasicBlock* root = proc.addBlock();
352 Value* slotPtr = root->appendNew<Value>(
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>(
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))),
369 root->appendNewControlValue(
370 proc, Return, Origin(),
371 root->appendNew<Const32Value>(proc, Origin(), 0));
373 CHECK(!compileAndRun<int>(proc, amount));
374 CHECK(slot == 37 + amount);
377 void testStoreAddLoadImm32Index(int amount)
380 BasicBlock* root = proc.addBlock();
384 Value* slotPtr = root->appendNew<Value>(
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>(
396 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
397 root->appendNew<Const32Value>(proc, Origin(), amount)),
399 root->appendNewControlValue(
400 proc, Return, Origin(),
401 root->appendNew<Const32Value>(proc, Origin(), 0));
403 CHECK(!compileAndRun<int>(proc));
404 CHECK(slot == 37 + amount);
407 void testStoreAddLoad8Index(int amount, B3::Opcode loadOpcode)
410 BasicBlock* root = proc.addBlock();
414 Value* slotPtr = root->appendNew<Value>(
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>(
426 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
427 root->appendNew<Value>(
428 proc, Trunc, Origin(),
429 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
431 root->appendNewControlValue(
432 proc, Return, Origin(),
433 root->appendNew<Const32Value>(proc, Origin(), 0));
435 CHECK(!compileAndRun<int>(proc, amount));
436 CHECK(slot == 37 + amount);
439 void testStoreAddLoadImm8Index(int amount, B3::Opcode loadOpcode)
442 BasicBlock* root = proc.addBlock();
446 Value* slotPtr = root->appendNew<Value>(
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>(
458 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
459 root->appendNew<Const32Value>(proc, Origin(), amount)),
461 root->appendNewControlValue(
462 proc, Return, Origin(),
463 root->appendNew<Const32Value>(proc, Origin(), 0));
465 CHECK(!compileAndRun<int>(proc));
466 CHECK(slot == 37 + amount);
469 void testStoreAddLoad16Index(int amount, B3::Opcode loadOpcode)
472 BasicBlock* root = proc.addBlock();
474 int16_t* ptr = &slot;
476 Value* slotPtr = root->appendNew<Value>(
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>(
488 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
489 root->appendNew<Value>(
490 proc, Trunc, Origin(),
491 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
493 root->appendNewControlValue(
494 proc, Return, Origin(),
495 root->appendNew<Const32Value>(proc, Origin(), 0));
497 CHECK(!compileAndRun<int>(proc, amount));
498 CHECK(slot == 37 + amount);
501 void testStoreAddLoadImm16Index(int amount, B3::Opcode loadOpcode)
504 BasicBlock* root = proc.addBlock();
506 int16_t* ptr = &slot;
508 Value* slotPtr = root->appendNew<Value>(
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>(
520 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
521 root->appendNew<Const32Value>(proc, Origin(), amount)),
523 root->appendNewControlValue(
524 proc, Return, Origin(),
525 root->appendNew<Const32Value>(proc, Origin(), 0));
527 CHECK(!compileAndRun<int>(proc));
528 CHECK(slot == 37 + amount);
531 void testStoreAddLoad64Index(int amount)
534 BasicBlock* root = proc.addBlock();
535 int64_t slot = 37000000000ll;
536 int64_t* ptr = &slot;
538 Value* slotPtr = root->appendNew<Value>(
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>(
550 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
551 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
553 root->appendNewControlValue(
554 proc, Return, Origin(),
555 root->appendNew<Const32Value>(proc, Origin(), 0));
557 CHECK(!compileAndRun<int>(proc, amount));
558 CHECK(slot == 37000000000ll + amount);
561 void testStoreAddLoadImm64Index(int64_t amount)
564 BasicBlock* root = proc.addBlock();
565 int64_t slot = 370000000000ll;
566 int64_t* ptr = &slot;
568 Value* slotPtr = root->appendNew<Value>(
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>(
580 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
581 root->appendNew<Const64Value>(proc, Origin(), amount)),
583 root->appendNewControlValue(
584 proc, Return, Origin(),
585 root->appendNew<Const32Value>(proc, Origin(), 0));
587 CHECK(!compileAndRun<int>(proc));
588 CHECK(slot == 370000000000ll + amount);
591 void testStoreSubLoad(int amount)
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>(
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))),
607 root->appendNewControlValue(
608 proc, Return, Origin(),
609 root->appendNew<Const32Value>(proc, Origin(), 0));
611 CHECK(!compileAndRun<int>(proc, amount));
612 CHECK(slot == startValue - amount);
615 void testStoreAddLoadInterference(int amount)
618 BasicBlock* root = proc.addBlock();
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),
628 root->appendNew<MemoryValue>(
629 proc, Store, Origin(),
630 root->appendNew<Value>(
632 load, root->appendNew<Const32Value>(proc, Origin(), amount)),
634 root->appendNewControlValue(
635 proc, Return, Origin(),
636 root->appendNew<Const32Value>(proc, Origin(), 0));
638 CHECK(!compileAndRun<int>(proc, &slot));
639 CHECK(slot == 37 + amount);
642 void testStoreAddAndLoad(int amount, int mask)
645 BasicBlock* root = proc.addBlock();
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>(
654 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
655 root->appendNew<Const32Value>(proc, Origin(), amount)),
656 root->appendNew<Const32Value>(proc, Origin(), mask)),
658 root->appendNewControlValue(
659 proc, Return, Origin(),
660 root->appendNew<Const32Value>(proc, Origin(), 0));
662 CHECK(!compileAndRun<int>(proc));
663 CHECK(slot == ((37 + amount) & mask));
666 void testStoreNegLoad32(int32_t value)
669 BasicBlock* root = proc.addBlock();
671 int32_t slot = value;
673 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
675 root->appendNew<MemoryValue>(
676 proc, Store, Origin(),
677 root->appendNew<Value>(
679 root->appendNew<Const32Value>(proc, Origin(), 0),
680 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)),
683 root->appendNewControlValue(
684 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
686 CHECK(!compileAndRun<int32_t>(proc));
687 CHECK(slot == -value);
690 void testStoreNegLoadPtr(intptr_t value)
693 BasicBlock* root = proc.addBlock();
695 intptr_t slot = value;
697 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
699 root->appendNew<MemoryValue>(
700 proc, Store, Origin(),
701 root->appendNew<Value>(
703 root->appendNew<ConstPtrValue>(proc, Origin(), 0),
704 root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)),
707 root->appendNewControlValue(
708 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
710 CHECK(!compileAndRun<int32_t>(proc));
711 CHECK(slot == -value);
714 void testAdd1Uncommuted(int value)
717 BasicBlock* root = proc.addBlock();
718 root->appendNewControlValue(
719 proc, Return, Origin(),
720 root->appendNew<Value>(
722 root->appendNew<Const32Value>(proc, Origin(), 1),
723 root->appendNew<Value>(
724 proc, Trunc, Origin(),
725 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
727 CHECK(compileAndRun<int>(proc, value) == value + 1);
730 void testLoadOffset()
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>(
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)))));
743 CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
746 void testLoadOffsetNotConstant()
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>(
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)))));
759 CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
762 void testLoadOffsetUsingAdd()
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>(
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)))))));
783 CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
786 void testLoadOffsetUsingAddInterference()
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));
814 CHECK(compileAndRun<int>(proc, &array[0]) == 1 + 2);
815 CHECK(array[0] == 666);
816 CHECK(array[1] == 666);
819 void testLoadOffsetUsingAddNotConstant()
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>(
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)))))));
840 CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
843 void testLoadAddrShift(unsigned shift)
846 BasicBlock* root = proc.addBlock();
849 // Figure out which slot to use while having proper alignment for the shift.
852 for (unsigned i = sizeof(slots)/sizeof(slots[0]); i--;) {
854 arg = bitwise_cast<uintptr_t>(slot) >> shift;
855 if (bitwise_cast<int*>(arg << shift) == slot)
861 root->appendNewControlValue(
862 proc, Return, Origin(),
863 root->appendNew<MemoryValue>(
864 proc, Load, Int32, Origin(),
865 root->appendNew<Value>(
867 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
868 root->appendNew<Const32Value>(proc, Origin(), shift))));
870 CHECK(compileAndRun<int>(proc, arg) == 8675309);
873 void testFramePointer()
876 BasicBlock* root = proc.addBlock();
877 root->appendNewControlValue(
878 proc, Return, Origin(),
879 root->appendNew<Value>(proc, FramePointer, Origin()));
881 void* fp = compileAndRun<void*>(proc);
883 CHECK(fp >= bitwise_cast<char*>(&proc) - 10000);
886 void testOverrideFramePointer()
890 BasicBlock* root = proc.addBlock();
892 // Add a stack slot to make the frame non trivial.
893 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8));
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);
900 root->appendNewControlValue(proc, Return, Origin(), result);
901 CHECK(compileAndRun<int64_t>(proc, 1));
905 BasicBlock* root = proc.addBlock();
907 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8));
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);
916 root->appendNewControlValue(proc, Return, Origin(), result);
917 CHECK(compileAndRun<int64_t>(proc, 1, 2));
924 BasicBlock* root = proc.addBlock();
925 root->appendNewControlValue(
926 proc, Return, Origin(),
927 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(1)));
929 void* stackSlot = compileAndRun<void*>(proc);
930 CHECK(stackSlot < &proc);
931 CHECK(stackSlot >= bitwise_cast<char*>(&proc) - 10000);
934 void testLoadFromFramePointer()
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())));
944 void* fp = compileAndRun<void*>(proc);
945 void* myFP = __builtin_frame_address(0);
947 CHECK(fp >= bitwise_cast<char*>(myFP) - 10000);
950 void testStoreLoadStackSlot(int value)
953 BasicBlock* root = proc.addBlock();
955 SlotBaseValue* stack =
956 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(sizeof(int)));
958 root->appendNew<MemoryValue>(
959 proc, Store, Origin(),
960 root->appendNew<Value>(
961 proc, Trunc, Origin(),
962 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
965 root->appendNewControlValue(
966 proc, Return, Origin(),
967 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), stack));
969 CHECK(compileAndRun<int>(proc, value) == value);
972 void testStoreFloat(double input)
974 // Simple store from an address in a register.
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);
981 Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
982 root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
984 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
987 CHECK(!compileAndRun<int64_t>(proc, input, &output));
988 CHECK(isIdentical(static_cast<float>(input), output));
991 // Simple indexed store.
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);
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(),
1003 root->appendNew<Const32Value>(proc, Origin(), 2));
1004 Value* destinationAddress = root->appendNew<Value>(proc, Add, Origin(), scaledIndex, destinationBaseAddress);
1006 root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
1008 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1011 CHECK(!compileAndRun<int64_t>(proc, input, &output - 1, 1));
1012 CHECK(isIdentical(static_cast<float>(input), output));
1016 void testStoreDoubleConstantAsFloat(double input)
1018 // Simple store from an address in a register.
1020 BasicBlock* root = proc.addBlock();
1021 Value* value = root->appendNew<ConstDoubleValue>(proc, Origin(), input);
1022 Value* valueAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), value);
1024 Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1026 root->appendNew<MemoryValue>(proc, Store, Origin(), valueAsFloat, destinationAddress);
1028 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1031 CHECK(!compileAndRun<int64_t>(proc, input, &output));
1032 CHECK(isIdentical(static_cast<float>(input), output));
1038 BasicBlock* root = proc.addBlock();
1040 Vector<Value*> sources;
1041 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1042 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1044 for (unsigned i = 0; i < 30; ++i) {
1046 root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
1050 Value* total = root->appendNew<Const64Value>(proc, Origin(), 0);
1051 for (Value* value : sources)
1052 total = root->appendNew<Value>(proc, Add, Origin(), total, value);
1054 root->appendNewControlValue(proc, Return, Origin(), total);
1055 compileAndRun<int>(proc, 1, 2);
1061 BasicBlock* root = proc.addBlock();
1063 Vector<Value*> sources;
1064 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
1065 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
1067 for (unsigned i = 0; i < 30; ++i) {
1069 root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
1073 Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
1074 for (Value* value : sources)
1075 total = root->appendNew<Value>(proc, Add, Origin(), total, value);
1077 root->appendNewControlValue(proc, Return, Origin(), total);
1078 compileAndRun<double>(proc, 1.1, 2.5);
1081 void testInt32ToDoublePartialRegisterStall()
1084 BasicBlock* root = proc.addBlock();
1085 BasicBlock* loop = proc.addBlock();
1086 BasicBlock* done = proc.addBlock();
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));
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);
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);
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(),
1113 FrequentedBlock(loop), FrequentedBlock(done));
1116 done->appendNewControlValue(proc, Return, Origin(), updatedTotal);
1117 CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
1120 void testInt32ToDoublePartialRegisterWithoutStall()
1123 BasicBlock* root = proc.addBlock();
1124 BasicBlock* loop = proc.addBlock();
1125 BasicBlock* done = proc.addBlock();
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));
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);
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);
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);
1164 UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
1165 updatedTotalUpsilon->setPhi(loopTotal);
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(),
1173 FrequentedBlock(loop), FrequentedBlock(done));
1176 done->appendNewControlValue(proc, Return, Origin(), updatedTotal);
1177 CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
1183 BasicBlock* root = proc.addBlock();
1184 BasicBlock* thenCase = proc.addBlock();
1185 BasicBlock* elseCase = proc.addBlock();
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));
1194 thenCase->appendNewControlValue(
1195 proc, Return, Origin(),
1196 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1198 elseCase->appendNewControlValue(
1199 proc, Return, Origin(),
1200 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1202 auto code = compileProc(proc);
1203 CHECK(invoke<int>(*code, 42) == 1);
1204 CHECK(invoke<int>(*code, 0) == 0);
1207 void testBranchPtr()
1210 BasicBlock* root = proc.addBlock();
1211 BasicBlock* thenCase = proc.addBlock();
1212 BasicBlock* elseCase = proc.addBlock();
1214 root->appendNewControlValue(
1215 proc, Branch, Origin(),
1216 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1217 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1219 thenCase->appendNewControlValue(
1220 proc, Return, Origin(),
1221 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1223 elseCase->appendNewControlValue(
1224 proc, Return, Origin(),
1225 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
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);
1235 BasicBlock* root = proc.addBlock();
1236 BasicBlock* thenCase = proc.addBlock();
1237 BasicBlock* elseCase = proc.addBlock();
1238 BasicBlock* done = proc.addBlock();
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));
1247 UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
1248 proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1249 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1251 UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
1252 proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1253 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
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);
1260 auto code = compileProc(proc);
1261 CHECK(invoke<int>(*code, 42) == 1);
1262 CHECK(invoke<int>(*code, 0) == 0);
1265 void testBranchNotEqual()
1268 BasicBlock* root = proc.addBlock();
1269 BasicBlock* thenCase = proc.addBlock();
1270 BasicBlock* elseCase = proc.addBlock();
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));
1282 thenCase->appendNewControlValue(
1283 proc, Return, Origin(),
1284 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1286 elseCase->appendNewControlValue(
1287 proc, Return, Origin(),
1288 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1290 auto code = compileProc(proc);
1291 CHECK(invoke<int>(*code, 42) == 1);
1292 CHECK(invoke<int>(*code, 0) == 0);
1295 void testBranchNotEqualCommute()
1298 BasicBlock* root = proc.addBlock();
1299 BasicBlock* thenCase = proc.addBlock();
1300 BasicBlock* elseCase = proc.addBlock();
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));
1312 thenCase->appendNewControlValue(
1313 proc, Return, Origin(),
1314 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1316 elseCase->appendNewControlValue(
1317 proc, Return, Origin(),
1318 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1320 auto code = compileProc(proc);
1321 CHECK(invoke<int>(*code, 42) == 1);
1322 CHECK(invoke<int>(*code, 0) == 0);
1325 void testBranchNotEqualNotEqual()
1328 BasicBlock* root = proc.addBlock();
1329 BasicBlock* thenCase = proc.addBlock();
1330 BasicBlock* elseCase = proc.addBlock();
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));
1345 thenCase->appendNewControlValue(
1346 proc, Return, Origin(),
1347 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1349 elseCase->appendNewControlValue(
1350 proc, Return, Origin(),
1351 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1353 auto code = compileProc(proc);
1354 CHECK(invoke<int>(*code, 42) == 1);
1355 CHECK(invoke<int>(*code, 0) == 0);
1358 void testBranchEqual()
1361 BasicBlock* root = proc.addBlock();
1362 BasicBlock* thenCase = proc.addBlock();
1363 BasicBlock* elseCase = proc.addBlock();
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));
1375 thenCase->appendNewControlValue(
1376 proc, Return, Origin(),
1377 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1379 elseCase->appendNewControlValue(
1380 proc, Return, Origin(),
1381 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1383 auto code = compileProc(proc);
1384 CHECK(invoke<int>(*code, 42) == 1);
1385 CHECK(invoke<int>(*code, 0) == 0);
1388 void testBranchEqualEqual()
1391 BasicBlock* root = proc.addBlock();
1392 BasicBlock* thenCase = proc.addBlock();
1393 BasicBlock* elseCase = proc.addBlock();
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));
1408 thenCase->appendNewControlValue(
1409 proc, Return, Origin(),
1410 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1412 elseCase->appendNewControlValue(
1413 proc, Return, Origin(),
1414 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1416 auto code = compileProc(proc);
1417 CHECK(invoke<int>(*code, 42) == 1);
1418 CHECK(invoke<int>(*code, 0) == 0);
1421 void testBranchEqualCommute()
1424 BasicBlock* root = proc.addBlock();
1425 BasicBlock* thenCase = proc.addBlock();
1426 BasicBlock* elseCase = proc.addBlock();
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));
1438 thenCase->appendNewControlValue(
1439 proc, Return, Origin(),
1440 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1442 elseCase->appendNewControlValue(
1443 proc, Return, Origin(),
1444 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1446 auto code = compileProc(proc);
1447 CHECK(invoke<int>(*code, 42) == 1);
1448 CHECK(invoke<int>(*code, 0) == 0);
1451 void testBranchEqualEqual1()
1454 BasicBlock* root = proc.addBlock();
1455 BasicBlock* thenCase = proc.addBlock();
1456 BasicBlock* elseCase = proc.addBlock();
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));
1471 thenCase->appendNewControlValue(
1472 proc, Return, Origin(),
1473 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
1475 elseCase->appendNewControlValue(
1476 proc, Return, Origin(),
1477 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
1479 auto code = compileProc(proc);
1480 CHECK(invoke<int>(*code, 42) == 1);
1481 CHECK(invoke<int>(*code, 0) == 0);
1484 void testBranchEqualOrUnorderedArgs(double a, double b)
1487 BasicBlock* root = proc.addBlock();
1488 BasicBlock* thenCase = proc.addBlock();
1489 BasicBlock* elseCase = proc.addBlock();
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(),
1499 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1501 thenCase->appendNewControlValue(
1502 proc, Return, Origin(),
1503 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1505 elseCase->appendNewControlValue(
1506 proc, Return, Origin(),
1507 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1509 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1510 CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
1513 void testBranchEqualOrUnorderedArgs(float a, float b)
1516 BasicBlock* root = proc.addBlock();
1517 BasicBlock* thenCase = proc.addBlock();
1518 BasicBlock* elseCase = proc.addBlock();
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));
1525 root->appendNewControlValue(
1526 proc, Branch, Origin(),
1527 root->appendNew<Value>(
1528 proc, EqualOrUnordered, Origin(),
1531 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1533 thenCase->appendNewControlValue(
1534 proc, Return, Origin(),
1535 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1537 elseCase->appendNewControlValue(
1538 proc, Return, Origin(),
1539 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1541 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1542 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1545 void testBranchNotEqualAndOrderedArgs(double a, double b)
1548 BasicBlock* root = proc.addBlock();
1549 BasicBlock* thenCase = proc.addBlock();
1550 BasicBlock* elseCase = proc.addBlock();
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(),
1558 Value* notEqualAndOrdered = root->appendNew<Value>(
1559 proc, Equal, Origin(),
1560 root->appendNew<Const32Value>(proc, Origin(), 0),
1562 root->appendNewControlValue(
1563 proc, Branch, Origin(),
1565 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1567 thenCase->appendNewControlValue(
1568 proc, Return, Origin(),
1569 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1571 elseCase->appendNewControlValue(
1572 proc, Return, Origin(),
1573 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1575 int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
1576 CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
1579 void testBranchNotEqualAndOrderedArgs(float a, float b)
1582 BasicBlock* root = proc.addBlock();
1583 BasicBlock* thenCase = proc.addBlock();
1584 BasicBlock* elseCase = proc.addBlock();
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(),
1594 Value* notEqualAndOrdered = root->appendNew<Value>(
1595 proc, Equal, Origin(),
1596 root->appendNew<Const32Value>(proc, Origin(), 0),
1598 root->appendNewControlValue(
1599 proc, Branch, Origin(),
1601 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1603 thenCase->appendNewControlValue(
1604 proc, Return, Origin(),
1605 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1607 elseCase->appendNewControlValue(
1608 proc, Return, Origin(),
1609 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1611 int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
1612 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1615 void testBranchEqualOrUnorderedDoubleArgImm(double a, double b)
1618 BasicBlock* root = proc.addBlock();
1619 BasicBlock* thenCase = proc.addBlock();
1620 BasicBlock* elseCase = proc.addBlock();
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(),
1630 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1632 thenCase->appendNewControlValue(
1633 proc, Return, Origin(),
1634 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1636 elseCase->appendNewControlValue(
1637 proc, Return, Origin(),
1638 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1640 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1641 CHECK(compileAndRun<int64_t>(proc, a) == expected);
1644 void testBranchEqualOrUnorderedFloatArgImm(float a, float b)
1647 BasicBlock* root = proc.addBlock();
1648 BasicBlock* thenCase = proc.addBlock();
1649 BasicBlock* elseCase = proc.addBlock();
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);
1655 root->appendNewControlValue(
1656 proc, Branch, Origin(),
1657 root->appendNew<Value>(
1658 proc, EqualOrUnordered, Origin(),
1661 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1663 thenCase->appendNewControlValue(
1664 proc, Return, Origin(),
1665 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1667 elseCase->appendNewControlValue(
1668 proc, Return, Origin(),
1669 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1671 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1672 CHECK(compileAndRun<int64_t>(proc, &a) == expected);
1675 void testBranchEqualOrUnorderedDoubleImms(double a, double b)
1678 BasicBlock* root = proc.addBlock();
1679 BasicBlock* thenCase = proc.addBlock();
1680 BasicBlock* elseCase = proc.addBlock();
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(),
1690 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1692 thenCase->appendNewControlValue(
1693 proc, Return, Origin(),
1694 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1696 elseCase->appendNewControlValue(
1697 proc, Return, Origin(),
1698 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1700 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1701 CHECK(compileAndRun<int64_t>(proc) == expected);
1704 void testBranchEqualOrUnorderedFloatImms(float a, float b)
1707 BasicBlock* root = proc.addBlock();
1708 BasicBlock* thenCase = proc.addBlock();
1709 BasicBlock* elseCase = proc.addBlock();
1711 Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1712 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1714 root->appendNewControlValue(
1715 proc, Branch, Origin(),
1716 root->appendNew<Value>(
1717 proc, EqualOrUnordered, Origin(),
1720 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1722 thenCase->appendNewControlValue(
1723 proc, Return, Origin(),
1724 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1726 elseCase->appendNewControlValue(
1727 proc, Return, Origin(),
1728 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1730 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1731 CHECK(compileAndRun<int64_t>(proc) == expected);
1734 void testBranchEqualOrUnorderedFloatWithUselessDoubleConversion(float a, float b)
1737 BasicBlock* root = proc.addBlock();
1738 BasicBlock* thenCase = proc.addBlock();
1739 BasicBlock* elseCase = proc.addBlock();
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);
1748 root->appendNewControlValue(
1749 proc, Branch, Origin(),
1750 root->appendNew<Value>(
1751 proc, EqualOrUnordered, Origin(),
1754 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1756 thenCase->appendNewControlValue(
1757 proc, Return, Origin(),
1758 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
1760 elseCase->appendNewControlValue(
1761 proc, Return, Origin(),
1762 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
1764 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
1765 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
1768 void testBranchFold(int value)
1771 BasicBlock* root = proc.addBlock();
1772 BasicBlock* thenCase = proc.addBlock();
1773 BasicBlock* elseCase = proc.addBlock();
1775 root->appendNewControlValue(
1776 proc, Branch, Origin(),
1777 root->appendNew<Const32Value>(proc, Origin(), value),
1778 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1780 thenCase->appendNewControlValue(
1781 proc, Return, Origin(),
1782 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1784 elseCase->appendNewControlValue(
1785 proc, Return, Origin(),
1786 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1788 CHECK(compileAndRun<int>(proc) == !!value);
1791 void testDiamondFold(int value)
1794 BasicBlock* root = proc.addBlock();
1795 BasicBlock* thenCase = proc.addBlock();
1796 BasicBlock* elseCase = proc.addBlock();
1797 BasicBlock* done = proc.addBlock();
1799 root->appendNewControlValue(
1800 proc, Branch, Origin(),
1801 root->appendNew<Const32Value>(proc, Origin(), value),
1802 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
1804 UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
1805 proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1806 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
1808 UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
1809 proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1810 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
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);
1817 CHECK(compileAndRun<int>(proc) == !!value);
1820 void testBranchNotEqualFoldPtr(intptr_t value)
1823 BasicBlock* root = proc.addBlock();
1824 BasicBlock* thenCase = proc.addBlock();
1825 BasicBlock* elseCase = proc.addBlock();
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));
1835 thenCase->appendNewControlValue(
1836 proc, Return, Origin(),
1837 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1839 elseCase->appendNewControlValue(
1840 proc, Return, Origin(),
1841 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1843 CHECK(compileAndRun<int>(proc) == !!value);
1846 void testBranchEqualFoldPtr(intptr_t value)
1849 BasicBlock* root = proc.addBlock();
1850 BasicBlock* thenCase = proc.addBlock();
1851 BasicBlock* elseCase = proc.addBlock();
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));
1861 thenCase->appendNewControlValue(
1862 proc, Return, Origin(),
1863 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1865 elseCase->appendNewControlValue(
1866 proc, Return, Origin(),
1867 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1869 CHECK(compileAndRun<int>(proc) == !value);
1872 void testBranchLoadPtr()
1875 BasicBlock* root = proc.addBlock();
1876 BasicBlock* thenCase = proc.addBlock();
1877 BasicBlock* elseCase = proc.addBlock();
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));
1886 thenCase->appendNewControlValue(
1887 proc, Return, Origin(),
1888 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1890 elseCase->appendNewControlValue(
1891 proc, Return, Origin(),
1892 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1894 auto code = compileProc(proc);
1897 CHECK(invoke<int>(*code, &cond) == 1);
1899 CHECK(invoke<int>(*code, &cond) == 0);
1902 void testBranchLoad32()
1905 BasicBlock* root = proc.addBlock();
1906 BasicBlock* thenCase = proc.addBlock();
1907 BasicBlock* elseCase = proc.addBlock();
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));
1916 thenCase->appendNewControlValue(
1917 proc, Return, Origin(),
1918 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1920 elseCase->appendNewControlValue(
1921 proc, Return, Origin(),
1922 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1924 auto code = compileProc(proc);
1927 CHECK(invoke<int>(*code, &cond) == 1);
1929 CHECK(invoke<int>(*code, &cond) == 0);
1932 void testBranchLoad8S()
1935 BasicBlock* root = proc.addBlock();
1936 BasicBlock* thenCase = proc.addBlock();
1937 BasicBlock* elseCase = proc.addBlock();
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));
1946 thenCase->appendNewControlValue(
1947 proc, Return, Origin(),
1948 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1950 elseCase->appendNewControlValue(
1951 proc, Return, Origin(),
1952 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1954 auto code = compileProc(proc);
1957 CHECK(invoke<int>(*code, &cond) == 1);
1959 CHECK(invoke<int>(*code, &cond) == 0);
1962 void testBranchLoad8Z()
1965 BasicBlock* root = proc.addBlock();
1966 BasicBlock* thenCase = proc.addBlock();
1967 BasicBlock* elseCase = proc.addBlock();
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));
1976 thenCase->appendNewControlValue(
1977 proc, Return, Origin(),
1978 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
1980 elseCase->appendNewControlValue(
1981 proc, Return, Origin(),
1982 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
1984 auto code = compileProc(proc);
1987 CHECK(invoke<int>(*code, &cond) == 1);
1989 CHECK(invoke<int>(*code, &cond) == 0);
1992 void testBranchLoad16S()
1995 BasicBlock* root = proc.addBlock();
1996 BasicBlock* thenCase = proc.addBlock();
1997 BasicBlock* elseCase = proc.addBlock();
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));
2006 thenCase->appendNewControlValue(
2007 proc, Return, Origin(),
2008 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2010 elseCase->appendNewControlValue(
2011 proc, Return, Origin(),
2012 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2014 auto code = compileProc(proc);
2017 CHECK(invoke<int>(*code, &cond) == 1);
2019 CHECK(invoke<int>(*code, &cond) == 0);
2022 void testBranchLoad16Z()
2025 BasicBlock* root = proc.addBlock();
2026 BasicBlock* thenCase = proc.addBlock();
2027 BasicBlock* elseCase = proc.addBlock();
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));
2036 thenCase->appendNewControlValue(
2037 proc, Return, Origin(),
2038 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2040 elseCase->appendNewControlValue(
2041 proc, Return, Origin(),
2042 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2044 auto code = compileProc(proc);
2047 CHECK(invoke<int>(*code, &cond) == 1);
2049 CHECK(invoke<int>(*code, &cond) == 0);
2052 void testBranch8WithLoad8ZIndex()
2055 BasicBlock* root = proc.addBlock();
2056 BasicBlock* thenCase = proc.addBlock();
2057 BasicBlock* elseCase = proc.addBlock();
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));
2076 thenCase->appendNewControlValue(
2077 proc, Return, Origin(),
2078 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2080 elseCase->appendNewControlValue(
2081 proc, Return, Origin(),
2082 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2084 auto code = compileProc(proc);
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);
2092 void testComplex(unsigned numVars, unsigned numConstructs)
2094 MonotonicTime before = MonotonicTime::now();
2097 BasicBlock* current = proc.addBlock();
2099 Const32Value* one = current->appendNew<Const32Value>(proc, Origin(), 1);
2101 Vector<int32_t> varSlots;
2102 for (unsigned i = numVars; i--;)
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));
2111 for (unsigned i = 0; i < numConstructs; ++i) {
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;
2118 BasicBlock* thenBlock = proc.addBlock();
2119 BasicBlock* elseBlock = proc.addBlock();
2120 BasicBlock* continuation = proc.addBlock();
2122 current->appendNewControlValue(
2123 proc, Branch, Origin(), vars[predicateVarIndex],
2124 FrequentedBlock(thenBlock), FrequentedBlock(elseBlock));
2126 UpsilonValue* thenThenResult = thenBlock->appendNew<UpsilonValue>(
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));
2133 UpsilonValue* elseElseResult = elseBlock->appendNew<UpsilonValue>(
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));
2140 Value* thenPhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2141 thenThenResult->setPhi(thenPhi);
2142 elseThenResult->setPhi(thenPhi);
2143 vars[thenIncVarIndex] = thenPhi;
2145 Value* elsePhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2146 thenElseResult->setPhi(elsePhi);
2147 elseElseResult->setPhi(elsePhi);
2148 vars[elseIncVarIndex] = thenPhi;
2150 current = continuation;
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();
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));
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));
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(),
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(),
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));
2200 loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodyIndex, bodyIndex);
2201 loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodySum, bodySum);
2202 loopReentry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody));
2204 UpsilonValue* exitSum = loopExit->appendNew<UpsilonValue>(proc, Origin(), newBodySum);
2205 loopExit->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2207 UpsilonValue* skipSum = loopSkip->appendNew<UpsilonValue>(proc, Origin(), startSum);
2208 loopSkip->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
2210 Value* finalSum = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
2211 exitSum->setPhi(finalSum);
2212 skipSum->setPhi(finalSum);
2214 current = continuation;
2215 vars[((i >> 1) + 0) % numVars] = finalSum;
2219 current->appendNewControlValue(proc, Return, Origin(), vars[0]);
2223 MonotonicTime after = MonotonicTime::now();
2224 dataLog(toCString(" That took ", (after - before).milliseconds(), " ms.\n"));
2227 void testBranchBitTest32TmpImm(uint32_t value, uint32_t imm)
2230 BasicBlock* root = proc.addBlock();
2231 BasicBlock* thenCase = proc.addBlock();
2232 BasicBlock* elseCase = proc.addBlock();
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);
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),
2245 root->appendNewControlValue(
2246 proc, Branch, Origin(),
2248 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2250 thenCase->appendNewControlValue(
2251 proc, Return, Origin(),
2252 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2254 elseCase->appendNewControlValue(
2255 proc, Return, Origin(),
2256 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2258 auto code = compileProc(proc);
2259 CHECK_EQ(invoke<uint32_t>(*code, value), (value>>(imm%32))&1);
2262 void testBranchBitTest32AddrImm(uint32_t value, uint32_t imm)
2265 BasicBlock* root = proc.addBlock();
2266 BasicBlock* thenCase = proc.addBlock();
2267 BasicBlock* elseCase = proc.addBlock();
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);
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),
2280 root->appendNewControlValue(
2281 proc, Branch, Origin(),
2283 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2285 thenCase->appendNewControlValue(
2286 proc, Return, Origin(),
2287 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2289 elseCase->appendNewControlValue(
2290 proc, Return, Origin(),
2291 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2293 auto code = compileProc(proc);
2294 CHECK_EQ(invoke<uint32_t>(*code, &value), (value>>(imm%32))&1);
2297 void testBranchBitTest32TmpTmp(uint32_t value, uint32_t value2)
2300 BasicBlock* root = proc.addBlock();
2301 BasicBlock* thenCase = proc.addBlock();
2302 BasicBlock* elseCase = proc.addBlock();
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));
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),
2317 root->appendNewControlValue(
2318 proc, Branch, Origin(),
2320 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2322 thenCase->appendNewControlValue(
2323 proc, Return, Origin(),
2324 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
2326 elseCase->appendNewControlValue(
2327 proc, Return, Origin(),
2328 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
2330 auto code = compileProc(proc);
2331 CHECK_EQ(invoke<uint32_t>(*code, value, value2), (value>>(value2%32))&1);
2334 void testBranchBitTest64TmpTmp(uint64_t value, uint64_t value2)
2337 BasicBlock* root = proc.addBlock();
2338 BasicBlock* thenCase = proc.addBlock();
2339 BasicBlock* elseCase = proc.addBlock();
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));
2348 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2349 Value* bitTest = root->appendNew<Value>(
2350 proc, BitAnd, Origin(),
2352 root->appendNew<Value>(proc, Shl, Origin(), one, bitOffset));
2354 root->appendNewControlValue(
2355 proc, Branch, Origin(),
2357 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2359 thenCase->appendNewControlValue(
2360 proc, Return, Origin(),
2361 thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2363 elseCase->appendNewControlValue(
2364 proc, Return, Origin(),
2365 elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2367 auto code = compileProc(proc);
2368 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2371 void testBranchBitTest64AddrTmp(uint64_t value, uint64_t value2)
2374 BasicBlock* root = proc.addBlock();
2375 BasicBlock* thenCase = proc.addBlock();
2376 BasicBlock* elseCase = proc.addBlock();
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));
2385 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2386 Value* bitTest = root->appendNew<Value>(
2387 proc, BitAnd, Origin(),
2389 root->appendNew<Value>(proc, Shl, Origin(), one, bitOffset));
2391 root->appendNewControlValue(
2392 proc, Branch, Origin(),
2394 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2396 thenCase->appendNewControlValue(
2397 proc, Return, Origin(),
2398 thenCase->appendNew<Const64Value>(proc, Origin(), 1));
2400 elseCase->appendNewControlValue(
2401 proc, Return, Origin(),
2402 elseCase->appendNew<Const64Value>(proc, Origin(), 0));
2404 auto code = compileProc(proc);
2405 CHECK_EQ(invoke<uint64_t>(*code, &value, value2), (value>>(value2%64))&1);
2408 void testBranchBitTestNegation(uint64_t value, uint64_t value2)
2411 BasicBlock* root = proc.addBlock();
2412 BasicBlock* thenCase = proc.addBlock();
2413 BasicBlock* elseCase = proc.addBlock();
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);
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)),
2427 root->appendNewControlValue(
2428 proc, Branch, Origin(),
2430 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2432 thenCase->appendNewControlValue(
2433 proc, Return, Origin(),
2434 thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2436 elseCase->appendNewControlValue(
2437 proc, Return, Origin(),
2438 elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2440 auto code = compileProc(proc);
2441 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2444 void testBranchBitTestNegation2(uint64_t value, uint64_t value2)
2447 BasicBlock* root = proc.addBlock();
2448 BasicBlock* thenCase = proc.addBlock();
2449 BasicBlock* elseCase = proc.addBlock();
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);
2459 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1);
2460 Value* bitTest = root->appendNew<Value>(
2461 proc, BitAnd, Origin(),
2465 root->appendNewControlValue(
2466 proc, Branch, Origin(),
2468 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
2470 thenCase->appendNewControlValue(
2471 proc, Return, Origin(),
2472 thenCase->appendNew<Const64Value>(proc, Origin(), 0));
2474 elseCase->appendNewControlValue(
2475 proc, Return, Origin(),
2476 elseCase->appendNew<Const64Value>(proc, Origin(), 1));
2478 auto code = compileProc(proc);
2479 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1);
2482 void testSimplePatchpoint()
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());
2500 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2502 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2505 void testSimplePatchpointWithoutOuputClobbersGPArgs()
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);
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);
2530 Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
2531 root->appendNewControlValue(proc, Return, Origin(), result);
2533 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2536 void testSimplePatchpointWithOuputClobbersGPArgs()
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.
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.
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
2550 // https://bugs.webkit.org/show_bug.cgi?id=194633
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);
2559 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int64, Origin());
2561 RegisterSet clobberAll = RegisterSet::allGPRs();
2562 clobberAll.exclude(RegisterSet::stackRegisters());
2563 clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
2564 clobberAll.clear(GPRInfo::argumentGPR2);
2565 patchpoint->clobberLate(clobberAll);
2567 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2568 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
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());
2580 clobberAll.forEach([&] (Reg reg) {
2581 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), reg.gpr());
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);
2589 CHECK(compileAndRun<int>(proc, 1, 2) == 58);
2592 void testSimplePatchpointWithoutOuputClobbersFPArgs()
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);
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);
2617 Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
2618 root->appendNewControlValue(proc, Return, Origin(), result);
2620 CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 4);
2623 void testSimplePatchpointWithOuputClobbersFPArgs()
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
2630 // https://bugs.webkit.org/show_bug.cgi?id=194633
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);
2639 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin());
2641 RegisterSet clobberAll = RegisterSet::allFPRs();
2642 clobberAll.exclude(RegisterSet::stackRegisters());
2643 clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
2644 clobberAll.clear(FPRInfo::argumentFPR2);
2645 patchpoint->clobberLate(clobberAll);
2647 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
2648 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
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());
2659 clobberAll.forEach([&] (Reg reg) {
2660 jit.moveZeroToDouble(reg.fpr());
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);
2668 CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 59.6);
2671 void testPatchpointWithEarlyClobber()
2673 auto test = [] (GPRReg registerToClobber, bool arg1InArgGPR, bool arg2InArgGPR) {
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);
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) {
2687 CHECK((params[1].gpr() == GPRInfo::argumentGPR0) == arg1InArgGPR);
2688 CHECK((params[2].gpr() == GPRInfo::argumentGPR1) == arg2InArgGPR);
2691 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
2694 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2696 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2699 test(GPRInfo::nonArgGPR0, true, true);
2700 test(GPRInfo::argumentGPR0, false, true);
2701 test(GPRInfo::argumentGPR1, true, false);
2704 void testPatchpointCallArg()
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());
2721 CCallHelpers::Address(GPRInfo::callFrameRegister, params[1].offsetFromFP()),
2724 CCallHelpers::Address(GPRInfo::callFrameRegister, params[2].offsetFromFP()),
2727 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2729 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2732 void testPatchpointFixedRegister()
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());
2750 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2752 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2755 void testPatchpointAny(ValueRep rep)
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());
2774 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2776 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2779 void testPatchpointGPScratch()
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());
2810 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2812 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2815 void testPatchpointFPScratch()
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());
2840 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2842 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
2845 void testPatchpointLotsOfLateAnys()
2848 BasicBlock* root = proc.addBlock();
2850 for (unsigned i = 200; i--;)
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);
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());
2877 CHECK(params[i].isStack());
2878 jit.add32(CCallHelpers::Address(GPRInfo::callFrameRegister, params[i].offsetFromFP()), params[0].gpr());
2882 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2884 CHECK(static_cast<size_t>(compileAndRun<int>(proc)) == (things.size() * (things.size() - 1)) / 2);
2887 void testPatchpointAnyImm(ValueRep rep)
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);
2907 CCallHelpers::TrustedImm32(static_cast<int32_t>(params[2].value())),
2908 params[1].gpr(), params[0].gpr());
2910 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
2912 CHECK(compileAndRun<int>(proc, 1) == 43);
2915 #endif // ENABLE(B3_JIT)