1/*
2 * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#include "AirCode.h"
29#include "AirInstInlines.h"
30#include "AirValidate.h"
31#include "AllowMacroScratchRegisterUsage.h"
32#include "B3ArgumentRegValue.h"
33#include "B3AtomicValue.h"
34#include "B3BasicBlockInlines.h"
35#include "B3BreakCriticalEdges.h"
36#include "B3CCallValue.h"
37#include "B3Compilation.h"
38#include "B3Compile.h"
39#include "B3ComputeDivisionMagic.h"
40#include "B3Const32Value.h"
41#include "B3Const64Value.h"
42#include "B3ConstPtrValue.h"
43#include "B3Effects.h"
44#include "B3FenceValue.h"
45#include "B3FixSSA.h"
46#include "B3Generate.h"
47#include "B3LowerToAir.h"
48#include "B3MathExtras.h"
49#include "B3MemoryValue.h"
50#include "B3MoveConstants.h"
51#include "B3NativeTraits.h"
52#include "B3Procedure.h"
53#include "B3ReduceStrength.h"
54#include "B3SlotBaseValue.h"
55#include "B3StackSlot.h"
56#include "B3StackmapGenerationParams.h"
57#include "B3SwitchValue.h"
58#include "B3UpsilonValue.h"
59#include "B3UseCounts.h"
60#include "B3Validate.h"
61#include "B3ValueInlines.h"
62#include "B3VariableValue.h"
63#include "B3WasmAddressValue.h"
64#include "B3WasmBoundsCheckValue.h"
65#include "CCallHelpers.h"
66#include "FPRInfo.h"
67#include "GPRInfo.h"
68#include "InitializeThreading.h"
69#include "JSCInlines.h"
70#include "LinkBuffer.h"
71#include "PureNaN.h"
72#include <cmath>
73#include <string>
74#include <wtf/FastTLS.h>
75#include <wtf/IndexSet.h>
76#include <wtf/ListDump.h>
77#include <wtf/Lock.h>
78#include <wtf/NumberOfCores.h>
79#include <wtf/StdList.h>
80#include <wtf/Threading.h>
81#include <wtf/text/StringCommon.h>
82
83// We don't have a NO_RETURN_DUE_TO_EXIT, nor should we. That's ridiculous.
84static bool hiddenTruthBecauseNoReturnIsStupid() { return true; }
85
86static void usage()
87{
88 dataLog("Usage: testb3 [<filter>]\n");
89 if (hiddenTruthBecauseNoReturnIsStupid())
90 exit(1);
91}
92
93#if ENABLE(B3_JIT)
94
95using namespace JSC;
96using namespace JSC::B3;
97
98namespace {
99
100bool shouldBeVerbose()
101{
102 return shouldDumpIR(B3Mode);
103}
104
105Lock crashLock;
106
107// Nothing fancy for now; we just use the existing WTF assertion machinery.
108#define CHECK(x) do { \
109 if (!!(x)) \
110 break; \
111 crashLock.lock(); \
112 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #x); \
113 CRASH(); \
114 } while (false)
115
116#define CHECK_EQ(x, y) do { \
117 auto __x = (x); \
118 auto __y = (y); \
119 if (__x == __y) \
120 break; \
121 crashLock.lock(); \
122 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(#x " == " #y, " (" #x " == ", __x, ", " #y " == ", __y, ")").data()); \
123 CRASH(); \
124 } while (false)
125
126std::unique_ptr<Compilation> compileProc(Procedure& procedure, unsigned optLevel = Options::defaultB3OptLevel())
127{
128 procedure.setOptLevel(optLevel);
129 return std::make_unique<Compilation>(B3::compile(procedure));
130}
131
132template<typename T, typename... Arguments>
133T invoke(MacroAssemblerCodePtr<B3CompilationPtrTag> ptr, Arguments... arguments)
134{
135 void* executableAddress = untagCFunctionPtr<B3CompilationPtrTag>(ptr.executableAddress());
136 T (*function)(Arguments...) = bitwise_cast<T(*)(Arguments...)>(executableAddress);
137 return function(arguments...);
138}
139
140template<typename T, typename... Arguments>
141T invoke(const Compilation& code, Arguments... arguments)
142{
143 return invoke<T>(code.code(), arguments...);
144}
145
146template<typename T, typename... Arguments>
147T compileAndRun(Procedure& procedure, Arguments... arguments)
148{
149 return invoke<T>(*compileProc(procedure), arguments...);
150}
151
152void lowerToAirForTesting(Procedure& proc)
153{
154 proc.resetReachability();
155
156 if (shouldBeVerbose())
157 dataLog("B3 before lowering:\n", proc);
158
159 validate(proc);
160 lowerToAir(proc);
161
162 if (shouldBeVerbose())
163 dataLog("Air after lowering:\n", proc.code());
164
165 Air::validate(proc.code());
166}
167
168template<typename Func>
169void checkDisassembly(Compilation& compilation, const Func& func, const CString& failText)
170{
171 CString disassembly = compilation.disassembly();
172 if (func(disassembly.data()))
173 return;
174
175 crashLock.lock();
176 dataLog("Bad lowering! ", failText, "\n");
177 dataLog(disassembly);
178 CRASH();
179}
180
181void checkUsesInstruction(Compilation& compilation, const char* text)
182{
183 checkDisassembly(
184 compilation,
185 [&] (const char* disassembly) -> bool {
186 return strstr(disassembly, text);
187 },
188 toCString("Expected to find ", text, " but didnt!"));
189}
190
191void checkDoesNotUseInstruction(Compilation& compilation, const char* text)
192{
193 checkDisassembly(
194 compilation,
195 [&] (const char* disassembly) -> bool {
196 return !strstr(disassembly, text);
197 },
198 toCString("Did not expected to find ", text, " but it's there!"));
199}
200
201template<typename Type>
202struct Operand {
203 const char* name;
204 Type value;
205};
206
207typedef Operand<int64_t> Int64Operand;
208typedef Operand<int32_t> Int32Operand;
209
210template<typename FloatType>
211void populateWithInterestingValues(Vector<Operand<FloatType>>& operands)
212{
213 operands.append({ "0.", static_cast<FloatType>(0.) });
214 operands.append({ "-0.", static_cast<FloatType>(-0.) });
215 operands.append({ "0.4", static_cast<FloatType>(0.5) });
216 operands.append({ "-0.4", static_cast<FloatType>(-0.5) });
217 operands.append({ "0.5", static_cast<FloatType>(0.5) });
218 operands.append({ "-0.5", static_cast<FloatType>(-0.5) });
219 operands.append({ "0.6", static_cast<FloatType>(0.5) });
220 operands.append({ "-0.6", static_cast<FloatType>(-0.5) });
221 operands.append({ "1.", static_cast<FloatType>(1.) });
222 operands.append({ "-1.", static_cast<FloatType>(-1.) });
223 operands.append({ "2.", static_cast<FloatType>(2.) });
224 operands.append({ "-2.", static_cast<FloatType>(-2.) });
225 operands.append({ "M_PI", static_cast<FloatType>(M_PI) });
226 operands.append({ "-M_PI", static_cast<FloatType>(-M_PI) });
227 operands.append({ "min", std::numeric_limits<FloatType>::min() });
228 operands.append({ "max", std::numeric_limits<FloatType>::max() });
229 operands.append({ "lowest", std::numeric_limits<FloatType>::lowest() });
230 operands.append({ "epsilon", std::numeric_limits<FloatType>::epsilon() });
231 operands.append({ "infiniti", std::numeric_limits<FloatType>::infinity() });
232 operands.append({ "-infiniti", - std::numeric_limits<FloatType>::infinity() });
233 operands.append({ "PNaN", static_cast<FloatType>(PNaN) });
234}
235
236template<typename FloatType>
237Vector<Operand<FloatType>> floatingPointOperands()
238{
239 Vector<Operand<FloatType>> operands;
240 populateWithInterestingValues(operands);
241 return operands;
242};
243
244static Vector<Int64Operand> int64Operands()
245{
246 Vector<Int64Operand> operands;
247 operands.append({ "0", 0 });
248 operands.append({ "1", 1 });
249 operands.append({ "-1", -1 });
250 operands.append({ "42", 42 });
251 operands.append({ "-42", -42 });
252 operands.append({ "int64-max", std::numeric_limits<int64_t>::max() });
253 operands.append({ "int64-min", std::numeric_limits<int64_t>::min() });
254 operands.append({ "int32-max", std::numeric_limits<int32_t>::max() });
255 operands.append({ "int32-min", std::numeric_limits<int32_t>::min() });
256 operands.append({ "uint64-max", static_cast<int64_t>(std::numeric_limits<uint64_t>::max()) });
257 operands.append({ "uint64-min", static_cast<int64_t>(std::numeric_limits<uint64_t>::min()) });
258 operands.append({ "uint32-max", static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) });
259 operands.append({ "uint32-min", static_cast<int64_t>(std::numeric_limits<uint32_t>::min()) });
260
261 return operands;
262}
263
264static Vector<Int32Operand> int32Operands()
265{
266 Vector<Int32Operand> operands({
267 { "0", 0 },
268 { "1", 1 },
269 { "-1", -1 },
270 { "42", 42 },
271 { "-42", -42 },
272 { "int32-max", std::numeric_limits<int32_t>::max() },
273 { "int32-min", std::numeric_limits<int32_t>::min() },
274 { "uint32-max", static_cast<int32_t>(std::numeric_limits<uint32_t>::max()) },
275 { "uint32-min", static_cast<int32_t>(std::numeric_limits<uint32_t>::min()) }
276 });
277 return operands;
278}
279
280void add32(CCallHelpers& jit, GPRReg src1, GPRReg src2, GPRReg dest)
281{
282 if (src2 == dest)
283 jit.add32(src1, dest);
284 else {
285 jit.move(src1, dest);
286 jit.add32(src2, dest);
287 }
288}
289
290void test42()
291{
292 Procedure proc;
293 BasicBlock* root = proc.addBlock();
294 Value* const42 = root->appendNew<Const32Value>(proc, Origin(), 42);
295 root->appendNewControlValue(proc, Return, Origin(), const42);
296
297 CHECK(compileAndRun<int>(proc) == 42);
298}
299
300void testLoad42()
301{
302 Procedure proc;
303 BasicBlock* root = proc.addBlock();
304 int x = 42;
305 root->appendNewControlValue(
306 proc, Return, Origin(),
307 root->appendNew<MemoryValue>(
308 proc, Load, Int32, Origin(),
309 root->appendNew<ConstPtrValue>(proc, Origin(), &x)));
310
311 CHECK(compileAndRun<int>(proc) == 42);
312}
313
314void testLoadAcq42()
315{
316 Procedure proc;
317 BasicBlock* root = proc.addBlock();
318 int x = 42;
319 root->appendNewControlValue(
320 proc, Return, Origin(),
321 root->appendNew<MemoryValue>(
322 proc, Load, Int32, Origin(),
323 root->appendNew<ConstPtrValue>(proc, Origin(), &x),
324 0, HeapRange(42), HeapRange(42)));
325
326 auto code = compileProc(proc);
327 if (isARM64())
328 checkUsesInstruction(*code, "lda");
329 CHECK(invoke<int>(*code) == 42);
330}
331
332void testLoadWithOffsetImpl(int32_t offset64, int32_t offset32)
333{
334 {
335 Procedure proc;
336 BasicBlock* root = proc.addBlock();
337 int64_t x = -42;
338 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
339 root->appendNewControlValue(
340 proc, Return, Origin(),
341 root->appendNew<MemoryValue>(
342 proc, Load, Int64, Origin(),
343 base,
344 offset64));
345
346 char* address = reinterpret_cast<char*>(&x) - offset64;
347 CHECK(compileAndRun<int64_t>(proc, address) == -42);
348 }
349 {
350 Procedure proc;
351 BasicBlock* root = proc.addBlock();
352 int32_t x = -42;
353 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
354 root->appendNewControlValue(
355 proc, Return, Origin(),
356 root->appendNew<MemoryValue>(
357 proc, Load, Int32, Origin(),
358 base,
359 offset32));
360
361 char* address = reinterpret_cast<char*>(&x) - offset32;
362 CHECK(compileAndRun<int32_t>(proc, address) == -42);
363 }
364}
365
366void testLoadOffsetImm9Max()
367{
368 testLoadWithOffsetImpl(255, 255);
369}
370
371void testLoadOffsetImm9MaxPlusOne()
372{
373 testLoadWithOffsetImpl(256, 256);
374}
375
376void testLoadOffsetImm9MaxPlusTwo()
377{
378 testLoadWithOffsetImpl(257, 257);
379}
380
381void testLoadOffsetImm9Min()
382{
383 testLoadWithOffsetImpl(-256, -256);
384}
385
386void testLoadOffsetImm9MinMinusOne()
387{
388 testLoadWithOffsetImpl(-257, -257);
389}
390
391void testLoadOffsetScaledUnsignedImm12Max()
392{
393 testLoadWithOffsetImpl(32760, 16380);
394}
395
396void testLoadOffsetScaledUnsignedOverImm12Max()
397{
398 testLoadWithOffsetImpl(32760, 32760);
399 testLoadWithOffsetImpl(32761, 16381);
400 testLoadWithOffsetImpl(32768, 16384);
401}
402
403void testBitXorTreeArgs(int64_t a, int64_t b)
404{
405 Procedure proc;
406 BasicBlock* root = proc.addBlock();
407 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
408 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
409 Value* node = root->appendNew<Value>(proc, BitXor, Origin(), argA, argB);
410 node = root->appendNew<Value>(proc, BitXor, Origin(), node, argB);
411 node = root->appendNew<Value>(proc, BitXor, Origin(), node, argA);
412 node = root->appendNew<Value>(proc, BitXor, Origin(), node, argB);
413 root->appendNew<Value>(proc, Return, Origin(), node);
414
415 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (((a ^ b) ^ b) ^ a) ^ b);
416}
417
418void testBitXorTreeArgsEven(int64_t a, int64_t b)
419{
420 Procedure proc;
421 BasicBlock* root = proc.addBlock();
422 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
423 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
424 Value* node = root->appendNew<Value>(proc, BitXor, Origin(), argA, argB);
425 node = root->appendNew<Value>(proc, BitXor, Origin(), node, argB);
426 node = root->appendNew<Value>(proc, BitXor, Origin(), node, argA);
427 root->appendNew<Value>(proc, Return, Origin(), node);
428
429 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), ((a ^ b) ^ b) ^ a);
430}
431
432void testBitXorTreeArgImm(int64_t a, int64_t b)
433{
434 Procedure proc;
435 BasicBlock* root = proc.addBlock();
436 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
437 Value* immB = root->appendNew<Const64Value>(proc, Origin(), b);
438 Value* node = root->appendNew<Value>(proc, BitXor, Origin(), argA, immB);
439 node = root->appendNew<Value>(proc, BitXor, Origin(), argA, node);
440 node = root->appendNew<Value>(proc, BitXor, Origin(), argA, node);
441 node = root->appendNew<Value>(proc, BitXor, Origin(), immB, node);
442 root->appendNew<Value>(proc, Return, Origin(), node);
443
444 CHECK_EQ(compileAndRun<int64_t>(proc, a), b ^ (a ^ (a ^ (a ^ b))));
445}
446
447void testAddTreeArg32(int32_t a)
448{
449 Procedure proc;
450 BasicBlock* root = proc.addBlock();
451 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
452 argA = root->appendNew<Value>(proc, Trunc, Origin(), argA);
453 Value* node = argA;
454 int32_t expectedResult = a;
455 for (unsigned i = 0; i < 20; ++i) {
456 Value* otherNode;
457 if (!(i % 3)) {
458 otherNode = root->appendNew<Const32Value>(proc, Origin(), i);
459 expectedResult += i;
460 } else {
461 otherNode = argA;
462 expectedResult += a;
463 }
464 node = root->appendNew<Value>(proc, Add, Origin(), node, otherNode);
465 }
466 root->appendNew<Value>(proc, Return, Origin(), node);
467
468 CHECK_EQ(compileAndRun<int32_t>(proc, a), expectedResult);
469}
470
471void testMulTreeArg32(int32_t a)
472{
473 // Fibonacci-like expression tree with multiplication instead of addition.
474 // Verifies that we don't explode on heavily factored graphs.
475 Procedure proc;
476 BasicBlock* root = proc.addBlock();
477 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
478 argA = root->appendNew<Value>(proc, Trunc, Origin(), argA);
479 Value* nodeA = argA;
480 Value* nodeB = argA;
481 int32_t expectedA = a, expectedResult = a;
482 for (unsigned i = 0; i < 20; ++i) {
483 Value* newNodeB = root->appendNew<Value>(proc, Mul, Origin(), nodeA, nodeB);
484 nodeA = nodeB;
485 nodeB = newNodeB;
486 int32_t newExpectedResult = expectedA * expectedResult;
487 expectedA = expectedResult;
488 expectedResult = newExpectedResult;
489 }
490 root->appendNew<Value>(proc, Return, Origin(), nodeB);
491
492 CHECK_EQ(compileAndRun<int32_t>(proc, a), expectedResult);
493}
494
495void testBitAndTreeArg32(int32_t a)
496{
497 Procedure proc;
498 BasicBlock* root = proc.addBlock();
499 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
500 argA = root->appendNew<Value>(proc, Trunc, Origin(), argA);
501 Value* node = argA;
502 for (unsigned i = 0; i < 8; ++i) {
503 Value* constI = root->appendNew<Const32Value>(proc, Origin(), i | 42);
504 Value* newBitAnd = root->appendNew<Value>(proc, BitAnd, Origin(), argA, constI);
505 node = root->appendNew<Value>(proc, BitAnd, Origin(), node, newBitAnd);
506 }
507 root->appendNew<Value>(proc, Return, Origin(), node);
508
509 CHECK_EQ(compileAndRun<int32_t>(proc, a), a & 42);
510}
511
512void testBitOrTreeArg32(int32_t a)
513{
514 Procedure proc;
515 BasicBlock* root = proc.addBlock();
516 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
517 argA = root->appendNew<Value>(proc, Trunc, Origin(), argA);
518 Value* node = argA;
519 for (unsigned i = 0; i < 8; ++i) {
520 Value* constI = root->appendNew<Const32Value>(proc, Origin(), i);
521 Value* newBitAnd = root->appendNew<Value>(proc, BitOr, Origin(), argA, constI);
522 node = root->appendNew<Value>(proc, BitOr, Origin(), node, newBitAnd);
523 }
524 root->appendNew<Value>(proc, Return, Origin(), node);
525
526 CHECK_EQ(compileAndRun<int32_t>(proc, a), a | 7);
527}
528
529void testArg(int argument)
530{
531 Procedure proc;
532 BasicBlock* root = proc.addBlock();
533 root->appendNewControlValue(
534 proc, Return, Origin(),
535 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
536
537 CHECK(compileAndRun<int>(proc, argument) == argument);
538}
539
540void testReturnConst64(int64_t value)
541{
542 Procedure proc;
543 BasicBlock* root = proc.addBlock();
544 root->appendNewControlValue(
545 proc, Return, Origin(),
546 root->appendNew<Const64Value>(proc, Origin(), value));
547
548 CHECK(compileAndRun<int64_t>(proc) == value);
549}
550
551void testReturnVoid()
552{
553 Procedure proc;
554 BasicBlock* root = proc.addBlock();
555 root->appendNewControlValue(proc, Return, Origin());
556 compileAndRun<void>(proc);
557}
558
559void testAddArg(int a)
560{
561 Procedure proc;
562 BasicBlock* root = proc.addBlock();
563 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
564 root->appendNewControlValue(
565 proc, Return, Origin(),
566 root->appendNew<Value>(proc, Add, Origin(), value, value));
567
568 CHECK(compileAndRun<int>(proc, a) == a + a);
569}
570
571void testAddArgs(int a, int b)
572{
573 Procedure proc;
574 BasicBlock* root = proc.addBlock();
575 root->appendNewControlValue(
576 proc, Return, Origin(),
577 root->appendNew<Value>(
578 proc, Add, Origin(),
579 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
580 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
581
582 CHECK(compileAndRun<int>(proc, a, b) == a + b);
583}
584
585void testAddArgImm(int a, int b)
586{
587 Procedure proc;
588 BasicBlock* root = proc.addBlock();
589 root->appendNewControlValue(
590 proc, Return, Origin(),
591 root->appendNew<Value>(
592 proc, Add, Origin(),
593 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
594 root->appendNew<Const64Value>(proc, Origin(), b)));
595
596 CHECK(compileAndRun<int>(proc, a) == a + b);
597}
598
599void testAddImmArg(int a, int b)
600{
601 Procedure proc;
602 BasicBlock* root = proc.addBlock();
603 root->appendNewControlValue(
604 proc, Return, Origin(),
605 root->appendNew<Value>(
606 proc, Add, Origin(),
607 root->appendNew<Const64Value>(proc, Origin(), a),
608 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
609
610 CHECK(compileAndRun<int>(proc, b) == a + b);
611}
612
613void testAddArgMem(int64_t a, int64_t b)
614{
615 Procedure proc;
616 BasicBlock* root = proc.addBlock();
617 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
618 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
619 Value* result = root->appendNew<Value>(proc, Add, Origin(),
620 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
621 load);
622 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
623 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
624
625 int64_t inputOutput = b;
626 CHECK(!compileAndRun<int64_t>(proc, a, &inputOutput));
627 CHECK(inputOutput == a + b);
628}
629
630void testAddMemArg(int64_t a, int64_t b)
631{
632 Procedure proc;
633 BasicBlock* root = proc.addBlock();
634 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
635 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
636 Value* result = root->appendNew<Value>(proc, Add, Origin(),
637 load,
638 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
639 root->appendNewControlValue(proc, Return, Origin(), result);
640
641 CHECK(compileAndRun<int64_t>(proc, &a, b) == a + b);
642}
643
644void testAddImmMem(int64_t a, int64_t b)
645{
646 Procedure proc;
647 BasicBlock* root = proc.addBlock();
648 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
649 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
650 Value* result = root->appendNew<Value>(proc, Add, Origin(),
651 root->appendNew<Const64Value>(proc, Origin(), a),
652 load);
653 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
654 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
655
656 int64_t inputOutput = b;
657 CHECK(!compileAndRun<int>(proc, &inputOutput));
658 CHECK(inputOutput == a + b);
659}
660
661void testAddArg32(int a)
662{
663 Procedure proc;
664 BasicBlock* root = proc.addBlock();
665 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
666 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
667 root->appendNewControlValue(
668 proc, Return, Origin(),
669 root->appendNew<Value>(proc, Add, Origin(), value, value));
670
671 CHECK(compileAndRun<int>(proc, a) == a + a);
672}
673
674void testAddArgs32(int a, int b)
675{
676 Procedure proc;
677 BasicBlock* root = proc.addBlock();
678 root->appendNewControlValue(
679 proc, Return, Origin(),
680 root->appendNew<Value>(
681 proc, Add, Origin(),
682 root->appendNew<Value>(
683 proc, Trunc, Origin(),
684 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
685 root->appendNew<Value>(
686 proc, Trunc, Origin(),
687 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
688
689 CHECK(compileAndRun<int>(proc, a, b) == a + b);
690}
691
692void testAddArgMem32(int32_t a, int32_t b)
693{
694 Procedure proc;
695 BasicBlock* root = proc.addBlock();
696 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
697 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
698 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
699 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
700 Value* result = root->appendNew<Value>(proc, Add, Origin(), argument, load);
701 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
702 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
703
704 int32_t inputOutput = b;
705 CHECK(!compileAndRun<int32_t>(proc, a, &inputOutput));
706 CHECK(inputOutput == a + b);
707}
708
709void testAddMemArg32(int32_t a, int32_t b)
710{
711 Procedure proc;
712 BasicBlock* root = proc.addBlock();
713 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
714 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
715 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
716 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
717 Value* result = root->appendNew<Value>(proc, Add, Origin(), load, argument);
718 root->appendNewControlValue(proc, Return, Origin(), result);
719
720 CHECK(compileAndRun<int32_t>(proc, &a, b) == a + b);
721}
722
723void testAddImmMem32(int32_t a, int32_t b)
724{
725 Procedure proc;
726 BasicBlock* root = proc.addBlock();
727 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
728 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
729 Value* result = root->appendNew<Value>(proc, Add, Origin(),
730 root->appendNew<Const32Value>(proc, Origin(), a),
731 load);
732 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
733 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
734
735 int32_t inputOutput = b;
736 CHECK(!compileAndRun<int>(proc, &inputOutput));
737 CHECK(inputOutput == a + b);
738}
739
740void testAddNeg1(int a, int b)
741{
742 Procedure proc;
743 BasicBlock* root = proc.addBlock();
744 root->appendNewControlValue(
745 proc, Return, Origin(),
746 root->appendNew<Value>(
747 proc, Add, Origin(),
748 root->appendNew<Value>(proc, Neg, Origin(),
749 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
750 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
751
752 CHECK(compileAndRun<int>(proc, a, b) == (- a) + b);
753}
754
755void testAddNeg2(int a, int b)
756{
757 Procedure proc;
758 BasicBlock* root = proc.addBlock();
759 root->appendNewControlValue(
760 proc, Return, Origin(),
761 root->appendNew<Value>(
762 proc, Add, Origin(),
763 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
764 root->appendNew<Value>(proc, Neg, Origin(),
765 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
766
767 CHECK(compileAndRun<int>(proc, a, b) == a + (- b));
768}
769
770void testAddArgZeroImmZDef()
771{
772 Procedure proc;
773 BasicBlock* root = proc.addBlock();
774 Value* arg = root->appendNew<Value>(
775 proc, Trunc, Origin(),
776 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
777 Value* constZero = root->appendNew<Const32Value>(proc, Origin(), 0);
778 root->appendNewControlValue(
779 proc, Return, Origin(),
780 root->appendNew<Value>(
781 proc, Add, Origin(),
782 arg,
783 constZero));
784
785 auto code = compileProc(proc, 0);
786 CHECK(invoke<int64_t>(*code, 0x0123456789abcdef) == 0x89abcdef);
787}
788
789void testAddLoadTwice()
790{
791 auto test = [&] () {
792 Procedure proc;
793 BasicBlock* root = proc.addBlock();
794 int32_t value = 42;
795 Value* load = root->appendNew<MemoryValue>(
796 proc, Load, Int32, Origin(),
797 root->appendNew<ConstPtrValue>(proc, Origin(), &value));
798 root->appendNewControlValue(
799 proc, Return, Origin(),
800 root->appendNew<Value>(proc, Add, Origin(), load, load));
801
802 auto code = compileProc(proc);
803 CHECK(invoke<int32_t>(*code) == 42 * 2);
804 };
805
806 test();
807}
808
809void testAddArgDouble(double a)
810{
811 Procedure proc;
812 BasicBlock* root = proc.addBlock();
813 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
814 root->appendNewControlValue(
815 proc, Return, Origin(),
816 root->appendNew<Value>(proc, Add, Origin(), value, value));
817
818 CHECK(isIdentical(compileAndRun<double>(proc, a), a + a));
819}
820
821void testAddArgsDouble(double a, double b)
822{
823 Procedure proc;
824 BasicBlock* root = proc.addBlock();
825 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
826 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
827 root->appendNewControlValue(
828 proc, Return, Origin(),
829 root->appendNew<Value>(proc, Add, Origin(), valueA, valueB));
830
831 CHECK(isIdentical(compileAndRun<double>(proc, a, b), a + b));
832}
833
834void testAddArgImmDouble(double a, double b)
835{
836 Procedure proc;
837 BasicBlock* root = proc.addBlock();
838 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
839 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
840 root->appendNewControlValue(
841 proc, Return, Origin(),
842 root->appendNew<Value>(proc, Add, Origin(), valueA, valueB));
843
844 CHECK(isIdentical(compileAndRun<double>(proc, a), a + b));
845}
846
847void testAddImmArgDouble(double a, double b)
848{
849 Procedure proc;
850 BasicBlock* root = proc.addBlock();
851 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
852 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
853 root->appendNewControlValue(
854 proc, Return, Origin(),
855 root->appendNew<Value>(proc, Add, Origin(), valueA, valueB));
856
857 CHECK(isIdentical(compileAndRun<double>(proc, b), a + b));
858}
859
860void testAddImmsDouble(double a, double b)
861{
862 Procedure proc;
863 BasicBlock* root = proc.addBlock();
864 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
865 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
866 root->appendNewControlValue(
867 proc, Return, Origin(),
868 root->appendNew<Value>(proc, Add, Origin(), valueA, valueB));
869
870 CHECK(isIdentical(compileAndRun<double>(proc), a + b));
871}
872
873void testAddArgFloat(float a)
874{
875 Procedure proc;
876 BasicBlock* root = proc.addBlock();
877 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
878 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
879 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
880 Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue, floatValue);
881 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
882 root->appendNewControlValue(proc, Return, Origin(), result32);
883
884
885 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + a)));
886}
887
888void testAddArgsFloat(float a, float b)
889{
890 Procedure proc;
891 BasicBlock* root = proc.addBlock();
892 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
893 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
894 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
895 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
896 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
897 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
898 Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue1, floatValue2);
899 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
900 root->appendNewControlValue(proc, Return, Origin(), result32);
901
902 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b)));
903}
904
905void testAddFPRArgsFloat(float a, float b)
906{
907 Procedure proc;
908 BasicBlock* root = proc.addBlock();
909 Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
910 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
911 Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
912 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
913 Value* result = root->appendNew<Value>(proc, Add, Origin(), argument1, argument2);
914 root->appendNewControlValue(proc, Return, Origin(), result);
915
916 CHECK(isIdentical(compileAndRun<float>(proc, a, b), a + b));
917}
918
919void testAddArgImmFloat(float a, float b)
920{
921 Procedure proc;
922 BasicBlock* root = proc.addBlock();
923 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
924 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
925 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
926 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
927 Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue, constValue);
928 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
929 root->appendNewControlValue(proc, Return, Origin(), result32);
930
931 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + b)));
932}
933
934void testAddImmArgFloat(float a, float b)
935{
936 Procedure proc;
937 BasicBlock* root = proc.addBlock();
938 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
939 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
940 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
941 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
942 Value* result = root->appendNew<Value>(proc, Add, Origin(), constValue, floatValue);
943 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
944 root->appendNewControlValue(proc, Return, Origin(), result32);
945
946 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b)));
947}
948
949void testAddImmsFloat(float a, float b)
950{
951 Procedure proc;
952 BasicBlock* root = proc.addBlock();
953 Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
954 Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
955 Value* result = root->appendNew<Value>(proc, Add, Origin(), constValue1, constValue2);
956 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
957 root->appendNewControlValue(proc, Return, Origin(), result32);
958
959 CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a + b)));
960}
961
962void testAddArgFloatWithUselessDoubleConversion(float a)
963{
964 Procedure proc;
965 BasicBlock* root = proc.addBlock();
966 Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
967 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
968 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
969 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
970 Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble, asDouble);
971 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
972 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
973 root->appendNewControlValue(proc, Return, Origin(), result32);
974
975 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + a)));
976}
977
978void testAddArgsFloatWithUselessDoubleConversion(float a, float b)
979{
980 Procedure proc;
981 BasicBlock* root = proc.addBlock();
982 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
983 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
984 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
985 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
986 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
987 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
988 Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
989 Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
990 Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble1, asDouble2);
991 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
992 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
993 root->appendNewControlValue(proc, Return, Origin(), result32);
994
995 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b)));
996}
997
998void testAddArgsFloatWithEffectfulDoubleConversion(float a, float b)
999{
1000 Procedure proc;
1001 BasicBlock* root = proc.addBlock();
1002 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1003 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1004 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1005 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1006 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1007 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1008 Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1009 Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1010 Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble1, asDouble2);
1011 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1012 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1013 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
1014 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1015 root->appendNewControlValue(proc, Return, Origin(), result32);
1016
1017 double effect = 0;
1018 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a + b)));
1019 CHECK(isIdentical(effect, static_cast<double>(a) + static_cast<double>(b)));
1020}
1021
1022void testAddMulMulArgs(int64_t a, int64_t b, int64_t c)
1023{
1024 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
1025 // ((a * b) + (a * c))
1026 // ((a * b) + (c * a))
1027 // ((b * a) + (a * c))
1028 // ((b * a) + (c * a))
1029 for (int i = 0; i < 4; ++i) {
1030 Procedure proc;
1031 BasicBlock* root = proc.addBlock();
1032 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1033 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1034 Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1035 Value* mulAB = i & 2 ? root->appendNew<Value>(proc, Mul, Origin(), argA, argB)
1036 : root->appendNew<Value>(proc, Mul, Origin(), argB, argA);
1037 Value* mulAC = i & 1 ? root->appendNew<Value>(proc, Mul, Origin(), argA, argC)
1038 : root->appendNew<Value>(proc, Mul, Origin(), argC, argA);
1039 root->appendNew<Value>(proc, Return, Origin(),
1040 root->appendNew<Value>(proc, Add, Origin(),
1041 mulAB,
1042 mulAC));
1043
1044 CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a * b) + (a * c)));
1045 }
1046}
1047
1048void testMulArg(int a)
1049{
1050 Procedure proc;
1051 BasicBlock* root = proc.addBlock();
1052 Value* value = root->appendNew<Value>(
1053 proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1054 root->appendNewControlValue(
1055 proc, Return, Origin(),
1056 root->appendNew<Value>(proc, Mul, Origin(), value, value));
1057
1058 CHECK(compileAndRun<int>(proc, a) == a * a);
1059}
1060
1061void testMulArgStore(int a)
1062{
1063 Procedure proc;
1064 BasicBlock* root = proc.addBlock();
1065
1066 int mulSlot;
1067 int valueSlot;
1068
1069 Value* value = root->appendNew<Value>(
1070 proc, Trunc, Origin(),
1071 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1072 Value* mul = root->appendNew<Value>(proc, Mul, Origin(), value, value);
1073
1074 root->appendNew<MemoryValue>(
1075 proc, Store, Origin(), value,
1076 root->appendNew<ConstPtrValue>(proc, Origin(), &valueSlot), 0);
1077 root->appendNew<MemoryValue>(
1078 proc, Store, Origin(), mul,
1079 root->appendNew<ConstPtrValue>(proc, Origin(), &mulSlot), 0);
1080
1081 root->appendNewControlValue(
1082 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1083
1084 CHECK(!compileAndRun<int>(proc, a));
1085 CHECK(mulSlot == a * a);
1086 CHECK(valueSlot == a);
1087}
1088
1089void testMulAddArg(int a)
1090{
1091 Procedure proc;
1092 BasicBlock* root = proc.addBlock();
1093 Value* value = root->appendNew<Value>(
1094 proc, Trunc, Origin(),
1095 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1096 root->appendNewControlValue(
1097 proc, Return, Origin(),
1098 root->appendNew<Value>(
1099 proc, Add, Origin(),
1100 root->appendNew<Value>(proc, Mul, Origin(), value, value),
1101 value));
1102
1103 CHECK(compileAndRun<int>(proc, a) == a * a + a);
1104}
1105
1106void testMulArgs(int a, int b)
1107{
1108 Procedure proc;
1109 BasicBlock* root = proc.addBlock();
1110 root->appendNewControlValue(
1111 proc, Return, Origin(),
1112 root->appendNew<Value>(
1113 proc, Mul, Origin(),
1114 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1115 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
1116
1117 CHECK(compileAndRun<int>(proc, a, b) == a * b);
1118}
1119
1120void testMulArgNegArg(int a, int b)
1121{
1122 Procedure proc;
1123 BasicBlock* root = proc.addBlock();
1124 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1125 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1126 Value* negB = root->appendNew<Value>(proc, Neg, Origin(), argB);
1127 Value* result = root->appendNew<Value>(proc, Mul, Origin(), argA, negB);
1128 root->appendNew<Value>(proc, Return, Origin(), result);
1129
1130 CHECK(compileAndRun<int>(proc, a, b) == a * (-b));
1131}
1132
1133void testMulNegArgArg(int a, int b)
1134{
1135 Procedure proc;
1136 BasicBlock* root = proc.addBlock();
1137 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1138 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1139 Value* negA = root->appendNew<Value>(proc, Neg, Origin(), argA);
1140 Value* result = root->appendNew<Value>(proc, Mul, Origin(), negA, argB);
1141 root->appendNew<Value>(proc, Return, Origin(), result);
1142
1143 CHECK(compileAndRun<int>(proc, a, b) == (-a) * b);
1144}
1145
1146void testMulArgImm(int64_t a, int64_t b)
1147{
1148 Procedure proc;
1149 BasicBlock* root = proc.addBlock();
1150 root->appendNewControlValue(
1151 proc, Return, Origin(),
1152 root->appendNew<Value>(
1153 proc, Mul, Origin(),
1154 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1155 root->appendNew<Const64Value>(proc, Origin(), b)));
1156
1157 CHECK(compileAndRun<int64_t>(proc, a) == a * b);
1158}
1159
1160void testMulImmArg(int a, int b)
1161{
1162 Procedure proc;
1163 BasicBlock* root = proc.addBlock();
1164 root->appendNewControlValue(
1165 proc, Return, Origin(),
1166 root->appendNew<Value>(
1167 proc, Mul, Origin(),
1168 root->appendNew<Const64Value>(proc, Origin(), a),
1169 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1170
1171 CHECK(compileAndRun<int>(proc, b) == a * b);
1172}
1173
1174void testMulArgs32(int a, int b)
1175{
1176 Procedure proc;
1177 BasicBlock* root = proc.addBlock();
1178 root->appendNewControlValue(
1179 proc, Return, Origin(),
1180 root->appendNew<Value>(
1181 proc, Mul, Origin(),
1182 root->appendNew<Value>(
1183 proc, Trunc, Origin(),
1184 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1185 root->appendNew<Value>(
1186 proc, Trunc, Origin(),
1187 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1188
1189 CHECK(compileAndRun<int>(proc, a, b) == a * b);
1190}
1191
1192void testMulLoadTwice()
1193{
1194 auto test = [&] () {
1195 Procedure proc;
1196 BasicBlock* root = proc.addBlock();
1197 int32_t value = 42;
1198 Value* load = root->appendNew<MemoryValue>(
1199 proc, Load, Int32, Origin(),
1200 root->appendNew<ConstPtrValue>(proc, Origin(), &value));
1201 root->appendNewControlValue(
1202 proc, Return, Origin(),
1203 root->appendNew<Value>(proc, Mul, Origin(), load, load));
1204
1205 auto code = compileProc(proc);
1206 CHECK(invoke<int32_t>(*code) == 42 * 42);
1207 };
1208
1209 test();
1210}
1211
1212void testMulAddArgsLeft()
1213{
1214 Procedure proc;
1215 BasicBlock* root = proc.addBlock();
1216
1217 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1218 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1219 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1220 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1221 Value* added = root->appendNew<Value>(proc, Add, Origin(), multiplied, arg2);
1222 root->appendNewControlValue(proc, Return, Origin(), added);
1223
1224 auto code = compileProc(proc);
1225
1226 auto testValues = int64Operands();
1227 for (auto a : testValues) {
1228 for (auto b : testValues) {
1229 for (auto c : testValues) {
1230 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value);
1231 }
1232 }
1233 }
1234}
1235
1236void testMulAddArgsRight()
1237{
1238 Procedure proc;
1239 BasicBlock* root = proc.addBlock();
1240
1241 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1242 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1243 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1244 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1245 Value* added = root->appendNew<Value>(proc, Add, Origin(), arg0, multiplied);
1246 root->appendNewControlValue(proc, Return, Origin(), added);
1247
1248 auto code = compileProc(proc);
1249
1250 auto testValues = int64Operands();
1251 for (auto a : testValues) {
1252 for (auto b : testValues) {
1253 for (auto c : testValues) {
1254 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value);
1255 }
1256 }
1257 }
1258}
1259
1260void testMulAddArgsLeft32()
1261{
1262 Procedure proc;
1263 BasicBlock* root = proc.addBlock();
1264
1265 Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1266 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1267 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1268 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1269 Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1270 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1271 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1272 Value* added = root->appendNew<Value>(proc, Add, Origin(), multiplied, arg2);
1273 root->appendNewControlValue(proc, Return, Origin(), added);
1274
1275 auto code = compileProc(proc);
1276
1277 auto testValues = int32Operands();
1278 for (auto a : testValues) {
1279 for (auto b : testValues) {
1280 for (auto c : testValues) {
1281 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value);
1282 }
1283 }
1284 }
1285}
1286
1287void testMulAddArgsRight32()
1288{
1289 Procedure proc;
1290 BasicBlock* root = proc.addBlock();
1291
1292 Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1293 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1294 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1295 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1296 Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1297 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1298 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1299 Value* added = root->appendNew<Value>(proc, Add, Origin(), arg0, multiplied);
1300 root->appendNewControlValue(proc, Return, Origin(), added);
1301
1302 auto code = compileProc(proc);
1303
1304 auto testValues = int32Operands();
1305 for (auto a : testValues) {
1306 for (auto b : testValues) {
1307 for (auto c : testValues) {
1308 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value);
1309 }
1310 }
1311 }
1312}
1313
1314void testMulSubArgsLeft()
1315{
1316 Procedure proc;
1317 BasicBlock* root = proc.addBlock();
1318
1319 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1320 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1321 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1322 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1323 Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
1324 root->appendNewControlValue(proc, Return, Origin(), added);
1325
1326 auto code = compileProc(proc);
1327
1328 auto testValues = int64Operands();
1329 for (auto a : testValues) {
1330 for (auto b : testValues) {
1331 for (auto c : testValues) {
1332 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
1333 }
1334 }
1335 }
1336}
1337
1338void testMulSubArgsRight()
1339{
1340 Procedure proc;
1341 BasicBlock* root = proc.addBlock();
1342
1343 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1344 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1345 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1346 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1347 Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
1348 root->appendNewControlValue(proc, Return, Origin(), added);
1349
1350 auto code = compileProc(proc);
1351
1352 auto testValues = int64Operands();
1353 for (auto a : testValues) {
1354 for (auto b : testValues) {
1355 for (auto c : testValues) {
1356 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
1357 }
1358 }
1359 }
1360}
1361
1362void testMulSubArgsLeft32()
1363{
1364 Procedure proc;
1365 BasicBlock* root = proc.addBlock();
1366
1367 Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1368 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1369 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1370 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1371 Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1372 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1373 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1374 Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
1375 root->appendNewControlValue(proc, Return, Origin(), added);
1376
1377 auto code = compileProc(proc);
1378
1379 auto testValues = int32Operands();
1380 for (auto a : testValues) {
1381 for (auto b : testValues) {
1382 for (auto c : testValues) {
1383 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
1384 }
1385 }
1386 }
1387}
1388
1389void testMulSubArgsRight32()
1390{
1391 Procedure proc;
1392 BasicBlock* root = proc.addBlock();
1393
1394 Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1395 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1396 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1397 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1398 Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1399 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1400 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1401 Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
1402 root->appendNewControlValue(proc, Return, Origin(), added);
1403
1404 auto code = compileProc(proc);
1405
1406 auto testValues = int32Operands();
1407 for (auto a : testValues) {
1408 for (auto b : testValues) {
1409 for (auto c : testValues) {
1410 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
1411 }
1412 }
1413 }
1414}
1415
1416void testMulNegArgs()
1417{
1418 Procedure proc;
1419 BasicBlock* root = proc.addBlock();
1420
1421 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1422 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1423 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1424 Value* zero = root->appendNew<Const64Value>(proc, Origin(), 0);
1425 Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied);
1426 root->appendNewControlValue(proc, Return, Origin(), added);
1427
1428 auto code = compileProc(proc);
1429
1430 auto testValues = int64Operands();
1431 for (auto a : testValues) {
1432 for (auto b : testValues) {
1433 CHECK(invoke<int64_t>(*code, a.value, b.value) == -(a.value * b.value));
1434 }
1435 }
1436}
1437
1438void testMulNegArgs32()
1439{
1440 Procedure proc;
1441 BasicBlock* root = proc.addBlock();
1442
1443 Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1444 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1445 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1446 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1447 Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1448 Value* zero = root->appendNew<Const32Value>(proc, Origin(), 0);
1449 Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied);
1450 root->appendNewControlValue(proc, Return, Origin(), added);
1451
1452 auto code = compileProc(proc);
1453
1454 auto testValues = int32Operands();
1455 for (auto a : testValues) {
1456 for (auto b : testValues) {
1457 CHECK(invoke<int32_t>(*code, a.value, b.value) == -(a.value * b.value));
1458 }
1459 }
1460}
1461
1462void testMulArgDouble(double a)
1463{
1464 Procedure proc;
1465 BasicBlock* root = proc.addBlock();
1466 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1467 root->appendNewControlValue(
1468 proc, Return, Origin(),
1469 root->appendNew<Value>(proc, Mul, Origin(), value, value));
1470
1471 CHECK(isIdentical(compileAndRun<double>(proc, a), a * a));
1472}
1473
1474void testMulArgsDouble(double a, double b)
1475{
1476 Procedure proc;
1477 BasicBlock* root = proc.addBlock();
1478 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1479 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1480 root->appendNewControlValue(
1481 proc, Return, Origin(),
1482 root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1483
1484 CHECK(isIdentical(compileAndRun<double>(proc, a, b), a * b));
1485}
1486
1487void testMulArgImmDouble(double a, double b)
1488{
1489 Procedure proc;
1490 BasicBlock* root = proc.addBlock();
1491 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1492 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1493 root->appendNewControlValue(
1494 proc, Return, Origin(),
1495 root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1496
1497 CHECK(isIdentical(compileAndRun<double>(proc, a), a * b));
1498}
1499
1500void testMulImmArgDouble(double a, double b)
1501{
1502 Procedure proc;
1503 BasicBlock* root = proc.addBlock();
1504 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1505 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1506 root->appendNewControlValue(
1507 proc, Return, Origin(),
1508 root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1509
1510 CHECK(isIdentical(compileAndRun<double>(proc, b), a * b));
1511}
1512
1513void testMulImmsDouble(double a, double b)
1514{
1515 Procedure proc;
1516 BasicBlock* root = proc.addBlock();
1517 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1518 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1519 root->appendNewControlValue(
1520 proc, Return, Origin(),
1521 root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1522
1523 CHECK(isIdentical(compileAndRun<double>(proc), a * b));
1524}
1525
1526void testMulArgFloat(float a)
1527{
1528 Procedure proc;
1529 BasicBlock* root = proc.addBlock();
1530 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1531 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1532 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1533 Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue, floatValue);
1534 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1535 root->appendNewControlValue(proc, Return, Origin(), result32);
1536
1537
1538 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * a)));
1539}
1540
1541void testMulArgsFloat(float a, float b)
1542{
1543 Procedure proc;
1544 BasicBlock* root = proc.addBlock();
1545 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1546 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1547 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1548 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1549 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1550 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1551 Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue1, floatValue2);
1552 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1553 root->appendNewControlValue(proc, Return, Origin(), result32);
1554
1555 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1556}
1557
1558void testMulArgImmFloat(float a, float b)
1559{
1560 Procedure proc;
1561 BasicBlock* root = proc.addBlock();
1562 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1563 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1564 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1565 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1566 Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue, constValue);
1567 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1568 root->appendNewControlValue(proc, Return, Origin(), result32);
1569
1570 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * b)));
1571}
1572
1573void testMulImmArgFloat(float a, float b)
1574{
1575 Procedure proc;
1576 BasicBlock* root = proc.addBlock();
1577 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1578 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1579 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1580 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1581 Value* result = root->appendNew<Value>(proc, Mul, Origin(), constValue, floatValue);
1582 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1583 root->appendNewControlValue(proc, Return, Origin(), result32);
1584
1585 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1586}
1587
1588void testMulImmsFloat(float a, float b)
1589{
1590 Procedure proc;
1591 BasicBlock* root = proc.addBlock();
1592 Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1593 Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1594 Value* result = root->appendNew<Value>(proc, Mul, Origin(), constValue1, constValue2);
1595 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1596 root->appendNewControlValue(proc, Return, Origin(), result32);
1597
1598 CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a * b)));
1599}
1600
1601void testMulArgFloatWithUselessDoubleConversion(float a)
1602{
1603 Procedure proc;
1604 BasicBlock* root = proc.addBlock();
1605 Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1606 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1607 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
1608 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1609 Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble, asDouble);
1610 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1611 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1612 root->appendNewControlValue(proc, Return, Origin(), result32);
1613
1614 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * a)));
1615}
1616
1617void testMulArgsFloatWithUselessDoubleConversion(float a, float b)
1618{
1619 Procedure proc;
1620 BasicBlock* root = proc.addBlock();
1621 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1622 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1623 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1624 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1625 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1626 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1627 Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1628 Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1629 Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble1, asDouble2);
1630 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1631 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1632 root->appendNewControlValue(proc, Return, Origin(), result32);
1633
1634 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1635}
1636
1637void testMulArgsFloatWithEffectfulDoubleConversion(float a, float b)
1638{
1639 Procedure proc;
1640 BasicBlock* root = proc.addBlock();
1641 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1642 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1643 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1644 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1645 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1646 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1647 Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1648 Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1649 Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble1, asDouble2);
1650 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1651 Value* doubleMulress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1652 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleMulress);
1653 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1654 root->appendNewControlValue(proc, Return, Origin(), result32);
1655
1656 double effect = 0;
1657 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a * b)));
1658 CHECK(isIdentical(effect, static_cast<double>(a) * static_cast<double>(b)));
1659}
1660
1661void testDivArgDouble(double a)
1662{
1663 Procedure proc;
1664 BasicBlock* root = proc.addBlock();
1665 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1666 root->appendNewControlValue(
1667 proc, Return, Origin(),
1668 root->appendNew<Value>(proc, Div, Origin(), value, value));
1669
1670 CHECK(isIdentical(compileAndRun<double>(proc, a), a / a));
1671}
1672
1673void testDivArgsDouble(double a, double b)
1674{
1675 Procedure proc;
1676 BasicBlock* root = proc.addBlock();
1677 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1678 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1679 root->appendNewControlValue(
1680 proc, Return, Origin(),
1681 root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1682
1683 CHECK(isIdentical(compileAndRun<double>(proc, a, b), a / b));
1684}
1685
1686void testDivArgImmDouble(double a, double b)
1687{
1688 Procedure proc;
1689 BasicBlock* root = proc.addBlock();
1690 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1691 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1692 root->appendNewControlValue(
1693 proc, Return, Origin(),
1694 root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1695
1696 CHECK(isIdentical(compileAndRun<double>(proc, a), a / b));
1697}
1698
1699void testDivImmArgDouble(double a, double b)
1700{
1701 Procedure proc;
1702 BasicBlock* root = proc.addBlock();
1703 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1704 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1705 root->appendNewControlValue(
1706 proc, Return, Origin(),
1707 root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1708
1709 CHECK(isIdentical(compileAndRun<double>(proc, b), a / b));
1710}
1711
1712void testDivImmsDouble(double a, double b)
1713{
1714 Procedure proc;
1715 BasicBlock* root = proc.addBlock();
1716 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1717 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1718 root->appendNewControlValue(
1719 proc, Return, Origin(),
1720 root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1721
1722 CHECK(isIdentical(compileAndRun<double>(proc), a / b));
1723}
1724
1725void testDivArgFloat(float a)
1726{
1727 Procedure proc;
1728 BasicBlock* root = proc.addBlock();
1729 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1730 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1731 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1732 Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue, floatValue);
1733 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1734 root->appendNewControlValue(proc, Return, Origin(), result32);
1735
1736
1737 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a)));
1738}
1739
1740void testDivArgsFloat(float a, float b)
1741{
1742 Procedure proc;
1743 BasicBlock* root = proc.addBlock();
1744 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1745 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1746 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1747 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1748 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1749 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1750 Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue1, floatValue2);
1751 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1752 root->appendNewControlValue(proc, Return, Origin(), result32);
1753
1754 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1755}
1756
1757void testDivArgImmFloat(float a, float b)
1758{
1759 Procedure proc;
1760 BasicBlock* root = proc.addBlock();
1761 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1762 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1763 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1764 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1765 Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue, constValue);
1766 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1767 root->appendNewControlValue(proc, Return, Origin(), result32);
1768
1769 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / b)));
1770}
1771
1772void testDivImmArgFloat(float a, float b)
1773{
1774 Procedure proc;
1775 BasicBlock* root = proc.addBlock();
1776 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1777 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1778 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1779 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1780 Value* result = root->appendNew<Value>(proc, Div, Origin(), constValue, floatValue);
1781 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1782 root->appendNewControlValue(proc, Return, Origin(), result32);
1783
1784 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1785}
1786
1787void testDivImmsFloat(float a, float b)
1788{
1789 Procedure proc;
1790 BasicBlock* root = proc.addBlock();
1791 Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1792 Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1793 Value* result = root->appendNew<Value>(proc, Div, Origin(), constValue1, constValue2);
1794 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1795 root->appendNewControlValue(proc, Return, Origin(), result32);
1796
1797 CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a / b)));
1798}
1799
1800void testModArgDouble(double a)
1801{
1802 Procedure proc;
1803 BasicBlock* root = proc.addBlock();
1804 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1805 root->appendNewControlValue(
1806 proc, Return, Origin(),
1807 root->appendNew<Value>(proc, Mod, Origin(), value, value));
1808
1809 CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, a)));
1810}
1811
1812void testModArgsDouble(double a, double b)
1813{
1814 Procedure proc;
1815 BasicBlock* root = proc.addBlock();
1816 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1817 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1818 root->appendNewControlValue(
1819 proc, Return, Origin(),
1820 root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1821
1822 CHECK(isIdentical(compileAndRun<double>(proc, a, b), fmod(a, b)));
1823}
1824
1825void testModArgImmDouble(double a, double b)
1826{
1827 Procedure proc;
1828 BasicBlock* root = proc.addBlock();
1829 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1830 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1831 root->appendNewControlValue(
1832 proc, Return, Origin(),
1833 root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1834
1835 CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, b)));
1836}
1837
1838void testModImmArgDouble(double a, double b)
1839{
1840 Procedure proc;
1841 BasicBlock* root = proc.addBlock();
1842 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1843 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1844 root->appendNewControlValue(
1845 proc, Return, Origin(),
1846 root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1847
1848 CHECK(isIdentical(compileAndRun<double>(proc, b), fmod(a, b)));
1849}
1850
1851void testModImmsDouble(double a, double b)
1852{
1853 Procedure proc;
1854 BasicBlock* root = proc.addBlock();
1855 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1856 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1857 root->appendNewControlValue(
1858 proc, Return, Origin(),
1859 root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1860
1861 CHECK(isIdentical(compileAndRun<double>(proc), fmod(a, b)));
1862}
1863
1864void testModArgFloat(float a)
1865{
1866 Procedure proc;
1867 BasicBlock* root = proc.addBlock();
1868 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1869 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1870 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1871 Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, floatValue);
1872 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1873 root->appendNewControlValue(proc, Return, Origin(), result32);
1874
1875
1876 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, a)))));
1877}
1878
1879void testModArgsFloat(float a, float b)
1880{
1881 Procedure proc;
1882 BasicBlock* root = proc.addBlock();
1883 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1884 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1885 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1886 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1887 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1888 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1889 Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue1, floatValue2);
1890 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1891 root->appendNewControlValue(proc, Return, Origin(), result32);
1892
1893 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1894}
1895
1896void testModArgImmFloat(float a, float b)
1897{
1898 Procedure proc;
1899 BasicBlock* root = proc.addBlock();
1900 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1901 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1902 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1903 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1904 Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, constValue);
1905 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1906 root->appendNewControlValue(proc, Return, Origin(), result32);
1907
1908 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1909}
1910
1911void testModImmArgFloat(float a, float b)
1912{
1913 Procedure proc;
1914 BasicBlock* root = proc.addBlock();
1915 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1916 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1917 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1918 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1919 Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue, floatValue);
1920 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1921 root->appendNewControlValue(proc, Return, Origin(), result32);
1922
1923 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1924}
1925
1926void testModImmsFloat(float a, float b)
1927{
1928 Procedure proc;
1929 BasicBlock* root = proc.addBlock();
1930 Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1931 Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1932 Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue1, constValue2);
1933 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1934 root->appendNewControlValue(proc, Return, Origin(), result32);
1935
1936 CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1937}
1938
1939void testDivArgFloatWithUselessDoubleConversion(float a)
1940{
1941 Procedure proc;
1942 BasicBlock* root = proc.addBlock();
1943 Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1944 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1945 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
1946 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1947 Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble, asDouble);
1948 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1949 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1950 root->appendNewControlValue(proc, Return, Origin(), result32);
1951
1952 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a)));
1953}
1954
1955void testDivArgsFloatWithUselessDoubleConversion(float a, float b)
1956{
1957 Procedure proc;
1958 BasicBlock* root = proc.addBlock();
1959 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1960 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1961 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1962 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1963 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1964 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1965 Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1966 Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1967 Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2);
1968 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1969 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1970 root->appendNewControlValue(proc, Return, Origin(), result32);
1971
1972 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1973}
1974
1975void testDivArgsFloatWithEffectfulDoubleConversion(float a, float b)
1976{
1977 Procedure proc;
1978 BasicBlock* root = proc.addBlock();
1979 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1980 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1981 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1982 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1983 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1984 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1985 Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1986 Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1987 Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2);
1988 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1989 Value* doubleDivress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1990 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleDivress);
1991 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1992 root->appendNewControlValue(proc, Return, Origin(), result32);
1993
1994 double effect = 0;
1995 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a / b)));
1996 CHECK(isIdentical(effect, static_cast<double>(a) / static_cast<double>(b)));
1997}
1998
1999void testUDivArgsInt32(uint32_t a, uint32_t b)
2000{
2001 // UDiv with denominator == 0 is invalid.
2002 if (!b)
2003 return;
2004
2005 Procedure proc;
2006 BasicBlock* root = proc.addBlock();
2007 Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
2008 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2009 Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
2010 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2011 Value* result = root->appendNew<Value>(proc, UDiv, Origin(), argument1, argument2);
2012 root->appendNew<Value>(proc, Return, Origin(), result);
2013
2014 CHECK_EQ(compileAndRun<uint32_t>(proc, a, b), a / b);
2015}
2016
2017void testUDivArgsInt64(uint64_t a, uint64_t b)
2018{
2019 // UDiv with denominator == 0 is invalid.
2020 if (!b)
2021 return;
2022
2023 Procedure proc;
2024 BasicBlock* root = proc.addBlock();
2025 Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2026 Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2027 Value* result = root->appendNew<Value>(proc, UDiv, Origin(), argument1, argument2);
2028 root->appendNew<Value>(proc, Return, Origin(), result);
2029
2030 CHECK_EQ(compileAndRun<uint64_t>(proc, a, b), a / b);
2031}
2032
2033void testUModArgsInt32(uint32_t a, uint32_t b)
2034{
2035 // UMod with denominator == 0 is invalid.
2036 if (!b)
2037 return;
2038
2039 Procedure proc;
2040 BasicBlock* root = proc.addBlock();
2041 Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
2042 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2043 Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
2044 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2045 Value* result = root->appendNew<Value>(proc, UMod, Origin(), argument1, argument2);
2046 root->appendNew<Value>(proc, Return, Origin(), result);
2047
2048 CHECK_EQ(compileAndRun<uint32_t>(proc, a, b), a % b);
2049}
2050
2051void testUModArgsInt64(uint64_t a, uint64_t b)
2052{
2053 // UMod with denominator == 0 is invalid.
2054 if (!b)
2055 return;
2056
2057 Procedure proc;
2058 BasicBlock* root = proc.addBlock();
2059 Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2060 Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2061 Value* result = root->appendNew<Value>(proc, UMod, Origin(), argument1, argument2);
2062 root->appendNew<Value>(proc, Return, Origin(), result);
2063
2064 CHECK_EQ(compileAndRun<uint64_t>(proc, a, b), a % b);
2065}
2066
2067void testSubArg(int a)
2068{
2069 Procedure proc;
2070 BasicBlock* root = proc.addBlock();
2071 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2072 root->appendNewControlValue(
2073 proc, Return, Origin(),
2074 root->appendNew<Value>(proc, Sub, Origin(), value, value));
2075
2076 CHECK(!compileAndRun<int>(proc, a));
2077}
2078
2079void testSubArgs(int a, int b)
2080{
2081 Procedure proc;
2082 BasicBlock* root = proc.addBlock();
2083 root->appendNewControlValue(
2084 proc, Return, Origin(),
2085 root->appendNew<Value>(
2086 proc, Sub, Origin(),
2087 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2088 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2089
2090 CHECK(compileAndRun<int>(proc, a, b) == a - b);
2091}
2092
2093void testSubArgImm(int64_t a, int64_t b)
2094{
2095 Procedure proc;
2096 BasicBlock* root = proc.addBlock();
2097 root->appendNewControlValue(
2098 proc, Return, Origin(),
2099 root->appendNew<Value>(
2100 proc, Sub, Origin(),
2101 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2102 root->appendNew<Const64Value>(proc, Origin(), b)));
2103
2104 CHECK(compileAndRun<int64_t>(proc, a) == a - b);
2105}
2106
2107void testSubNeg(int a, int b)
2108{
2109 Procedure proc;
2110 BasicBlock* root = proc.addBlock();
2111 root->appendNewControlValue(
2112 proc, Return, Origin(),
2113 root->appendNew<Value>(
2114 proc, Sub, Origin(),
2115 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2116 root->appendNew<Value>(proc, Neg, Origin(),
2117 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2118
2119 CHECK(compileAndRun<int>(proc, a, b) == a - (- b));
2120}
2121
2122void testNegSub(int a, int b)
2123{
2124 Procedure proc;
2125 BasicBlock* root = proc.addBlock();
2126 root->appendNewControlValue(
2127 proc, Return, Origin(),
2128 root->appendNew<Value>(
2129 proc, Neg, Origin(),
2130 root->appendNew<Value>(proc, Sub, Origin(),
2131 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2132 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2133
2134 CHECK(compileAndRun<int>(proc, a, b) == -(a - b));
2135}
2136
2137void testNegValueSubOne(int a)
2138{
2139 Procedure proc;
2140 BasicBlock* root = proc.addBlock();
2141 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2142 Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
2143 root->appendNew<Const64Value>(proc, Origin(), 0),
2144 argument);
2145 Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
2146 negArgument,
2147 root->appendNew<Const64Value>(proc, Origin(), 1));
2148 root->appendNewControlValue(proc, Return, Origin(), negArgumentMinusOne);
2149 CHECK(compileAndRun<int>(proc, a) == -a - 1);
2150}
2151
2152void testSubImmArg(int a, int b)
2153{
2154 Procedure proc;
2155 BasicBlock* root = proc.addBlock();
2156 root->appendNewControlValue(
2157 proc, Return, Origin(),
2158 root->appendNew<Value>(
2159 proc, Sub, Origin(),
2160 root->appendNew<Const64Value>(proc, Origin(), a),
2161 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2162
2163 CHECK(compileAndRun<int>(proc, b) == a - b);
2164}
2165
2166void testSubArgMem(int64_t a, int64_t b)
2167{
2168 Procedure proc;
2169 BasicBlock* root = proc.addBlock();
2170 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2171 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2172 Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2173 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2174 load);
2175 root->appendNewControlValue(proc, Return, Origin(), result);
2176
2177 CHECK(compileAndRun<int64_t>(proc, a, &b) == a - b);
2178}
2179
2180void testSubMemArg(int64_t a, int64_t b)
2181{
2182 Procedure proc;
2183 BasicBlock* root = proc.addBlock();
2184 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2185 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2186 Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2187 load,
2188 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2189 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2190 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2191
2192 int64_t inputOutput = a;
2193 CHECK(!compileAndRun<int64_t>(proc, &inputOutput, b));
2194 CHECK(inputOutput == a - b);
2195}
2196
2197void testSubImmMem(int64_t a, int64_t b)
2198{
2199 Procedure proc;
2200 BasicBlock* root = proc.addBlock();
2201 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2202 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2203 Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2204 root->appendNew<Const64Value>(proc, Origin(), a),
2205 load);
2206 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2207 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2208
2209 int64_t inputOutput = b;
2210 CHECK(!compileAndRun<int>(proc, &inputOutput));
2211 CHECK(inputOutput == a - b);
2212}
2213
2214void testSubMemImm(int64_t a, int64_t b)
2215{
2216 Procedure proc;
2217 BasicBlock* root = proc.addBlock();
2218 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2219 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
2220 Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2221 load,
2222 root->appendNew<Const64Value>(proc, Origin(), b));
2223 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2224 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2225
2226 int64_t inputOutput = a;
2227 CHECK(!compileAndRun<int>(proc, &inputOutput));
2228 CHECK(inputOutput == a - b);
2229}
2230
2231
2232void testSubArgs32(int a, int b)
2233{
2234 Procedure proc;
2235 BasicBlock* root = proc.addBlock();
2236 root->appendNewControlValue(
2237 proc, Return, Origin(),
2238 root->appendNew<Value>(
2239 proc, Sub, Origin(),
2240 root->appendNew<Value>(
2241 proc, Trunc, Origin(),
2242 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2243 root->appendNew<Value>(
2244 proc, Trunc, Origin(),
2245 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2246
2247 CHECK(compileAndRun<int>(proc, a, b) == a - b);
2248}
2249
2250void testSubArgImm32(int a, int b)
2251{
2252 Procedure proc;
2253 BasicBlock* root = proc.addBlock();
2254 root->appendNewControlValue(
2255 proc, Return, Origin(),
2256 root->appendNew<Value>(
2257 proc, Sub, Origin(),
2258 root->appendNew<Value>(
2259 proc, Trunc, Origin(),
2260 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2261 root->appendNew<Const32Value>(proc, Origin(), b)));
2262
2263 CHECK(compileAndRun<int>(proc, a) == a - b);
2264}
2265
2266void testSubImmArg32(int a, int b)
2267{
2268 Procedure proc;
2269 BasicBlock* root = proc.addBlock();
2270 root->appendNewControlValue(
2271 proc, Return, Origin(),
2272 root->appendNew<Value>(
2273 proc, Sub, Origin(),
2274 root->appendNew<Const32Value>(proc, Origin(), a),
2275 root->appendNew<Value>(
2276 proc, Trunc, Origin(),
2277 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2278
2279 CHECK(compileAndRun<int>(proc, b) == a - b);
2280}
2281
2282void testSubMemArg32(int32_t a, int32_t b)
2283{
2284 Procedure proc;
2285 BasicBlock* root = proc.addBlock();
2286 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2287 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2288 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2289 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2290 Value* result = root->appendNew<Value>(proc, Sub, Origin(), load, argument);
2291 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2292 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2293
2294 int32_t inputOutput = a;
2295 CHECK(!compileAndRun<int32_t>(proc, &inputOutput, b));
2296 CHECK(inputOutput == a - b);
2297}
2298
2299void testSubArgMem32(int32_t a, int32_t b)
2300{
2301 Procedure proc;
2302 BasicBlock* root = proc.addBlock();
2303 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2304 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2305 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2306 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2307 Value* result = root->appendNew<Value>(proc, Sub, Origin(), argument, load);
2308 root->appendNewControlValue(proc, Return, Origin(), result);
2309
2310 CHECK(compileAndRun<int32_t>(proc, a, &b) == a - b);
2311}
2312
2313void testSubImmMem32(int32_t a, int32_t b)
2314{
2315 Procedure proc;
2316 BasicBlock* root = proc.addBlock();
2317 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2318 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2319 Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2320 root->appendNew<Const32Value>(proc, Origin(), a),
2321 load);
2322 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2323 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2324
2325 int32_t inputOutput = b;
2326 CHECK(!compileAndRun<int>(proc, &inputOutput));
2327 CHECK(inputOutput == a - b);
2328}
2329
2330void testSubMemImm32(int32_t a, int32_t b)
2331{
2332 Procedure proc;
2333 BasicBlock* root = proc.addBlock();
2334 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2335 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2336 Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2337 load,
2338 root->appendNew<Const32Value>(proc, Origin(), b));
2339 root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2340 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2341
2342 int32_t inputOutput = a;
2343 CHECK(!compileAndRun<int>(proc, &inputOutput));
2344 CHECK(inputOutput == a - b);
2345}
2346
2347void testNegValueSubOne32(int a)
2348{
2349 Procedure proc;
2350 BasicBlock* root = proc.addBlock();
2351 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2352 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2353 Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
2354 root->appendNew<Const32Value>(proc, Origin(), 0),
2355 argument);
2356 Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
2357 negArgument,
2358 root->appendNew<Const32Value>(proc, Origin(), 1));
2359 root->appendNewControlValue(proc, Return, Origin(), negArgumentMinusOne);
2360 CHECK(compileAndRun<int>(proc, a) == -a - 1);
2361}
2362
2363void testNegMulArgImm(int64_t a, int64_t b)
2364{
2365 Procedure proc;
2366 BasicBlock* root = proc.addBlock();
2367 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2368 Value* constant = root->appendNew<Const64Value>(proc, Origin(), b);
2369 Value* mul = root->appendNew<Value>(proc, Mul, Origin(), argument, constant);
2370 Value* result = root->appendNew<Value>(proc, Neg, Origin(), mul);
2371 root->appendNew<Value>(proc, Return, Origin(), result);
2372
2373 CHECK(compileAndRun<int64_t>(proc, a) == -(a * b));
2374}
2375
2376void testSubMulMulArgs(int64_t a, int64_t b, int64_t c)
2377{
2378 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
2379 // ((a * b) - (a * c))
2380 // ((a * b) - (c * a))
2381 // ((b * a) - (a * c))
2382 // ((b * a) - (c * a))
2383 for (int i = 0; i < 4; ++i) {
2384 Procedure proc;
2385 BasicBlock* root = proc.addBlock();
2386 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2387 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2388 Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
2389 Value* mulAB = i & 2 ? root->appendNew<Value>(proc, Mul, Origin(), argA, argB)
2390 : root->appendNew<Value>(proc, Mul, Origin(), argB, argA);
2391 Value* mulAC = i & 1 ? root->appendNew<Value>(proc, Mul, Origin(), argA, argC)
2392 : root->appendNew<Value>(proc, Mul, Origin(), argC, argA);
2393 root->appendNew<Value>(proc, Return, Origin(),
2394 root->appendNew<Value>(proc, Sub, Origin(),
2395 mulAB,
2396 mulAC));
2397
2398 CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a * b) - (a * c)));
2399 }
2400}
2401
2402void testSubArgDouble(double a)
2403{
2404 Procedure proc;
2405 BasicBlock* root = proc.addBlock();
2406 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2407 root->appendNewControlValue(
2408 proc, Return, Origin(),
2409 root->appendNew<Value>(proc, Sub, Origin(), value, value));
2410
2411 CHECK(isIdentical(compileAndRun<double>(proc, a), a - a));
2412}
2413
2414void testSubArgsDouble(double a, double b)
2415{
2416 Procedure proc;
2417 BasicBlock* root = proc.addBlock();
2418 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2419 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2420 root->appendNewControlValue(
2421 proc, Return, Origin(),
2422 root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2423
2424 CHECK(isIdentical(compileAndRun<double>(proc, a, b), a - b));
2425}
2426
2427void testSubArgImmDouble(double a, double b)
2428{
2429 Procedure proc;
2430 BasicBlock* root = proc.addBlock();
2431 Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2432 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2433 root->appendNewControlValue(
2434 proc, Return, Origin(),
2435 root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2436
2437 CHECK(isIdentical(compileAndRun<double>(proc, a), a - b));
2438}
2439
2440void testSubImmArgDouble(double a, double b)
2441{
2442 Procedure proc;
2443 BasicBlock* root = proc.addBlock();
2444 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2445 Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2446 root->appendNewControlValue(
2447 proc, Return, Origin(),
2448 root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2449
2450 CHECK(isIdentical(compileAndRun<double>(proc, b), a - b));
2451}
2452
2453void testSubImmsDouble(double a, double b)
2454{
2455 Procedure proc;
2456 BasicBlock* root = proc.addBlock();
2457 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2458 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2459 root->appendNewControlValue(
2460 proc, Return, Origin(),
2461 root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2462
2463 CHECK(isIdentical(compileAndRun<double>(proc), a - b));
2464}
2465
2466void testSubArgFloat(float a)
2467{
2468 Procedure proc;
2469 BasicBlock* root = proc.addBlock();
2470 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2471 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2472 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2473 Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, floatValue);
2474 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2475 root->appendNewControlValue(proc, Return, Origin(), result32);
2476
2477
2478 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a)));
2479}
2480
2481void testSubArgsFloat(float a, float b)
2482{
2483 Procedure proc;
2484 BasicBlock* root = proc.addBlock();
2485 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2486 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2487 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2488 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2489 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2490 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2491 Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue1, floatValue2);
2492 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2493 root->appendNewControlValue(proc, Return, Origin(), result32);
2494
2495 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2496}
2497
2498void testSubArgImmFloat(float a, float b)
2499{
2500 Procedure proc;
2501 BasicBlock* root = proc.addBlock();
2502 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2503 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2504 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2505 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2506 Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, constValue);
2507 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2508 root->appendNewControlValue(proc, Return, Origin(), result32);
2509
2510 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - b)));
2511}
2512
2513void testSubImmArgFloat(float a, float b)
2514{
2515 Procedure proc;
2516 BasicBlock* root = proc.addBlock();
2517 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2518 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2519 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2520 Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2521 Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue, floatValue);
2522 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2523 root->appendNewControlValue(proc, Return, Origin(), result32);
2524
2525 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2526}
2527
2528void testSubImmsFloat(float a, float b)
2529{
2530 Procedure proc;
2531 BasicBlock* root = proc.addBlock();
2532 Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2533 Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2534 Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue1, constValue2);
2535 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2536 root->appendNewControlValue(proc, Return, Origin(), result32);
2537
2538 CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a - b)));
2539}
2540
2541void testSubArgFloatWithUselessDoubleConversion(float a)
2542{
2543 Procedure proc;
2544 BasicBlock* root = proc.addBlock();
2545 Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
2546 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2547 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
2548 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2549 Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble, asDouble);
2550 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2551 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2552 root->appendNewControlValue(proc, Return, Origin(), result32);
2553
2554 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a)));
2555}
2556
2557void testSubArgsFloatWithUselessDoubleConversion(float a, float b)
2558{
2559 Procedure proc;
2560 BasicBlock* root = proc.addBlock();
2561 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2562 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2563 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2564 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2565 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2566 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2567 Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
2568 Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
2569 Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2);
2570 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2571 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2572 root->appendNewControlValue(proc, Return, Origin(), result32);
2573
2574 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2575}
2576
2577void testSubArgsFloatWithEffectfulDoubleConversion(float a, float b)
2578{
2579 Procedure proc;
2580 BasicBlock* root = proc.addBlock();
2581 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2582 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2583 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2584 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2585 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2586 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2587 Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
2588 Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
2589 Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2);
2590 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2591 Value* doubleSubress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
2592 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleSubress);
2593 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2594 root->appendNewControlValue(proc, Return, Origin(), result32);
2595
2596 double effect = 0;
2597 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a - b)));
2598 CHECK(isIdentical(effect, static_cast<double>(a) - static_cast<double>(b)));
2599}
2600
2601void testTernarySubInstructionSelection(B3::Opcode valueModifier, Type valueType, Air::Opcode expectedOpcode)
2602{
2603 Procedure proc;
2604 BasicBlock* root = proc.addBlock();
2605
2606 Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2607 Value* right = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2608
2609 if (valueModifier == Trunc) {
2610 left = root->appendNew<Value>(proc, valueModifier, valueType, Origin(), left);
2611 right = root->appendNew<Value>(proc, valueModifier, valueType, Origin(), right);
2612 }
2613
2614 root->appendNewControlValue(
2615 proc, Return, Origin(),
2616 root->appendNew<Value>(proc, Sub, Origin(), left, right));
2617
2618 lowerToAirForTesting(proc);
2619
2620 auto block = proc.code()[0];
2621 unsigned numberOfSubInstructions = 0;
2622 for (auto instruction : *block) {
2623 if (instruction.kind.opcode == expectedOpcode) {
2624 CHECK_EQ(instruction.args.size(), 3ul);
2625 CHECK_EQ(instruction.args[0].kind(), Air::Arg::Tmp);
2626 CHECK_EQ(instruction.args[1].kind(), Air::Arg::Tmp);
2627 CHECK_EQ(instruction.args[2].kind(), Air::Arg::Tmp);
2628 numberOfSubInstructions++;
2629 }
2630 }
2631 CHECK_EQ(numberOfSubInstructions, 1ul);
2632}
2633
2634void testNegDouble(double a)
2635{
2636 Procedure proc;
2637 BasicBlock* root = proc.addBlock();
2638 root->appendNewControlValue(
2639 proc, Return, Origin(),
2640 root->appendNew<Value>(
2641 proc, Neg, Origin(),
2642 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
2643
2644 CHECK(isIdentical(compileAndRun<double>(proc, a), -a));
2645}
2646
2647void testNegFloat(float a)
2648{
2649 Procedure proc;
2650 BasicBlock* root = proc.addBlock();
2651 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2652 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2653 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2654 root->appendNewControlValue(
2655 proc, Return, Origin(),
2656 root->appendNew<Value>(proc, Neg, Origin(), floatValue));
2657
2658 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), -a));
2659}
2660
2661void testNegFloatWithUselessDoubleConversion(float a)
2662{
2663 Procedure proc;
2664 BasicBlock* root = proc.addBlock();
2665 Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
2666 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2667 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
2668 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2669 Value* result = root->appendNew<Value>(proc, Neg, Origin(), asDouble);
2670 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2671 root->appendNewControlValue(proc, Return, Origin(), floatResult);
2672
2673 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), -a));
2674}
2675
2676void testBitAndArgs(int64_t a, int64_t b)
2677{
2678 Procedure proc;
2679 BasicBlock* root = proc.addBlock();
2680 root->appendNewControlValue(
2681 proc, Return, Origin(),
2682 root->appendNew<Value>(
2683 proc, BitAnd, Origin(),
2684 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2685 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2686
2687 CHECK(compileAndRun<int64_t>(proc, a, b) == (a & b));
2688}
2689
2690void testBitAndSameArg(int64_t a)
2691{
2692 Procedure proc;
2693 BasicBlock* root = proc.addBlock();
2694 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2695 root->appendNewControlValue(
2696 proc, Return, Origin(),
2697 root->appendNew<Value>(
2698 proc, BitAnd, Origin(),
2699 argument,
2700 argument));
2701
2702 CHECK(compileAndRun<int64_t>(proc, a) == a);
2703}
2704
2705void testBitAndNotNot(int64_t a, int64_t b)
2706{
2707 Procedure proc;
2708 BasicBlock* root = proc.addBlock();
2709 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2710 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2711 Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
2712 Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const64Value>(proc, Origin(), -1));
2713 root->appendNewControlValue(
2714 proc, Return, Origin(),
2715 root->appendNew<Value>(
2716 proc, BitAnd, Origin(),
2717 notA,
2718 notB));
2719
2720 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a & ~b));
2721}
2722
2723void testBitAndNotImm(int64_t a, int64_t b)
2724{
2725 Procedure proc;
2726 BasicBlock* root = proc.addBlock();
2727 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2728 Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
2729 Value* cstB = root->appendNew<Const64Value>(proc, Origin(), b);
2730 root->appendNewControlValue(
2731 proc, Return, Origin(),
2732 root->appendNew<Value>(
2733 proc, BitAnd, Origin(),
2734 notA,
2735 cstB));
2736
2737 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a & b));
2738}
2739
2740void testBitAndImms(int64_t a, int64_t b)
2741{
2742 Procedure proc;
2743 BasicBlock* root = proc.addBlock();
2744 root->appendNewControlValue(
2745 proc, Return, Origin(),
2746 root->appendNew<Value>(
2747 proc, BitAnd, Origin(),
2748 root->appendNew<Const64Value>(proc, Origin(), a),
2749 root->appendNew<Const64Value>(proc, Origin(), b)));
2750
2751 CHECK(compileAndRun<int64_t>(proc) == (a & b));
2752}
2753
2754void testBitAndArgImm(int64_t a, int64_t b)
2755{
2756 Procedure proc;
2757 BasicBlock* root = proc.addBlock();
2758 root->appendNewControlValue(
2759 proc, Return, Origin(),
2760 root->appendNew<Value>(
2761 proc, BitAnd, Origin(),
2762 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2763 root->appendNew<Const64Value>(proc, Origin(), b)));
2764
2765 CHECK(compileAndRun<int64_t>(proc, a) == (a & b));
2766}
2767
2768void testBitAndImmArg(int64_t a, int64_t b)
2769{
2770 Procedure proc;
2771 BasicBlock* root = proc.addBlock();
2772 root->appendNewControlValue(
2773 proc, Return, Origin(),
2774 root->appendNew<Value>(
2775 proc, BitAnd, Origin(),
2776 root->appendNew<Const64Value>(proc, Origin(), a),
2777 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2778
2779 CHECK(compileAndRun<int64_t>(proc, b) == (a & b));
2780}
2781
2782void testBitAndBitAndArgImmImm(int64_t a, int64_t b, int64_t c)
2783{
2784 Procedure proc;
2785 BasicBlock* root = proc.addBlock();
2786 Value* innerBitAnd = root->appendNew<Value>(
2787 proc, BitAnd, Origin(),
2788 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2789 root->appendNew<Const64Value>(proc, Origin(), b));
2790 root->appendNewControlValue(
2791 proc, Return, Origin(),
2792 root->appendNew<Value>(
2793 proc, BitAnd, Origin(),
2794 innerBitAnd,
2795 root->appendNew<Const64Value>(proc, Origin(), c)));
2796
2797 CHECK(compileAndRun<int64_t>(proc, a) == ((a & b) & c));
2798}
2799
2800void testBitAndImmBitAndArgImm(int64_t a, int64_t b, int64_t c)
2801{
2802 Procedure proc;
2803 BasicBlock* root = proc.addBlock();
2804 Value* innerBitAnd = root->appendNew<Value>(
2805 proc, BitAnd, Origin(),
2806 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2807 root->appendNew<Const64Value>(proc, Origin(), c));
2808 root->appendNewControlValue(
2809 proc, Return, Origin(),
2810 root->appendNew<Value>(
2811 proc, BitAnd, Origin(),
2812 root->appendNew<Const64Value>(proc, Origin(), a),
2813 innerBitAnd));
2814
2815 CHECK(compileAndRun<int64_t>(proc, b) == (a & (b & c)));
2816}
2817
2818void testBitAndArgs32(int a, int b)
2819{
2820 Procedure proc;
2821 BasicBlock* root = proc.addBlock();
2822 root->appendNewControlValue(
2823 proc, Return, Origin(),
2824 root->appendNew<Value>(
2825 proc, BitAnd, Origin(),
2826 root->appendNew<Value>(
2827 proc, Trunc, Origin(),
2828 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2829 root->appendNew<Value>(
2830 proc, Trunc, Origin(),
2831 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2832
2833 CHECK(compileAndRun<int>(proc, a, b) == (a & b));
2834}
2835
2836void testBitAndSameArg32(int a)
2837{
2838 Procedure proc;
2839 BasicBlock* root = proc.addBlock();
2840 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2841 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2842 root->appendNewControlValue(
2843 proc, Return, Origin(),
2844 root->appendNew<Value>(
2845 proc, BitAnd, Origin(),
2846 argument,
2847 argument));
2848
2849 CHECK(compileAndRun<int>(proc, a) == a);
2850}
2851
2852void testBitAndImms32(int a, int b)
2853{
2854 Procedure proc;
2855 BasicBlock* root = proc.addBlock();
2856 root->appendNewControlValue(
2857 proc, Return, Origin(),
2858 root->appendNew<Value>(
2859 proc, BitAnd, Origin(),
2860 root->appendNew<Const32Value>(proc, Origin(), a),
2861 root->appendNew<Const32Value>(proc, Origin(), b)));
2862
2863 CHECK(compileAndRun<int>(proc) == (a & b));
2864}
2865
2866void testBitAndArgImm32(int a, int b)
2867{
2868 Procedure proc;
2869 BasicBlock* root = proc.addBlock();
2870 root->appendNewControlValue(
2871 proc, Return, Origin(),
2872 root->appendNew<Value>(
2873 proc, BitAnd, Origin(),
2874 root->appendNew<Value>(
2875 proc, Trunc, Origin(),
2876 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2877 root->appendNew<Const32Value>(proc, Origin(), b)));
2878
2879 CHECK(compileAndRun<int>(proc, a) == (a & b));
2880}
2881
2882void testBitAndImmArg32(int a, int b)
2883{
2884 Procedure proc;
2885 BasicBlock* root = proc.addBlock();
2886 root->appendNewControlValue(
2887 proc, Return, Origin(),
2888 root->appendNew<Value>(
2889 proc, BitAnd, Origin(),
2890 root->appendNew<Const32Value>(proc, Origin(), a),
2891 root->appendNew<Value>(
2892 proc, Trunc, Origin(),
2893 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2894
2895 CHECK(compileAndRun<int>(proc, b) == (a & b));
2896}
2897
2898void testBitAndBitAndArgImmImm32(int a, int b, int c)
2899{
2900 Procedure proc;
2901 BasicBlock* root = proc.addBlock();
2902 Value* innerBitAnd = root->appendNew<Value>(
2903 proc, BitAnd, Origin(),
2904 root->appendNew<Value>(
2905 proc, Trunc, Origin(),
2906 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2907 root->appendNew<Const32Value>(proc, Origin(), b));
2908 root->appendNewControlValue(
2909 proc, Return, Origin(),
2910 root->appendNew<Value>(
2911 proc, BitAnd, Origin(),
2912 innerBitAnd,
2913 root->appendNew<Const32Value>(proc, Origin(), c)));
2914
2915 CHECK(compileAndRun<int>(proc, a) == ((a & b) & c));
2916}
2917
2918void testBitAndImmBitAndArgImm32(int a, int b, int c)
2919{
2920 Procedure proc;
2921 BasicBlock* root = proc.addBlock();
2922 Value* innerBitAnd = root->appendNew<Value>(
2923 proc, BitAnd, Origin(),
2924 root->appendNew<Value>(
2925 proc, Trunc, Origin(),
2926 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2927 root->appendNew<Const32Value>(proc, Origin(), c));
2928 root->appendNewControlValue(
2929 proc, Return, Origin(),
2930 root->appendNew<Value>(
2931 proc, BitAnd, Origin(),
2932 root->appendNew<Const32Value>(proc, Origin(), a),
2933 innerBitAnd));
2934
2935 CHECK(compileAndRun<int>(proc, b) == (a & (b & c)));
2936}
2937
2938void testBitAndWithMaskReturnsBooleans(int64_t a, int64_t b)
2939{
2940 Procedure proc;
2941 BasicBlock* root = proc.addBlock();
2942 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2943 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2944 Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg0, arg1);
2945 Value* maskedEqual = root->appendNew<Value>(proc, BitAnd, Origin(),
2946 root->appendNew<Const32Value>(proc, Origin(), 0x5),
2947 equal);
2948 Value* inverted = root->appendNew<Value>(proc, BitXor, Origin(),
2949 root->appendNew<Const32Value>(proc, Origin(), 0x1),
2950 maskedEqual);
2951 Value* select = root->appendNew<Value>(proc, Select, Origin(), inverted,
2952 root->appendNew<Const64Value>(proc, Origin(), 42),
2953 root->appendNew<Const64Value>(proc, Origin(), -5));
2954
2955 root->appendNewControlValue(proc, Return, Origin(), select);
2956
2957 int64_t expected = (a == b) ? -5 : 42;
2958 CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
2959}
2960
2961double bitAndDouble(double a, double b)
2962{
2963 return bitwise_cast<double>(bitwise_cast<uint64_t>(a) & bitwise_cast<uint64_t>(b));
2964}
2965
2966void testBitAndArgDouble(double a)
2967{
2968 Procedure proc;
2969 BasicBlock* root = proc.addBlock();
2970 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2971 Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2972 root->appendNewControlValue(proc, Return, Origin(), result);
2973
2974 CHECK(isIdentical(compileAndRun<double>(proc, a), bitAndDouble(a, a)));
2975}
2976
2977void testBitAndArgsDouble(double a, double b)
2978{
2979 Procedure proc;
2980 BasicBlock* root = proc.addBlock();
2981 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2982 Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2983 Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2984 root->appendNewControlValue(proc, Return, Origin(), result);
2985
2986 CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2987}
2988
2989void testBitAndArgImmDouble(double a, double b)
2990{
2991 Procedure proc;
2992 BasicBlock* root = proc.addBlock();
2993 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2994 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2995 Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2996 root->appendNewControlValue(proc, Return, Origin(), result);
2997
2998 CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2999}
3000
3001void testBitAndImmsDouble(double a, double b)
3002{
3003 Procedure proc;
3004 BasicBlock* root = proc.addBlock();
3005 Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
3006 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
3007 Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
3008 root->appendNewControlValue(proc, Return, Origin(), result);
3009
3010 CHECK(isIdentical(compileAndRun<double>(proc), bitAndDouble(a, b)));
3011}
3012
3013float bitAndFloat(float a, float b)
3014{
3015 return bitwise_cast<float>(bitwise_cast<uint32_t>(a) & bitwise_cast<uint32_t>(b));
3016}
3017
3018void testBitAndArgFloat(float a)
3019{
3020 Procedure proc;
3021 BasicBlock* root = proc.addBlock();
3022 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3023 root->appendNew<Value>(proc, Trunc, Origin(),
3024 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3025 Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
3026 root->appendNewControlValue(proc, Return, Origin(), result);
3027
3028 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitAndFloat(a, a)));
3029}
3030
3031void testBitAndArgsFloat(float a, float b)
3032{
3033 Procedure proc;
3034 BasicBlock* root = proc.addBlock();
3035 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3036 root->appendNew<Value>(proc, Trunc, Origin(),
3037 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3038 Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3039 root->appendNew<Value>(proc, Trunc, Origin(),
3040 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3041 Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
3042 root->appendNewControlValue(proc, Return, Origin(), result);
3043
3044 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
3045}
3046
3047void testBitAndArgImmFloat(float a, float b)
3048{
3049 Procedure proc;
3050 BasicBlock* root = proc.addBlock();
3051 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3052 root->appendNew<Value>(proc, Trunc, Origin(),
3053 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3054 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
3055 Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
3056 root->appendNewControlValue(proc, Return, Origin(), result);
3057
3058 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
3059}
3060
3061void testBitAndImmsFloat(float a, float b)
3062{
3063 Procedure proc;
3064 BasicBlock* root = proc.addBlock();
3065 Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
3066 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
3067 Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
3068 root->appendNewControlValue(proc, Return, Origin(), result);
3069
3070 CHECK(isIdentical(compileAndRun<float>(proc), bitAndFloat(a, b)));
3071}
3072
3073void testBitAndArgsFloatWithUselessDoubleConversion(float a, float b)
3074{
3075 Procedure proc;
3076 BasicBlock* root = proc.addBlock();
3077 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3078 root->appendNew<Value>(proc, Trunc, Origin(),
3079 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3080 Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3081 root->appendNew<Value>(proc, Trunc, Origin(),
3082 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3083 Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
3084 Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
3085 Value* doubleResult = root->appendNew<Value>(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble);
3086 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
3087 root->appendNewControlValue(proc, Return, Origin(), floatResult);
3088
3089 double doubleA = a;
3090 double doubleB = b;
3091 float expected = static_cast<float>(bitAndDouble(doubleA, doubleB));
3092 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
3093}
3094
3095void testBitOrArgs(int64_t a, int64_t b)
3096{
3097 Procedure proc;
3098 BasicBlock* root = proc.addBlock();
3099 root->appendNewControlValue(
3100 proc, Return, Origin(),
3101 root->appendNew<Value>(
3102 proc, BitOr, Origin(),
3103 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3104 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3105
3106 CHECK(compileAndRun<int64_t>(proc, a, b) == (a | b));
3107}
3108
3109void testBitOrSameArg(int64_t a)
3110{
3111 Procedure proc;
3112 BasicBlock* root = proc.addBlock();
3113 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3114 root->appendNewControlValue(
3115 proc, Return, Origin(),
3116 root->appendNew<Value>(
3117 proc, BitOr, Origin(),
3118 argument,
3119 argument));
3120
3121 CHECK(compileAndRun<int64_t>(proc, a) == a);
3122}
3123
3124void testBitOrAndAndArgs(int64_t a, int64_t b, int64_t c)
3125{
3126 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3127 // ((a & b) | (a & c))
3128 // ((a & b) | (c & a))
3129 // ((b & a) | (a & c))
3130 // ((b & a) | (c & a))
3131 for (int i = 0; i < 4; ++i) {
3132 Procedure proc;
3133 BasicBlock* root = proc.addBlock();
3134 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3135 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3136 Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
3137 Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3138 : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3139 Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
3140 : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
3141 root->appendNewControlValue(
3142 proc, Return, Origin(),
3143 root->appendNew<Value>(
3144 proc, BitOr, Origin(),
3145 andAB,
3146 andAC));
3147
3148 CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a & b) | (a & c)));
3149 }
3150}
3151
3152void testBitOrAndSameArgs(int64_t a, int64_t b)
3153{
3154 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3155 // ((a & b) | a)
3156 // ((b & a) | a)
3157 // (a | (a & b))
3158 // (a | (b & a))
3159 for (int i = 0; i < 4; ++i) {
3160 Procedure proc;
3161 BasicBlock* root = proc.addBlock();
3162 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3163 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3164 Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3165 : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3166 Value* result = i & 2 ? root->appendNew<Value>(proc, BitOr, Origin(), andAB, argA)
3167 : root->appendNew<Value>(proc, BitOr, Origin(), argA, andAB);
3168 root->appendNewControlValue(proc, Return, Origin(), result);
3169
3170 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), ((a & b) | a));
3171 }
3172}
3173
3174void testBitOrNotNot(int64_t a, int64_t b)
3175{
3176 Procedure proc;
3177 BasicBlock* root = proc.addBlock();
3178 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3179 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3180 Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
3181 Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const64Value>(proc, Origin(), -1));
3182 root->appendNewControlValue(
3183 proc, Return, Origin(),
3184 root->appendNew<Value>(
3185 proc, BitOr, Origin(),
3186 notA,
3187 notB));
3188
3189 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | ~b));
3190}
3191
3192void testBitOrNotImm(int64_t a, int64_t b)
3193{
3194 Procedure proc;
3195 BasicBlock* root = proc.addBlock();
3196 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3197 Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const64Value>(proc, Origin(), -1));
3198 Value* cstB = root->appendNew<Const64Value>(proc, Origin(), b);
3199 root->appendNewControlValue(
3200 proc, Return, Origin(),
3201 root->appendNew<Value>(
3202 proc, BitOr, Origin(),
3203 notA,
3204 cstB));
3205
3206 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | b));
3207}
3208
3209void testBitOrImms(int64_t a, int64_t b)
3210{
3211 Procedure proc;
3212 BasicBlock* root = proc.addBlock();
3213 root->appendNewControlValue(
3214 proc, Return, Origin(),
3215 root->appendNew<Value>(
3216 proc, BitOr, Origin(),
3217 root->appendNew<Const64Value>(proc, Origin(), a),
3218 root->appendNew<Const64Value>(proc, Origin(), b)));
3219
3220 CHECK(compileAndRun<int64_t>(proc) == (a | b));
3221}
3222
3223void testBitOrArgImm(int64_t a, int64_t b)
3224{
3225 Procedure proc;
3226 BasicBlock* root = proc.addBlock();
3227 root->appendNewControlValue(
3228 proc, Return, Origin(),
3229 root->appendNew<Value>(
3230 proc, BitOr, Origin(),
3231 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3232 root->appendNew<Const64Value>(proc, Origin(), b)));
3233
3234 CHECK(compileAndRun<int64_t>(proc, a) == (a | b));
3235}
3236
3237void testBitOrImmArg(int64_t a, int64_t b)
3238{
3239 Procedure proc;
3240 BasicBlock* root = proc.addBlock();
3241 root->appendNewControlValue(
3242 proc, Return, Origin(),
3243 root->appendNew<Value>(
3244 proc, BitOr, Origin(),
3245 root->appendNew<Const64Value>(proc, Origin(), a),
3246 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3247
3248 CHECK(compileAndRun<int64_t>(proc, b) == (a | b));
3249}
3250
3251void testBitOrBitOrArgImmImm(int64_t a, int64_t b, int64_t c)
3252{
3253 Procedure proc;
3254 BasicBlock* root = proc.addBlock();
3255 Value* innerBitOr = root->appendNew<Value>(
3256 proc, BitOr, Origin(),
3257 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3258 root->appendNew<Const64Value>(proc, Origin(), b));
3259 root->appendNewControlValue(
3260 proc, Return, Origin(),
3261 root->appendNew<Value>(
3262 proc, BitOr, Origin(),
3263 innerBitOr,
3264 root->appendNew<Const64Value>(proc, Origin(), c)));
3265
3266 CHECK(compileAndRun<int64_t>(proc, a) == ((a | b) | c));
3267}
3268
3269void testBitOrImmBitOrArgImm(int64_t a, int64_t b, int64_t c)
3270{
3271 Procedure proc;
3272 BasicBlock* root = proc.addBlock();
3273 Value* innerBitOr = root->appendNew<Value>(
3274 proc, BitOr, Origin(),
3275 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3276 root->appendNew<Const64Value>(proc, Origin(), c));
3277 root->appendNewControlValue(
3278 proc, Return, Origin(),
3279 root->appendNew<Value>(
3280 proc, BitOr, Origin(),
3281 root->appendNew<Const64Value>(proc, Origin(), a),
3282 innerBitOr));
3283
3284 CHECK(compileAndRun<int64_t>(proc, b) == (a | (b | c)));
3285}
3286
3287void testBitOrArgs32(int a, int b)
3288{
3289 Procedure proc;
3290 BasicBlock* root = proc.addBlock();
3291 root->appendNewControlValue(
3292 proc, Return, Origin(),
3293 root->appendNew<Value>(
3294 proc, BitOr, Origin(),
3295 root->appendNew<Value>(
3296 proc, Trunc, Origin(),
3297 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3298 root->appendNew<Value>(
3299 proc, Trunc, Origin(),
3300 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3301
3302 CHECK(compileAndRun<int>(proc, a, b) == (a | b));
3303}
3304
3305void testBitOrSameArg32(int a)
3306{
3307 Procedure proc;
3308 BasicBlock* root = proc.addBlock();
3309 Value* argument = root->appendNew<Value>(
3310 proc, Trunc, Origin(),
3311 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3312 root->appendNewControlValue(
3313 proc, Return, Origin(),
3314 root->appendNew<Value>(
3315 proc, BitOr, Origin(),
3316 argument,
3317 argument));
3318
3319 CHECK(compileAndRun<int>(proc, a) == a);
3320}
3321
3322void testBitOrImms32(int a, int b)
3323{
3324 Procedure proc;
3325 BasicBlock* root = proc.addBlock();
3326 root->appendNewControlValue(
3327 proc, Return, Origin(),
3328 root->appendNew<Value>(
3329 proc, BitOr, Origin(),
3330 root->appendNew<Const32Value>(proc, Origin(), a),
3331 root->appendNew<Const32Value>(proc, Origin(), b)));
3332
3333 CHECK(compileAndRun<int>(proc) == (a | b));
3334}
3335
3336void testBitOrArgImm32(int a, int b)
3337{
3338 Procedure proc;
3339 BasicBlock* root = proc.addBlock();
3340 root->appendNewControlValue(
3341 proc, Return, Origin(),
3342 root->appendNew<Value>(
3343 proc, BitOr, Origin(),
3344 root->appendNew<Value>(
3345 proc, Trunc, Origin(),
3346 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3347 root->appendNew<Const32Value>(proc, Origin(), b)));
3348
3349 CHECK(compileAndRun<int>(proc, a) == (a | b));
3350}
3351
3352void testBitOrImmArg32(int a, int b)
3353{
3354 Procedure proc;
3355 BasicBlock* root = proc.addBlock();
3356 root->appendNewControlValue(
3357 proc, Return, Origin(),
3358 root->appendNew<Value>(
3359 proc, BitOr, Origin(),
3360 root->appendNew<Const32Value>(proc, Origin(), a),
3361 root->appendNew<Value>(
3362 proc, Trunc, Origin(),
3363 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3364
3365 CHECK(compileAndRun<int>(proc, b) == (a | b));
3366}
3367
3368void testBitOrBitOrArgImmImm32(int a, int b, int c)
3369{
3370 Procedure proc;
3371 BasicBlock* root = proc.addBlock();
3372 Value* innerBitOr = root->appendNew<Value>(
3373 proc, BitOr, Origin(),
3374 root->appendNew<Value>(
3375 proc, Trunc, Origin(),
3376 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3377 root->appendNew<Const32Value>(proc, Origin(), b));
3378 root->appendNewControlValue(
3379 proc, Return, Origin(),
3380 root->appendNew<Value>(
3381 proc, BitOr, Origin(),
3382 innerBitOr,
3383 root->appendNew<Const32Value>(proc, Origin(), c)));
3384
3385 CHECK(compileAndRun<int>(proc, a) == ((a | b) | c));
3386}
3387
3388void testBitOrImmBitOrArgImm32(int a, int b, int c)
3389{
3390 Procedure proc;
3391 BasicBlock* root = proc.addBlock();
3392 Value* innerBitOr = root->appendNew<Value>(
3393 proc, BitOr, Origin(),
3394 root->appendNew<Value>(
3395 proc, Trunc, Origin(),
3396 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3397 root->appendNew<Const32Value>(proc, Origin(), c));
3398 root->appendNewControlValue(
3399 proc, Return, Origin(),
3400 root->appendNew<Value>(
3401 proc, BitOr, Origin(),
3402 root->appendNew<Const32Value>(proc, Origin(), a),
3403 innerBitOr));
3404
3405 CHECK(compileAndRun<int>(proc, b) == (a | (b | c)));
3406}
3407
3408double bitOrDouble(double a, double b)
3409{
3410 return bitwise_cast<double>(bitwise_cast<uint64_t>(a) | bitwise_cast<uint64_t>(b));
3411}
3412
3413void testBitOrArgDouble(double a)
3414{
3415 Procedure proc;
3416 BasicBlock* root = proc.addBlock();
3417 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3418 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argument, argument);
3419 root->appendNewControlValue(proc, Return, Origin(), result);
3420
3421 CHECK(isIdentical(compileAndRun<double>(proc, a), bitOrDouble(a, a)));
3422}
3423
3424void testBitOrArgsDouble(double a, double b)
3425{
3426 Procedure proc;
3427 BasicBlock* root = proc.addBlock();
3428 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3429 Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
3430 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3431 root->appendNewControlValue(proc, Return, Origin(), result);
3432
3433 CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b)));
3434}
3435
3436void testBitOrArgImmDouble(double a, double b)
3437{
3438 Procedure proc;
3439 BasicBlock* root = proc.addBlock();
3440 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3441 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
3442 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3443 root->appendNewControlValue(proc, Return, Origin(), result);
3444
3445 CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b)));
3446}
3447
3448void testBitOrImmsDouble(double a, double b)
3449{
3450 Procedure proc;
3451 BasicBlock* root = proc.addBlock();
3452 Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
3453 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
3454 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3455 root->appendNewControlValue(proc, Return, Origin(), result);
3456
3457 CHECK(isIdentical(compileAndRun<double>(proc), bitOrDouble(a, b)));
3458}
3459
3460float bitOrFloat(float a, float b)
3461{
3462 return bitwise_cast<float>(bitwise_cast<uint32_t>(a) | bitwise_cast<uint32_t>(b));
3463}
3464
3465void testBitOrArgFloat(float a)
3466{
3467 Procedure proc;
3468 BasicBlock* root = proc.addBlock();
3469 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3470 root->appendNew<Value>(proc, Trunc, Origin(),
3471 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3472 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argument, argument);
3473 root->appendNewControlValue(proc, Return, Origin(), result);
3474
3475 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitOrFloat(a, a)));
3476}
3477
3478void testBitOrArgsFloat(float a, float b)
3479{
3480 Procedure proc;
3481 BasicBlock* root = proc.addBlock();
3482 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3483 root->appendNew<Value>(proc, Trunc, Origin(),
3484 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3485 Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3486 root->appendNew<Value>(proc, Trunc, Origin(),
3487 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3488 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3489 root->appendNewControlValue(proc, Return, Origin(), result);
3490
3491 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b)));
3492}
3493
3494void testBitOrArgImmFloat(float a, float b)
3495{
3496 Procedure proc;
3497 BasicBlock* root = proc.addBlock();
3498 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3499 root->appendNew<Value>(proc, Trunc, Origin(),
3500 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3501 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
3502 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3503 root->appendNewControlValue(proc, Return, Origin(), result);
3504
3505 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b)));
3506}
3507
3508void testBitOrImmsFloat(float a, float b)
3509{
3510 Procedure proc;
3511 BasicBlock* root = proc.addBlock();
3512 Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
3513 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
3514 Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3515 root->appendNewControlValue(proc, Return, Origin(), result);
3516
3517 CHECK(isIdentical(compileAndRun<float>(proc), bitOrFloat(a, b)));
3518}
3519
3520void testBitOrArgsFloatWithUselessDoubleConversion(float a, float b)
3521{
3522 Procedure proc;
3523 BasicBlock* root = proc.addBlock();
3524 Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3525 root->appendNew<Value>(proc, Trunc, Origin(),
3526 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3527 Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3528 root->appendNew<Value>(proc, Trunc, Origin(),
3529 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3530 Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
3531 Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
3532 Value* doubleResult = root->appendNew<Value>(proc, BitOr, Origin(), argumentAasDouble, argumentBasDouble);
3533 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
3534 root->appendNewControlValue(proc, Return, Origin(), floatResult);
3535
3536 double doubleA = a;
3537 double doubleB = b;
3538 float expected = static_cast<float>(bitOrDouble(doubleA, doubleB));
3539 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
3540}
3541
3542void testBitXorArgs(int64_t a, int64_t b)
3543{
3544 Procedure proc;
3545 BasicBlock* root = proc.addBlock();
3546 root->appendNewControlValue(
3547 proc, Return, Origin(),
3548 root->appendNew<Value>(
3549 proc, BitXor, Origin(),
3550 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3551 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3552
3553 CHECK(compileAndRun<int64_t>(proc, a, b) == (a ^ b));
3554}
3555
3556void testBitXorSameArg(int64_t a)
3557{
3558 Procedure proc;
3559 BasicBlock* root = proc.addBlock();
3560 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3561 root->appendNewControlValue(
3562 proc, Return, Origin(),
3563 root->appendNew<Value>(
3564 proc, BitXor, Origin(),
3565 argument,
3566 argument));
3567
3568 CHECK(!compileAndRun<int64_t>(proc, a));
3569}
3570
3571void testBitXorAndAndArgs(int64_t a, int64_t b, int64_t c)
3572{
3573 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3574 // ((a & b) ^ (a & c))
3575 // ((a & b) ^ (c & a))
3576 // ((b & a) ^ (a & c))
3577 // ((b & a) ^ (c & a))
3578 for (int i = 0; i < 4; ++i) {
3579 Procedure proc;
3580 BasicBlock* root = proc.addBlock();
3581 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3582 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3583 Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
3584 Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3585 : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3586 Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
3587 : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
3588 root->appendNewControlValue(
3589 proc, Return, Origin(),
3590 root->appendNew<Value>(
3591 proc, BitXor, Origin(),
3592 andAB,
3593 andAC));
3594
3595 CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a & b) ^ (a & c)));
3596 }
3597}
3598
3599void testBitXorAndSameArgs(int64_t a, int64_t b)
3600{
3601 // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
3602 // ((a & b) ^ a)
3603 // ((b & a) ^ a)
3604 // (a ^ (a & b))
3605 // (a ^ (b & a))
3606 for (int i = 0; i < 4; ++i) {
3607 Procedure proc;
3608 BasicBlock* root = proc.addBlock();
3609 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3610 Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
3611 Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
3612 : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
3613 Value* result = i & 2 ? root->appendNew<Value>(proc, BitXor, Origin(), andAB, argA)
3614 : root->appendNew<Value>(proc, BitXor, Origin(), argA, andAB);
3615 root->appendNewControlValue(proc, Return, Origin(), result);
3616
3617 CHECK_EQ(compileAndRun<int64_t>(proc, a, b), ((a & b) ^ a));
3618 }
3619}
3620
3621void testBitXorImms(int64_t a, int64_t b)
3622{
3623 Procedure proc;
3624 BasicBlock* root = proc.addBlock();
3625 root->appendNewControlValue(
3626 proc, Return, Origin(),
3627 root->appendNew<Value>(
3628 proc, BitXor, Origin(),
3629 root->appendNew<Const64Value>(proc, Origin(), a),
3630 root->appendNew<Const64Value>(proc, Origin(), b)));
3631
3632 CHECK(compileAndRun<int64_t>(proc) == (a ^ b));
3633}
3634
3635void testBitXorArgImm(int64_t a, int64_t b)
3636{
3637 Procedure proc;
3638 BasicBlock* root = proc.addBlock();
3639 root->appendNewControlValue(
3640 proc, Return, Origin(),
3641 root->appendNew<Value>(
3642 proc, BitXor, Origin(),
3643 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3644 root->appendNew<Const64Value>(proc, Origin(), b)));
3645
3646 CHECK(compileAndRun<int64_t>(proc, a) == (a ^ b));
3647}
3648
3649void testBitXorImmArg(int64_t a, int64_t b)
3650{
3651 Procedure proc;
3652 BasicBlock* root = proc.addBlock();
3653 root->appendNewControlValue(
3654 proc, Return, Origin(),
3655 root->appendNew<Value>(
3656 proc, BitXor, Origin(),
3657 root->appendNew<Const64Value>(proc, Origin(), a),
3658 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3659
3660 CHECK(compileAndRun<int64_t>(proc, b) == (a ^ b));
3661}
3662
3663void testBitXorBitXorArgImmImm(int64_t a, int64_t b, int64_t c)
3664{
3665 Procedure proc;
3666 BasicBlock* root = proc.addBlock();
3667 Value* innerBitXor = root->appendNew<Value>(
3668 proc, BitXor, Origin(),
3669 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3670 root->appendNew<Const64Value>(proc, Origin(), b));
3671 root->appendNewControlValue(
3672 proc, Return, Origin(),
3673 root->appendNew<Value>(
3674 proc, BitXor, Origin(),
3675 innerBitXor,
3676 root->appendNew<Const64Value>(proc, Origin(), c)));
3677
3678 CHECK(compileAndRun<int64_t>(proc, a) == ((a ^ b) ^ c));
3679}
3680
3681void testBitXorImmBitXorArgImm(int64_t a, int64_t b, int64_t c)
3682{
3683 Procedure proc;
3684 BasicBlock* root = proc.addBlock();
3685 Value* innerBitXor = root->appendNew<Value>(
3686 proc, BitXor, Origin(),
3687 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3688 root->appendNew<Const64Value>(proc, Origin(), c));
3689 root->appendNewControlValue(
3690 proc, Return, Origin(),
3691 root->appendNew<Value>(
3692 proc, BitXor, Origin(),
3693 root->appendNew<Const64Value>(proc, Origin(), a),
3694 innerBitXor));
3695
3696 CHECK(compileAndRun<int64_t>(proc, b) == (a ^ (b ^ c)));
3697}
3698
3699void testBitXorArgs32(int a, int b)
3700{
3701 Procedure proc;
3702 BasicBlock* root = proc.addBlock();
3703 root->appendNewControlValue(
3704 proc, Return, Origin(),
3705 root->appendNew<Value>(
3706 proc, BitXor, Origin(),
3707 root->appendNew<Value>(
3708 proc, Trunc, Origin(),
3709 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3710 root->appendNew<Value>(
3711 proc, Trunc, Origin(),
3712 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3713
3714 CHECK(compileAndRun<int>(proc, a, b) == (a ^ b));
3715}
3716
3717void testBitXorSameArg32(int a)
3718{
3719 Procedure proc;
3720 BasicBlock* root = proc.addBlock();
3721 Value* argument = root->appendNew<Value>(
3722 proc, Trunc, Origin(),
3723 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3724 root->appendNewControlValue(
3725 proc, Return, Origin(),
3726 root->appendNew<Value>(
3727 proc, BitXor, Origin(),
3728 argument,
3729 argument));
3730
3731 CHECK(!compileAndRun<int>(proc, a));
3732}
3733
3734void testBitXorImms32(int a, int b)
3735{
3736 Procedure proc;
3737 BasicBlock* root = proc.addBlock();
3738 root->appendNewControlValue(
3739 proc, Return, Origin(),
3740 root->appendNew<Value>(
3741 proc, BitXor, Origin(),
3742 root->appendNew<Const32Value>(proc, Origin(), a),
3743 root->appendNew<Const32Value>(proc, Origin(), b)));
3744
3745 CHECK(compileAndRun<int>(proc) == (a ^ b));
3746}
3747
3748void testBitXorArgImm32(int a, int b)
3749{
3750 Procedure proc;
3751 BasicBlock* root = proc.addBlock();
3752 root->appendNewControlValue(
3753 proc, Return, Origin(),
3754 root->appendNew<Value>(
3755 proc, BitXor, Origin(),
3756 root->appendNew<Value>(
3757 proc, Trunc, Origin(),
3758 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3759 root->appendNew<Const32Value>(proc, Origin(), b)));
3760
3761 CHECK(compileAndRun<int>(proc, a) == (a ^ b));
3762}
3763
3764void testBitXorImmArg32(int a, int b)
3765{
3766 Procedure proc;
3767 BasicBlock* root = proc.addBlock();
3768 root->appendNewControlValue(
3769 proc, Return, Origin(),
3770 root->appendNew<Value>(
3771 proc, BitXor, Origin(),
3772 root->appendNew<Const32Value>(proc, Origin(), a),
3773 root->appendNew<Value>(
3774 proc, Trunc, Origin(),
3775 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3776
3777 CHECK(compileAndRun<int>(proc, b) == (a ^ b));
3778}
3779
3780void testBitXorBitXorArgImmImm32(int a, int b, int c)
3781{
3782 Procedure proc;
3783 BasicBlock* root = proc.addBlock();
3784 Value* innerBitXor = root->appendNew<Value>(
3785 proc, BitXor, Origin(),
3786 root->appendNew<Value>(
3787 proc, Trunc, Origin(),
3788 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3789 root->appendNew<Const32Value>(proc, Origin(), b));
3790 root->appendNewControlValue(
3791 proc, Return, Origin(),
3792 root->appendNew<Value>(
3793 proc, BitXor, Origin(),
3794 innerBitXor,
3795 root->appendNew<Const32Value>(proc, Origin(), c)));
3796
3797 CHECK(compileAndRun<int>(proc, a) == ((a ^ b) ^ c));
3798}
3799
3800void testBitXorImmBitXorArgImm32(int a, int b, int c)
3801{
3802 Procedure proc;
3803 BasicBlock* root = proc.addBlock();
3804 Value* innerBitXor = root->appendNew<Value>(
3805 proc, BitXor, Origin(),
3806 root->appendNew<Value>(
3807 proc, Trunc, Origin(),
3808 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3809 root->appendNew<Const32Value>(proc, Origin(), c));
3810 root->appendNewControlValue(
3811 proc, Return, Origin(),
3812 root->appendNew<Value>(
3813 proc, BitXor, Origin(),
3814 root->appendNew<Const32Value>(proc, Origin(), a),
3815 innerBitXor));
3816
3817 CHECK(compileAndRun<int>(proc, b) == (a ^ (b ^ c)));
3818}
3819
3820void testBitNotArg(int64_t a)
3821{
3822 Procedure proc;
3823 BasicBlock* root = proc.addBlock();
3824 root->appendNewControlValue(
3825 proc, Return, Origin(),
3826 root->appendNew<Value>(
3827 proc, BitXor, Origin(),
3828 root->appendNew<Const64Value>(proc, Origin(), -1),
3829 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3830
3831 CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3832}
3833
3834void testBitNotImm(int64_t a)
3835{
3836 Procedure proc;
3837 BasicBlock* root = proc.addBlock();
3838 root->appendNewControlValue(
3839 proc, Return, Origin(),
3840 root->appendNew<Value>(
3841 proc, BitXor, Origin(),
3842 root->appendNew<Const64Value>(proc, Origin(), -1),
3843 root->appendNew<Const64Value>(proc, Origin(), a)));
3844
3845 CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3846}
3847
3848void testBitNotMem(int64_t a)
3849{
3850 Procedure proc;
3851 BasicBlock* root = proc.addBlock();
3852 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3853 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
3854 Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
3855 root->appendNew<Const64Value>(proc, Origin(), -1),
3856 load);
3857 root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
3858 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3859
3860 int64_t input = a;
3861 compileAndRun<int32_t>(proc, &input);
3862 CHECK(isIdentical(input, static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3863}
3864
3865void testBitNotArg32(int32_t a)
3866{
3867 Procedure proc;
3868 BasicBlock* root = proc.addBlock();
3869 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
3870 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3871 root->appendNewControlValue(
3872 proc, Return, Origin(),
3873 root->appendNew<Value>(proc, BitXor, Origin(),
3874 root->appendNew<Const32Value>(proc, Origin(), -1),
3875 argument));
3876 CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3877}
3878
3879void testBitNotImm32(int32_t a)
3880{
3881 Procedure proc;
3882 BasicBlock* root = proc.addBlock();
3883 root->appendNewControlValue(
3884 proc, Return, Origin(),
3885 root->appendNew<Value>(
3886 proc, BitXor, Origin(),
3887 root->appendNew<Const32Value>(proc, Origin(), -1),
3888 root->appendNew<Const32Value>(proc, Origin(), a)));
3889
3890 CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3891}
3892
3893void testBitNotMem32(int32_t a)
3894{
3895 Procedure proc;
3896 BasicBlock* root = proc.addBlock();
3897 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3898 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
3899 Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
3900 root->appendNew<Const32Value>(proc, Origin(), -1),
3901 load);
3902 root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
3903 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3904
3905 int32_t input = a;
3906 compileAndRun<int32_t>(proc, &input);
3907 CHECK(isIdentical(input, static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3908}
3909
3910void testNotOnBooleanAndBranch32(int64_t a, int64_t b)
3911{
3912 Procedure proc;
3913 BasicBlock* root = proc.addBlock();
3914 BasicBlock* thenCase = proc.addBlock();
3915 BasicBlock* elseCase = proc.addBlock();
3916
3917 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
3918 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3919 Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
3920 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3921 Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2);
3922 Value* argsAreNotEqual = root->appendNew<Value>(proc, BitXor, Origin(),
3923 root->appendNew<Const32Value>(proc, Origin(), 1),
3924 argsAreEqual);
3925
3926 root->appendNewControlValue(
3927 proc, Branch, Origin(),
3928 argsAreNotEqual,
3929 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
3930
3931 thenCase->appendNewControlValue(
3932 proc, Return, Origin(),
3933 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
3934
3935 elseCase->appendNewControlValue(
3936 proc, Return, Origin(),
3937 elseCase->appendNew<Const32Value>(proc, Origin(), -42));
3938
3939 int32_t expectedValue = (a != b) ? 42 : -42;
3940 CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue);
3941}
3942
3943void testBitNotOnBooleanAndBranch32(int64_t a, int64_t b)
3944{
3945 Procedure proc;
3946 BasicBlock* root = proc.addBlock();
3947 BasicBlock* thenCase = proc.addBlock();
3948 BasicBlock* elseCase = proc.addBlock();
3949
3950 Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
3951 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3952 Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
3953 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3954 Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2);
3955 Value* bitNotArgsAreEqual = root->appendNew<Value>(proc, BitXor, Origin(),
3956 root->appendNew<Const32Value>(proc, Origin(), -1),
3957 argsAreEqual);
3958
3959 root->appendNewControlValue(proc, Branch, Origin(),
3960 bitNotArgsAreEqual, FrequentedBlock(thenCase), FrequentedBlock(elseCase));
3961
3962 thenCase->appendNewControlValue(proc, Return, Origin(),
3963 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
3964
3965 elseCase->appendNewControlValue(proc, Return, Origin(),
3966 elseCase->appendNew<Const32Value>(proc, Origin(), -42));
3967
3968 static constexpr int32_t expectedValue = 42;
3969 CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue);
3970}
3971
3972void testShlArgs(int64_t a, int64_t b)
3973{
3974 Procedure proc;
3975 BasicBlock* root = proc.addBlock();
3976 root->appendNewControlValue(
3977 proc, Return, Origin(),
3978 root->appendNew<Value>(
3979 proc, Shl, Origin(),
3980 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3981 root->appendNew<Value>(
3982 proc, Trunc, Origin(),
3983 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3984
3985 CHECK(compileAndRun<int64_t>(proc, a, b) == (a << b));
3986}
3987
3988void testShlImms(int64_t a, int64_t b)
3989{
3990 Procedure proc;
3991 BasicBlock* root = proc.addBlock();
3992 root->appendNewControlValue(
3993 proc, Return, Origin(),
3994 root->appendNew<Value>(
3995 proc, Shl, Origin(),
3996 root->appendNew<Const64Value>(proc, Origin(), a),
3997 root->appendNew<Const32Value>(proc, Origin(), b)));
3998
3999 b = b & 0x3f; // to avoid undefined behaviour below
4000 CHECK(compileAndRun<int64_t>(proc) == (a << b));
4001}
4002
4003void testShlArgImm(int64_t a, int64_t b)
4004{
4005 Procedure proc;
4006 BasicBlock* root = proc.addBlock();
4007 root->appendNewControlValue(
4008 proc, Return, Origin(),
4009 root->appendNew<Value>(
4010 proc, Shl, Origin(),
4011 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
4012 root->appendNew<Const32Value>(proc, Origin(), b)));
4013
4014 b = b & 0x3f; // to avoid undefined behaviour below
4015 CHECK(compileAndRun<int64_t>(proc, a) == (a << b));
4016}
4017
4018void testShlSShrArgImm(int64_t a, int64_t b)
4019{
4020 Procedure proc;
4021 BasicBlock* root = proc.addBlock();
4022 Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4023 Value* constB = root->appendNew<Const32Value>(proc, Origin(), b);
4024 Value* innerShift = root->appendNew<Value>(proc, SShr, Origin(), argA, constB);
4025 root->appendNewControlValue(
4026 proc, Return, Origin(),
4027 root->appendNew<Value>(
4028 proc, Shl, Origin(),
4029 innerShift,
4030 constB));
4031
4032 b = b & 0x3f; // to avoid undefined behaviour below
4033 CHECK(compileAndRun<int64_t>(proc, a) == ((a >> b) << b));
4034}
4035
4036void testShlArg32(int32_t a)
4037{
4038 Procedure proc;
4039 BasicBlock* root = proc.addBlock();
4040 Value* value = root->appendNew<Value>(
4041 proc, Trunc, Origin(),
4042 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4043 root->appendNewControlValue(
4044 proc, Return, Origin(),
4045 root->appendNew<Value>(proc, Shl, Origin(), value, value));
4046
4047 CHECK(compileAndRun<int32_t>(proc, a) == (a << a));
4048}
4049
4050void testShlArgs32(int32_t a, int32_t b)
4051{
4052 Procedure proc;
4053 BasicBlock* root = proc.addBlock();
4054 root->appendNewControlValue(
4055 proc, Return, Origin(),
4056 root->appendNew<Value>(
4057 proc, Shl, Origin(),
4058 root->appendNew<Value>(
4059 proc, Trunc, Origin(),
4060 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
4061 root->appendNew<Value>(
4062 proc, Trunc, Origin(),
4063 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
4064
4065 CHECK(compileAndRun<int32_t>(proc, a, b) == (a << b));
4066}
4067
4068void testShlImms32(int32_t a, int32_t b)
4069{
4070 Procedure proc;
4071 BasicBlock* root = proc.addBlock();
4072 root->appendNewControlValue(
4073 proc, Return, Origin(),
4074 root->appendNew<Value>(
4075 proc, Shl, Origin(),
4076 root->appendNew<Const32Value>(proc, Origin(), a),
4077 root->appendNew<Const32Value>(proc, Origin(), b)));
4078
4079 b = b & 0x1f; // to avoid undefined behaviour below
4080 CHECK(compileAndRun<int32_t>(proc) == (a << b));
4081}
4082
4083void testShlArgImm32(int32_t a, int32_t b)
4084{
4085 Procedure proc;
4086 BasicBlock* root = proc.addBlock();
4087 root->appendNewControlValue(
4088 proc, Return, Origin(),
4089 root->appendNew<Value>(
4090 proc, Shl, Origin(),
4091 root->appendNew<Value>(
4092 proc, Trunc, Origin(),
4093 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
4094 root->appendNew<Const32Value>(proc, Origin(), b)));
4095
4096 b = b & 0x1f; // to avoid undefined behaviour below
4097 CHECK(compileAndRun<int32_t>(proc, a) == (a << b));
4098}
4099
4100void testShlZShrArgImm32(int32_t a, int32_t b)
4101{
4102 Procedure proc;
4103 BasicBlock* root = proc.addBlock();
4104 Value* argA = root->appendNew<Value>(
4105 proc, Trunc, Origin(),
4106 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4107 Value* constB = root->appendNew<Const32Value>(proc, Origin(), b);
4108 Value* innerShift = root->appendNew<Value>(proc, ZShr, Origin(), argA, constB);
4109 root->appendNewControlValue(
4110 proc, Return, Origin(),
4111 root->appendNew<Value>(
4112 proc, Shl, Origin(),
4113 innerShift,
4114 constB));
4115
4116 b = b & 0x1f; // to avoid undefined behaviour below
4117 CHECK(compileAndRun<int32_t>(proc, a) == static_cast<int32_t>((static_cast<uint32_t>(a) >> b) << b));
4118}
4119
4120void testSShrArgs(int64_t a, int64_t b)
4121{
4122 Procedure proc;
4123 BasicBlock* root = proc.addBlock();
4124 root->appendNewControlValue(
4125 proc, Return, Origin(),
4126 root->appendNew<Value>(
4127 proc, SShr, Origin(),
4128 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
4129 root->appendNew<Value>(
4130 proc, Trunc, Origin(),
4131 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
4132
4133 CHECK(compileAndRun<int64_t>(proc, a, b) == (a >> b));
4134}
4135
4136void testSShrImms(int64_t a, int64_t b)
4137{
4138 Procedure proc;
4139 BasicBlock* root = proc.addBlock();
4140 root->appendNewControlValue(
4141 proc, Return, Origin(),
4142 root->appendNew<Value>(
4143 proc, SShr, Origin(),
4144 root->appendNew<Const64Value>(proc, Origin(), a),
4145 root->appendNew<Const32Value>(proc, Origin(), b)));
4146
4147 CHECK(compileAndRun<int64_t>(proc) == (a >> b));
4148}
4149
4150void testSShrArgImm(int64_t a, int64_t b)
4151{
4152 Procedure proc;
4153 BasicBlock* root = proc.addBlock();
4154 root->appendNewControlValue(
4155 proc, Return, Origin(),
4156 root->appendNew<Value>(
4157 proc, SShr, Origin(),
4158 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
4159 root->appendNew<Const32Value>(proc, Origin(), b)));
4160
4161 CHECK(compileAndRun<int64_t>(proc, a) == (a >> b));
4162}
4163
4164void testSShrArg32(int32_t a)
4165{
4166 Procedure proc;
4167 BasicBlock* root = proc.addBlock();
4168 Value* value = root->appendNew<Value>(
4169 proc, Trunc, Origin(),
4170 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4171 root->appendNewControlValue(
4172 proc, Return, Origin(),
4173 root->appendNew<Value>(proc, SShr, Origin(), value, value));
4174
4175 CHECK(compileAndRun<int32_t>(proc, a) == (a >> (a & 31)));
4176}
4177
4178void testSShrArgs32(int32_t a, int32_t b)
4179{
4180 Procedure proc;
4181 BasicBlock* root = proc.addBlock();
4182 root->appendNewControlValue(
4183 proc, Return, Origin(),
4184 root->appendNew<Value>(
4185 proc, SShr, Origin(),
4186 root->appendNew<Value>(
4187 proc, Trunc, Origin(),
4188 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
4189 root->appendNew<Value>(
4190 proc, Trunc, Origin(),
4191 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
4192
4193 CHECK(compileAndRun<int32_t>(proc, a, b) == (a >> b));
4194}
4195
4196void testSShrImms32(int32_t a, int32_t b)
4197{
4198 Procedure proc;
4199 BasicBlock* root = proc.addBlock();
4200 root->appendNewControlValue(
4201 proc, Return, Origin(),
4202 root->appendNew<Value>(
4203 proc, SShr, Origin(),
4204 root->appendNew<Const32Value>(proc, Origin(), a),
4205 root->appendNew<Const32Value>(proc, Origin(), b)));
4206
4207 CHECK(compileAndRun<int32_t>(proc) == (a >> b));
4208}
4209
4210void testSShrArgImm32(int32_t a, int32_t b)
4211{
4212 Procedure proc;
4213 BasicBlock* root = proc.addBlock();
4214 root->appendNewControlValue(
4215 proc, Return, Origin(),
4216 root->appendNew<Value>(
4217 proc, SShr, Origin(),
4218 root->appendNew<Value>(
4219 proc, Trunc, Origin(),
4220 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
4221 root->appendNew<Const32Value>(proc, Origin(), b)));
4222
4223 CHECK(compileAndRun<int32_t>(proc, a) == (a >> b));
4224}
4225
4226void testZShrArgs(uint64_t a, uint64_t b)
4227{
4228 Procedure proc;
4229 BasicBlock* root = proc.addBlock();
4230 root->appendNewControlValue(
4231 proc, Return, Origin(),
4232 root->appendNew<Value>(
4233 proc, ZShr, Origin(),
4234 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
4235 root->appendNew<Value>(
4236 proc, Trunc, Origin(),
4237 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
4238
4239 CHECK(compileAndRun<uint64_t>(proc, a, b) == (a >> b));
4240}
4241
4242void testZShrImms(uint64_t a, uint64_t b)
4243{
4244 Procedure proc;
4245 BasicBlock* root = proc.addBlock();
4246 root->appendNewControlValue(
4247 proc, Return, Origin(),
4248 root->appendNew<Value>(
4249 proc, ZShr, Origin(),
4250 root->appendNew<Const64Value>(proc, Origin(), a),
4251 root->appendNew<Const32Value>(proc, Origin(), b)));
4252
4253 CHECK(compileAndRun<uint64_t>(proc) == (a >> b));
4254}
4255
4256void testZShrArgImm(uint64_t a, uint64_t b)
4257{
4258 Procedure proc;
4259 BasicBlock* root = proc.addBlock();
4260 root->appendNewControlValue(
4261 proc, Return, Origin(),
4262 root->appendNew<Value>(
4263 proc, ZShr, Origin(),
4264 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
4265 root->appendNew<Const32Value>(proc, Origin(), b)));
4266
4267 CHECK(compileAndRun<uint64_t>(proc, a) == (a >> b));
4268}
4269
4270void testZShrArg32(uint32_t a)
4271{
4272 Procedure proc;
4273 BasicBlock* root = proc.addBlock();
4274 Value* value = root->appendNew<Value>(
4275 proc, Trunc, Origin(),
4276 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4277 root->appendNewControlValue(
4278 proc, Return, Origin(),
4279 root->appendNew<Value>(proc, ZShr, Origin(), value, value));
4280
4281 CHECK(compileAndRun<uint32_t>(proc, a) == (a >> (a & 31)));
4282}
4283
4284void testZShrArgs32(uint32_t a, uint32_t b)
4285{
4286 Procedure proc;
4287 BasicBlock* root = proc.addBlock();
4288 root->appendNewControlValue(
4289 proc, Return, Origin(),
4290 root->appendNew<Value>(
4291 proc, ZShr, Origin(),
4292 root->appendNew<Value>(
4293 proc, Trunc, Origin(),
4294 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
4295 root->appendNew<Value>(
4296 proc, Trunc, Origin(),
4297 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
4298
4299 CHECK(compileAndRun<uint32_t>(proc, a, b) == (a >> b));
4300}
4301
4302void testZShrImms32(uint32_t a, uint32_t b)
4303{
4304 Procedure proc;
4305 BasicBlock* root = proc.addBlock();
4306 root->appendNewControlValue(
4307 proc, Return, Origin(),
4308 root->appendNew<Value>(
4309 proc, ZShr, Origin(),
4310 root->appendNew<Const32Value>(proc, Origin(), a),
4311 root->appendNew<Const32Value>(proc, Origin(), b)));
4312
4313 CHECK(compileAndRun<uint32_t>(proc) == (a >> b));
4314}
4315
4316void testZShrArgImm32(uint32_t a, uint32_t b)
4317{
4318 Procedure proc;
4319 BasicBlock* root = proc.addBlock();
4320 root->appendNewControlValue(
4321 proc, Return, Origin(),
4322 root->appendNew<Value>(
4323 proc, ZShr, Origin(),
4324 root->appendNew<Value>(
4325 proc, Trunc, Origin(),
4326 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
4327 root->appendNew<Const32Value>(proc, Origin(), b)));
4328
4329 CHECK(compileAndRun<uint32_t>(proc, a) == (a >> b));
4330}
4331
4332template<typename IntegerType>
4333static unsigned countLeadingZero(IntegerType value)
4334{
4335 unsigned bitCount = sizeof(IntegerType) * 8;
4336 if (!value)
4337 return bitCount;
4338
4339 unsigned counter = 0;
4340 while (!(static_cast<uint64_t>(value) & (1l << (bitCount - 1)))) {
4341 value <<= 1;
4342 ++counter;
4343 }
4344 return counter;
4345}
4346
4347void testClzArg64(int64_t a)
4348{
4349 Procedure proc;
4350 BasicBlock* root = proc.addBlock();
4351 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4352 Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument);
4353 root->appendNewControlValue(proc, Return, Origin(), clzValue);
4354 CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a));
4355}
4356
4357void testClzMem64(int64_t a)
4358{
4359 Procedure proc;
4360 BasicBlock* root = proc.addBlock();
4361 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4362 MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
4363 Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value);
4364 root->appendNewControlValue(proc, Return, Origin(), clzValue);
4365 CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
4366}
4367
4368void testClzArg32(int32_t a)
4369{
4370 Procedure proc;
4371 BasicBlock* root = proc.addBlock();
4372 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
4373 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4374 Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument);
4375 root->appendNewControlValue(proc, Return, Origin(), clzValue);
4376 CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a));
4377}
4378
4379void testClzMem32(int32_t a)
4380{
4381 Procedure proc;
4382 BasicBlock* root = proc.addBlock();
4383 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4384 MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
4385 Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value);
4386 root->appendNewControlValue(proc, Return, Origin(), clzValue);
4387 CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
4388}
4389
4390void testAbsArg(double a)
4391{
4392 Procedure proc;
4393 BasicBlock* root = proc.addBlock();
4394 root->appendNewControlValue(
4395 proc, Return, Origin(),
4396 root->appendNew<Value>(
4397 proc, Abs, Origin(),
4398 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
4399
4400 CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(a)));
4401}
4402
4403void testAbsImm(double a)
4404{
4405 Procedure proc;
4406 BasicBlock* root = proc.addBlock();
4407 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
4408 root->appendNewControlValue(
4409 proc, Return, Origin(),
4410 root->appendNew<Value>(proc, Abs, Origin(), argument));
4411
4412 CHECK(isIdentical(compileAndRun<double>(proc), fabs(a)));
4413}
4414
4415void testAbsMem(double a)
4416{
4417 Procedure proc;
4418 BasicBlock* root = proc.addBlock();
4419 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4420 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
4421 root->appendNewControlValue(
4422 proc, Return, Origin(),
4423 root->appendNew<Value>(proc, Abs, Origin(), loadDouble));
4424
4425 CHECK(isIdentical(compileAndRun<double>(proc, &a), fabs(a)));
4426}
4427
4428void testAbsAbsArg(double a)
4429{
4430 Procedure proc;
4431 BasicBlock* root = proc.addBlock();
4432 Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(),
4433 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
4434 Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs);
4435 root->appendNewControlValue(proc, Return, Origin(), secondAbs);
4436
4437 CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(fabs(a))));
4438}
4439
4440void testAbsNegArg(double a)
4441{
4442 Procedure proc;
4443 BasicBlock* root = proc.addBlock();
4444 Value* neg = root->appendNew<Value>(proc, Neg, Origin(),
4445 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
4446 Value* abs = root->appendNew<Value>(proc, Abs, Origin(), neg);
4447 root->appendNewControlValue(proc, Return, Origin(), abs);
4448
4449 CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(- a)));
4450}
4451
4452void testAbsBitwiseCastArg(double a)
4453{
4454 Procedure proc;
4455 BasicBlock* root = proc.addBlock();
4456 Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4457 Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64);
4458 Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble);
4459 root->appendNewControlValue(proc, Return, Origin(), absValue);
4460
4461 CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int64_t>(a)), fabs(a)));
4462}
4463
4464void testBitwiseCastAbsBitwiseCastArg(double a)
4465{
4466 Procedure proc;
4467 BasicBlock* root = proc.addBlock();
4468 Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4469 Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64);
4470 Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble);
4471 Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue);
4472
4473 root->appendNewControlValue(proc, Return, Origin(), resultAsInt64);
4474
4475 int64_t expectedResult = bitwise_cast<int64_t>(fabs(a));
4476 CHECK(isIdentical(compileAndRun<int64_t>(proc, bitwise_cast<int64_t>(a)), expectedResult));
4477}
4478
4479void testAbsArg(float a)
4480{
4481 Procedure proc;
4482 BasicBlock* root = proc.addBlock();
4483 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4484 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4485 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4486 Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument);
4487 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4488 root->appendNewControlValue(proc, Return, Origin(), result32);
4489
4490 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
4491}
4492
4493void testAbsImm(float a)
4494{
4495 Procedure proc;
4496 BasicBlock* root = proc.addBlock();
4497 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
4498 Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument);
4499 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4500 root->appendNewControlValue(proc, Return, Origin(), result32);
4501
4502 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
4503}
4504
4505void testAbsMem(float a)
4506{
4507 Procedure proc;
4508 BasicBlock* root = proc.addBlock();
4509 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4510 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
4511 Value* result = root->appendNew<Value>(proc, Abs, Origin(), loadFloat);
4512 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4513 root->appendNewControlValue(proc, Return, Origin(), result32);
4514
4515 CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
4516}
4517
4518void testAbsAbsArg(float a)
4519{
4520 Procedure proc;
4521 BasicBlock* root = proc.addBlock();
4522 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4523 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4524 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4525 Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(), argument);
4526 Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs);
4527 root->appendNewControlValue(proc, Return, Origin(), secondAbs);
4528
4529 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(fabs(a)))));
4530}
4531
4532void testAbsNegArg(float a)
4533{
4534 Procedure proc;
4535 BasicBlock* root = proc.addBlock();
4536 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4537 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4538 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4539 Value* neg = root->appendNew<Value>(proc, Neg, Origin(), argument);
4540 Value* abs = root->appendNew<Value>(proc, Abs, Origin(), neg);
4541 root->appendNewControlValue(proc, Return, Origin(), abs);
4542
4543 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(- a))));
4544}
4545
4546void testAbsBitwiseCastArg(float a)
4547{
4548 Procedure proc;
4549 BasicBlock* root = proc.addBlock();
4550 Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
4551 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4552 Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32);
4553 Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat);
4554 root->appendNewControlValue(proc, Return, Origin(), absValue);
4555
4556 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(a))));
4557}
4558
4559void testBitwiseCastAbsBitwiseCastArg(float a)
4560{
4561 Procedure proc;
4562 BasicBlock* root = proc.addBlock();
4563 Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
4564 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4565 Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32);
4566 Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat);
4567 Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue);
4568
4569 root->appendNewControlValue(proc, Return, Origin(), resultAsInt64);
4570
4571 int32_t expectedResult = bitwise_cast<int32_t>(static_cast<float>(fabs(a)));
4572 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), expectedResult));
4573}
4574
4575void testAbsArgWithUselessDoubleConversion(float a)
4576{
4577 Procedure proc;
4578 BasicBlock* root = proc.addBlock();
4579 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4580 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4581 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4582 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
4583 Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble);
4584 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
4585 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
4586 root->appendNewControlValue(proc, Return, Origin(), result32);
4587
4588 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
4589}
4590
4591void testAbsArgWithEffectfulDoubleConversion(float a)
4592{
4593 Procedure proc;
4594 BasicBlock* root = proc.addBlock();
4595 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4596 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4597 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4598 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
4599 Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble);
4600 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
4601 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
4602 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
4603 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
4604 root->appendNewControlValue(proc, Return, Origin(), result32);
4605
4606 double effect = 0;
4607 int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
4608 CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
4609 CHECK(isIdentical(effect, static_cast<double>(fabs(a))));
4610}
4611
4612void testCeilArg(double a)
4613{
4614 Procedure proc;
4615 BasicBlock* root = proc.addBlock();
4616 root->appendNewControlValue(
4617 proc, Return, Origin(),
4618 root->appendNew<Value>(
4619 proc, Ceil, Origin(),
4620 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
4621
4622 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
4623}
4624
4625void testCeilImm(double a)
4626{
4627 Procedure proc;
4628 BasicBlock* root = proc.addBlock();
4629 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
4630 root->appendNewControlValue(
4631 proc, Return, Origin(),
4632 root->appendNew<Value>(proc, Ceil, Origin(), argument));
4633
4634 CHECK(isIdentical(compileAndRun<double>(proc), ceil(a)));
4635}
4636
4637void testCeilMem(double a)
4638{
4639 Procedure proc;
4640 BasicBlock* root = proc.addBlock();
4641 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4642 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
4643 root->appendNewControlValue(
4644 proc, Return, Origin(),
4645 root->appendNew<Value>(proc, Ceil, Origin(), loadDouble));
4646
4647 CHECK(isIdentical(compileAndRun<double>(proc, &a), ceil(a)));
4648}
4649
4650void testCeilCeilArg(double a)
4651{
4652 Procedure proc;
4653 BasicBlock* root = proc.addBlock();
4654 Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(),
4655 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
4656 Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
4657 root->appendNewControlValue(proc, Return, Origin(), secondCeil);
4658
4659 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
4660}
4661
4662void testFloorCeilArg(double a)
4663{
4664 Procedure proc;
4665 BasicBlock* root = proc.addBlock();
4666 Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(),
4667 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
4668 Value* wrappingFloor = root->appendNew<Value>(proc, Floor, Origin(), firstCeil);
4669 root->appendNewControlValue(proc, Return, Origin(), wrappingFloor);
4670
4671 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
4672}
4673
4674void testCeilIToD64(int64_t a)
4675{
4676 Procedure proc;
4677 BasicBlock* root = proc.addBlock();
4678 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4679 Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
4680
4681 root->appendNewControlValue(
4682 proc, Return, Origin(),
4683 root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
4684
4685 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
4686}
4687
4688void testCeilIToD32(int64_t a)
4689{
4690 Procedure proc;
4691 BasicBlock* root = proc.addBlock();
4692 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
4693 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4694 Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
4695
4696 root->appendNewControlValue(
4697 proc, Return, Origin(),
4698 root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
4699
4700 CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
4701}
4702
4703void testCeilArg(float a)
4704{
4705 Procedure proc;
4706 BasicBlock* root = proc.addBlock();
4707 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4708 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4709 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4710 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
4711 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4712 root->appendNewControlValue(proc, Return, Origin(), result32);
4713
4714 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
4715}
4716
4717void testCeilImm(float a)
4718{
4719 Procedure proc;
4720 BasicBlock* root = proc.addBlock();
4721 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
4722 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
4723 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4724 root->appendNewControlValue(proc, Return, Origin(), result32);
4725
4726 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
4727}
4728
4729void testCeilMem(float a)
4730{
4731 Procedure proc;
4732 BasicBlock* root = proc.addBlock();
4733 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4734 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
4735 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), loadFloat);
4736 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4737 root->appendNewControlValue(proc, Return, Origin(), result32);
4738
4739 CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(ceilf(a))));
4740}
4741
4742void testCeilCeilArg(float a)
4743{
4744 Procedure proc;
4745 BasicBlock* root = proc.addBlock();
4746 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4747 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4748 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4749 Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument);
4750 Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
4751 root->appendNewControlValue(proc, Return, Origin(), secondCeil);
4752
4753 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a)));
4754}
4755
4756void testFloorCeilArg(float a)
4757{
4758 Procedure proc;
4759 BasicBlock* root = proc.addBlock();
4760 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4761 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4762 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4763 Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument);
4764 Value* wrappingFloor = root->appendNew<Value>(proc, Floor, Origin(), firstCeil);
4765 root->appendNewControlValue(proc, Return, Origin(), wrappingFloor);
4766
4767 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a)));
4768}
4769
4770void testCeilArgWithUselessDoubleConversion(float a)
4771{
4772 Procedure proc;
4773 BasicBlock* root = proc.addBlock();
4774 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4775 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4776 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4777 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
4778 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
4779 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
4780 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
4781 root->appendNewControlValue(proc, Return, Origin(), result32);
4782
4783 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
4784}
4785
4786void testCeilArgWithEffectfulDoubleConversion(float a)
4787{
4788 Procedure proc;
4789 BasicBlock* root = proc.addBlock();
4790 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4791 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4792 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4793 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
4794 Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
4795 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
4796 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
4797 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
4798 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
4799 root->appendNewControlValue(proc, Return, Origin(), result32);
4800
4801 double effect = 0;
4802 int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
4803 CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(ceilf(a))));
4804 CHECK(isIdentical(effect, static_cast<double>(ceilf(a))));
4805}
4806
4807void testFloorArg(double a)
4808{
4809 Procedure proc;
4810 BasicBlock* root = proc.addBlock();
4811 root->appendNewControlValue(
4812 proc, Return, Origin(),
4813 root->appendNew<Value>(
4814 proc, Floor, Origin(),
4815 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
4816
4817 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a)));
4818}
4819
4820void testFloorImm(double a)
4821{
4822 Procedure proc;
4823 BasicBlock* root = proc.addBlock();
4824 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
4825 root->appendNewControlValue(
4826 proc, Return, Origin(),
4827 root->appendNew<Value>(proc, Floor, Origin(), argument));
4828
4829 CHECK(isIdentical(compileAndRun<double>(proc), floor(a)));
4830}
4831
4832void testFloorMem(double a)
4833{
4834 Procedure proc;
4835 BasicBlock* root = proc.addBlock();
4836 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4837 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
4838 root->appendNewControlValue(
4839 proc, Return, Origin(),
4840 root->appendNew<Value>(proc, Floor, Origin(), loadDouble));
4841
4842 CHECK(isIdentical(compileAndRun<double>(proc, &a), floor(a)));
4843}
4844
4845void testFloorFloorArg(double a)
4846{
4847 Procedure proc;
4848 BasicBlock* root = proc.addBlock();
4849 Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(),
4850 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
4851 Value* secondFloor = root->appendNew<Value>(proc, Floor, Origin(), firstFloor);
4852 root->appendNewControlValue(proc, Return, Origin(), secondFloor);
4853
4854 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a)));
4855}
4856
4857void testCeilFloorArg(double a)
4858{
4859 Procedure proc;
4860 BasicBlock* root = proc.addBlock();
4861 Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(),
4862 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
4863 Value* wrappingCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstFloor);
4864 root->appendNewControlValue(proc, Return, Origin(), wrappingCeil);
4865
4866 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a)));
4867}
4868
4869void testFloorIToD64(int64_t a)
4870{
4871 Procedure proc;
4872 BasicBlock* root = proc.addBlock();
4873 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4874 Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
4875
4876 root->appendNewControlValue(
4877 proc, Return, Origin(),
4878 root->appendNew<Value>(proc, Floor, Origin(), argumentAsDouble));
4879
4880 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(static_cast<double>(a))));
4881}
4882
4883void testFloorIToD32(int64_t a)
4884{
4885 Procedure proc;
4886 BasicBlock* root = proc.addBlock();
4887 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
4888 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4889 Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
4890
4891 root->appendNewControlValue(
4892 proc, Return, Origin(),
4893 root->appendNew<Value>(proc, Floor, Origin(), argumentAsDouble));
4894
4895 CHECK(isIdentical(compileAndRun<double>(proc, a), floor(static_cast<double>(a))));
4896}
4897
4898void testFloorArg(float a)
4899{
4900 Procedure proc;
4901 BasicBlock* root = proc.addBlock();
4902 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4903 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4904 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4905 Value* result = root->appendNew<Value>(proc, Floor, Origin(), argument);
4906 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4907 root->appendNewControlValue(proc, Return, Origin(), result32);
4908
4909 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a))));
4910}
4911
4912void testFloorImm(float a)
4913{
4914 Procedure proc;
4915 BasicBlock* root = proc.addBlock();
4916 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
4917 Value* result = root->appendNew<Value>(proc, Floor, Origin(), argument);
4918 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4919 root->appendNewControlValue(proc, Return, Origin(), result32);
4920
4921 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a))));
4922}
4923
4924void testFloorMem(float a)
4925{
4926 Procedure proc;
4927 BasicBlock* root = proc.addBlock();
4928 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
4929 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
4930 Value* result = root->appendNew<Value>(proc, Floor, Origin(), loadFloat);
4931 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
4932 root->appendNewControlValue(proc, Return, Origin(), result32);
4933
4934 CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(floorf(a))));
4935}
4936
4937void testFloorFloorArg(float a)
4938{
4939 Procedure proc;
4940 BasicBlock* root = proc.addBlock();
4941 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4942 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4943 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4944 Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(), argument);
4945 Value* secondFloor = root->appendNew<Value>(proc, Floor, Origin(), firstFloor);
4946 root->appendNewControlValue(proc, Return, Origin(), secondFloor);
4947
4948 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), floorf(a)));
4949}
4950
4951void testCeilFloorArg(float a)
4952{
4953 Procedure proc;
4954 BasicBlock* root = proc.addBlock();
4955 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4956 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4957 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4958 Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(), argument);
4959 Value* wrappingCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstFloor);
4960 root->appendNewControlValue(proc, Return, Origin(), wrappingCeil);
4961
4962 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), floorf(a)));
4963}
4964
4965void testFloorArgWithUselessDoubleConversion(float a)
4966{
4967 Procedure proc;
4968 BasicBlock* root = proc.addBlock();
4969 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4970 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4971 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4972 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
4973 Value* result = root->appendNew<Value>(proc, Floor, Origin(), asDouble);
4974 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
4975 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
4976 root->appendNewControlValue(proc, Return, Origin(), result32);
4977
4978 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a))));
4979}
4980
4981void testFloorArgWithEffectfulDoubleConversion(float a)
4982{
4983 Procedure proc;
4984 BasicBlock* root = proc.addBlock();
4985 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
4986 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
4987 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
4988 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
4989 Value* result = root->appendNew<Value>(proc, Floor, Origin(), asDouble);
4990 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
4991 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
4992 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
4993 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
4994 root->appendNewControlValue(proc, Return, Origin(), result32);
4995
4996 double effect = 0;
4997 int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
4998 CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(floorf(a))));
4999 CHECK(isIdentical(effect, static_cast<double>(floorf(a))));
5000}
5001
5002double correctSqrt(double value)
5003{
5004#if CPU(X86) || CPU(X86_64)
5005 double result;
5006 asm ("sqrtsd %1, %0" : "=x"(result) : "x"(value));
5007 return result;
5008#else
5009 return sqrt(value);
5010#endif
5011}
5012
5013void testSqrtArg(double a)
5014{
5015 Procedure proc;
5016 BasicBlock* root = proc.addBlock();
5017 root->appendNewControlValue(
5018 proc, Return, Origin(),
5019 root->appendNew<Value>(
5020 proc, Sqrt, Origin(),
5021 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
5022
5023 CHECK(isIdentical(compileAndRun<double>(proc, a), correctSqrt(a)));
5024}
5025
5026void testSqrtImm(double a)
5027{
5028 Procedure proc;
5029 BasicBlock* root = proc.addBlock();
5030 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
5031 root->appendNewControlValue(
5032 proc, Return, Origin(),
5033 root->appendNew<Value>(proc, Sqrt, Origin(), argument));
5034
5035 CHECK(isIdentical(compileAndRun<double>(proc), correctSqrt(a)));
5036}
5037
5038void testSqrtMem(double a)
5039{
5040 Procedure proc;
5041 BasicBlock* root = proc.addBlock();
5042 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5043 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
5044 root->appendNewControlValue(
5045 proc, Return, Origin(),
5046 root->appendNew<Value>(proc, Sqrt, Origin(), loadDouble));
5047
5048 CHECK(isIdentical(compileAndRun<double>(proc, &a), correctSqrt(a)));
5049}
5050
5051void testSqrtArg(float a)
5052{
5053 Procedure proc;
5054 BasicBlock* root = proc.addBlock();
5055 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
5056 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5057 Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
5058 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), argument);
5059 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
5060 root->appendNewControlValue(proc, Return, Origin(), result32);
5061
5062 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
5063}
5064
5065void testSqrtImm(float a)
5066{
5067 Procedure proc;
5068 BasicBlock* root = proc.addBlock();
5069 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
5070 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), argument);
5071 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
5072 root->appendNewControlValue(proc, Return, Origin(), result32);
5073
5074 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
5075}
5076
5077void testSqrtMem(float a)
5078{
5079 Procedure proc;
5080 BasicBlock* root = proc.addBlock();
5081 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5082 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
5083 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), loadFloat);
5084 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
5085 root->appendNewControlValue(proc, Return, Origin(), result32);
5086
5087 CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
5088}
5089
5090void testSqrtArgWithUselessDoubleConversion(float a)
5091{
5092 Procedure proc;
5093 BasicBlock* root = proc.addBlock();
5094 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
5095 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5096 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
5097 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5098 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), asDouble);
5099 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
5100 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
5101 root->appendNewControlValue(proc, Return, Origin(), result32);
5102
5103 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
5104}
5105
5106void testSqrtArgWithEffectfulDoubleConversion(float a)
5107{
5108 Procedure proc;
5109 BasicBlock* root = proc.addBlock();
5110 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
5111 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5112 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
5113 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5114 Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), asDouble);
5115 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
5116 Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
5117 Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
5118 root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
5119 root->appendNewControlValue(proc, Return, Origin(), result32);
5120
5121 double effect = 0;
5122 int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
5123 CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(static_cast<float>(correctSqrt(a)))));
5124 double expected = static_cast<double>(correctSqrt(a));
5125 CHECK(isIdentical(effect, expected));
5126}
5127
5128void testCompareTwoFloatToDouble(float a, float b)
5129{
5130 Procedure proc;
5131 BasicBlock* root = proc.addBlock();
5132
5133 Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(),
5134 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5135 Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32);
5136 Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float);
5137
5138 Value* arg2As32 = root->appendNew<Value>(proc, Trunc, Origin(),
5139 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
5140 Value* arg2Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg2As32);
5141 Value* arg2AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg2Float);
5142 Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg1AsDouble, arg2AsDouble);
5143
5144 root->appendNewControlValue(proc, Return, Origin(), equal);
5145
5146 CHECK(compileAndRun<int64_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)) == (a == b));
5147}
5148
5149void testCompareOneFloatToDouble(float a, double b)
5150{
5151 Procedure proc;
5152 BasicBlock* root = proc.addBlock();
5153
5154 Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(),
5155 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5156 Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32);
5157 Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float);
5158
5159 Value* arg2AsDouble = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
5160 Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg1AsDouble, arg2AsDouble);
5161
5162 root->appendNewControlValue(proc, Return, Origin(), equal);
5163
5164 CHECK(compileAndRun<int64_t>(proc, bitwise_cast<int32_t>(a), b) == (a == b));
5165}
5166
5167void testCompareFloatToDoubleThroughPhi(float a, float b)
5168{
5169 Procedure proc;
5170 BasicBlock* root = proc.addBlock();
5171 BasicBlock* thenCase = proc.addBlock();
5172 BasicBlock* elseCase = proc.addBlock();
5173 BasicBlock* tail = proc.addBlock();
5174
5175 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5176
5177 Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(),
5178 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
5179 Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32);
5180 Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float);
5181
5182 Value* arg2AsDouble = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
5183 Value* arg2AsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), arg2AsDouble);
5184 Value* arg2AsFRoundedDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg2AsFloat);
5185
5186 root->appendNewControlValue(
5187 proc, Branch, Origin(),
5188 condition,
5189 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
5190
5191 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), arg1AsDouble);
5192 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5193
5194 Value* elseConst = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
5195 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), elseConst);
5196 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5197
5198 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
5199 thenValue->setPhi(doubleInput);
5200 elseValue->setPhi(doubleInput);
5201 Value* equal = tail->appendNew<Value>(proc, Equal, Origin(), doubleInput, arg2AsFRoundedDouble);
5202 tail->appendNewControlValue(proc, Return, Origin(), equal);
5203
5204 auto code = compileProc(proc);
5205 int32_t integerA = bitwise_cast<int32_t>(a);
5206 double doubleB = b;
5207 CHECK(invoke<int64_t>(*code, 1, integerA, doubleB) == (a == b));
5208 CHECK(invoke<int64_t>(*code, 0, integerA, doubleB) == (b == 0));
5209}
5210
5211void testDoubleToFloatThroughPhi(float value)
5212{
5213 // Simple case of:
5214 // if (a) {
5215 // x = DoubleAdd(a, b)
5216 // else
5217 // x = DoubleAdd(a, c)
5218 // DoubleToFloat(x)
5219 //
5220 // Both Adds can be converted to float add.
5221 Procedure proc;
5222 BasicBlock* root = proc.addBlock();
5223 BasicBlock* thenCase = proc.addBlock();
5224 BasicBlock* elseCase = proc.addBlock();
5225 BasicBlock* tail = proc.addBlock();
5226
5227 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5228 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
5229 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
5230 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
5231 Value* argAsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5232
5233 root->appendNewControlValue(
5234 proc, Branch, Origin(),
5235 condition,
5236 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
5237
5238 Value* postitiveConst = thenCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5f);
5239 Value* thenAdd = thenCase->appendNew<Value>(proc, Add, Origin(), argAsDouble, postitiveConst);
5240 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), thenAdd);
5241 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5242
5243 Value* elseConst = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), M_PI);
5244 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), elseConst);
5245 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5246
5247 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
5248 thenValue->setPhi(doubleInput);
5249 elseValue->setPhi(doubleInput);
5250 Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleInput);
5251 tail->appendNewControlValue(proc, Return, Origin(), floatResult);
5252
5253 auto code = compileProc(proc);
5254 CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + 42.5f));
5255 CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<float>(M_PI)));
5256}
5257
5258void testReduceFloatToDoubleValidates()
5259{
5260 // Simple case of:
5261 // f = DoubleToFloat(Bitcast(argGPR0))
5262 // if (a) {
5263 // x = FloatConst()
5264 // else
5265 // x = FloatConst()
5266 // p = Phi(x)
5267 // a = Mul(p, p)
5268 // b = Add(a, f)
5269 // c = Add(p, b)
5270 // Return(c)
5271 //
5272 // This should not crash in the validator after ReduceFloatToDouble.
5273 Procedure proc;
5274 BasicBlock* root = proc.addBlock();
5275 BasicBlock* thenCase = proc.addBlock();
5276 BasicBlock* elseCase = proc.addBlock();
5277 BasicBlock* tail = proc.addBlock();
5278
5279 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5280 Value* thingy = root->appendNew<Value>(proc, BitwiseCast, Origin(), condition);
5281 thingy = root->appendNew<Value>(proc, DoubleToFloat, Origin(), thingy); // Make the phase think it has work to do.
5282 root->appendNewControlValue(
5283 proc, Branch, Origin(),
5284 condition,
5285 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
5286
5287 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(),
5288 thenCase->appendNew<ConstFloatValue>(proc, Origin(), 11.5));
5289 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5290
5291 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(),
5292 elseCase->appendNew<ConstFloatValue>(proc, Origin(), 10.5));
5293 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5294
5295 Value* phi = tail->appendNew<Value>(proc, Phi, Float, Origin());
5296 thenValue->setPhi(phi);
5297 elseValue->setPhi(phi);
5298 Value* result = tail->appendNew<Value>(proc, Mul, Origin(),
5299 phi, phi);
5300 result = tail->appendNew<Value>(proc, Add, Origin(),
5301 result,
5302 thingy);
5303 result = tail->appendNew<Value>(proc, Add, Origin(),
5304 phi,
5305 result);
5306 tail->appendNewControlValue(proc, Return, Origin(), result);
5307
5308 auto code = compileProc(proc);
5309 CHECK(isIdentical(invoke<float>(*code, 1), 11.5f * 11.5f + static_cast<float>(bitwise_cast<double>(static_cast<uint64_t>(1))) + 11.5f));
5310 CHECK(isIdentical(invoke<float>(*code, 0), 10.5f * 10.5f + static_cast<float>(bitwise_cast<double>(static_cast<uint64_t>(0))) + 10.5f));
5311}
5312
5313void testDoubleProducerPhiToFloatConversion(float value)
5314{
5315 Procedure proc;
5316 BasicBlock* root = proc.addBlock();
5317 BasicBlock* thenCase = proc.addBlock();
5318 BasicBlock* elseCase = proc.addBlock();
5319 BasicBlock* tail = proc.addBlock();
5320
5321 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5322 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
5323 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
5324 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
5325
5326 root->appendNewControlValue(
5327 proc, Branch, Origin(),
5328 condition,
5329 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
5330
5331 Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5332 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble);
5333 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5334
5335 Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
5336 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble);
5337 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5338
5339 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
5340 thenValue->setPhi(doubleInput);
5341 elseValue->setPhi(doubleInput);
5342
5343 Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5344 Value* finalAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain);
5345 Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), finalAdd);
5346 tail->appendNewControlValue(proc, Return, Origin(), floatResult);
5347
5348 auto code = compileProc(proc);
5349 CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + value));
5350 CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), 42.5f + value));
5351}
5352
5353void testDoubleProducerPhiToFloatConversionWithDoubleConsumer(float value)
5354{
5355 // In this case, the Upsilon-Phi effectively contains a Float value, but it is used
5356 // as a Float and as a Double.
5357 Procedure proc;
5358 BasicBlock* root = proc.addBlock();
5359 BasicBlock* thenCase = proc.addBlock();
5360 BasicBlock* elseCase = proc.addBlock();
5361 BasicBlock* tail = proc.addBlock();
5362
5363 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5364 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
5365 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
5366 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
5367
5368 root->appendNewControlValue(
5369 proc, Branch, Origin(),
5370 condition,
5371 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
5372
5373 Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5374 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble);
5375 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5376
5377 Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
5378 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble);
5379 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5380
5381 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
5382 thenValue->setPhi(doubleInput);
5383 elseValue->setPhi(doubleInput);
5384
5385 Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5386 Value* floatAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain);
5387
5388 // FRound.
5389 Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), floatAdd);
5390 Value* doubleResult = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatResult);
5391
5392 // This one *cannot* be eliminated
5393 Value* doubleAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, doubleResult);
5394
5395 tail->appendNewControlValue(proc, Return, Origin(), doubleAdd);
5396
5397 auto code = compileProc(proc);
5398 CHECK(isIdentical(invoke<double>(*code, 1, bitwise_cast<int32_t>(value)), (value + value) + static_cast<double>(value)));
5399 CHECK(isIdentical(invoke<double>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<double>((42.5f + value) + 42.5f)));
5400}
5401
5402void testDoubleProducerPhiWithNonFloatConst(float value, double constValue)
5403{
5404 Procedure proc;
5405 BasicBlock* root = proc.addBlock();
5406 BasicBlock* thenCase = proc.addBlock();
5407 BasicBlock* elseCase = proc.addBlock();
5408 BasicBlock* tail = proc.addBlock();
5409
5410 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5411 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
5412 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
5413 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
5414
5415 root->appendNewControlValue(
5416 proc, Branch, Origin(),
5417 condition,
5418 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
5419
5420 Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5421 UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble);
5422 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5423
5424 Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), constValue);
5425 UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble);
5426 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
5427
5428 Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin());
5429 thenValue->setPhi(doubleInput);
5430 elseValue->setPhi(doubleInput);
5431
5432 Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5433 Value* finalAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain);
5434 Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), finalAdd);
5435 tail->appendNewControlValue(proc, Return, Origin(), floatResult);
5436
5437 auto code = compileProc(proc);
5438 CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + value));
5439 CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<float>(constValue + value)));
5440}
5441
5442void testDoubleArgToInt64BitwiseCast(double value)
5443{
5444 Procedure proc;
5445 BasicBlock* root = proc.addBlock();
5446 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
5447
5448 root->appendNewControlValue(
5449 proc, Return, Origin(),
5450 root->appendNew<Value>(
5451 proc, BitwiseCast, Origin(), argument));
5452
5453 CHECK(isIdentical(compileAndRun<int64_t>(proc, value), bitwise_cast<int64_t>(value)));
5454}
5455
5456void testDoubleImmToInt64BitwiseCast(double value)
5457{
5458 Procedure proc;
5459 BasicBlock* root = proc.addBlock();
5460 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value);
5461
5462 root->appendNewControlValue(
5463 proc, Return, Origin(),
5464 root->appendNew<Value>(
5465 proc, BitwiseCast, Origin(), argument));
5466
5467 CHECK(isIdentical(compileAndRun<int64_t>(proc), bitwise_cast<int64_t>(value)));
5468}
5469
5470void testTwoBitwiseCastOnDouble(double value)
5471{
5472 Procedure proc;
5473 BasicBlock* root = proc.addBlock();
5474 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
5475 Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
5476 Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
5477 root->appendNewControlValue(proc, Return, Origin(), second);
5478
5479 CHECK(isIdentical(compileAndRun<double>(proc, value), value));
5480}
5481
5482void testBitwiseCastOnDoubleInMemory(double value)
5483{
5484 Procedure proc;
5485 BasicBlock* root = proc.addBlock();
5486 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5487 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
5488 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
5489 root->appendNewControlValue(proc, Return, Origin(), cast);
5490
5491 CHECK(isIdentical(compileAndRun<int64_t>(proc, &value), bitwise_cast<int64_t>(value)));
5492}
5493
5494void testBitwiseCastOnDoubleInMemoryIndexed(double value)
5495{
5496 Procedure proc;
5497 BasicBlock* root = proc.addBlock();
5498 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5499 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
5500 Value* scaledOffset = root->appendNew<Value>(proc, Shl, Origin(),
5501 offset,
5502 root->appendNew<Const32Value>(proc, Origin(), 3));
5503 Value* address = root->appendNew<Value>(proc, Add, Origin(), base, scaledOffset);
5504 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
5505 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
5506 root->appendNewControlValue(proc, Return, Origin(), cast);
5507
5508 CHECK(isIdentical(compileAndRun<int64_t>(proc, &value, 0), bitwise_cast<int64_t>(value)));
5509}
5510
5511void testInt64BArgToDoubleBitwiseCast(int64_t value)
5512{
5513 Procedure proc;
5514 BasicBlock* root = proc.addBlock();
5515 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5516
5517 root->appendNewControlValue(
5518 proc, Return, Origin(),
5519 root->appendNew<Value>(
5520 proc, BitwiseCast, Origin(), argument));
5521
5522 CHECK(isIdentical(compileAndRun<double>(proc, value), bitwise_cast<double>(value)));
5523}
5524
5525void testInt64BImmToDoubleBitwiseCast(int64_t value)
5526{
5527 Procedure proc;
5528 BasicBlock* root = proc.addBlock();
5529 Value* argument = root->appendNew<Const64Value>(proc, Origin(), value);
5530
5531 root->appendNewControlValue(
5532 proc, Return, Origin(),
5533 root->appendNew<Value>(
5534 proc, BitwiseCast, Origin(), argument));
5535
5536 CHECK(isIdentical(compileAndRun<double>(proc), bitwise_cast<double>(value)));
5537}
5538
5539void testTwoBitwiseCastOnInt64(int64_t value)
5540{
5541 Procedure proc;
5542 BasicBlock* root = proc.addBlock();
5543 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5544 Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
5545 Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
5546 root->appendNewControlValue(proc, Return, Origin(), second);
5547
5548 CHECK(isIdentical(compileAndRun<int64_t>(proc, value), value));
5549}
5550
5551void testBitwiseCastOnInt64InMemory(int64_t value)
5552{
5553 Procedure proc;
5554 BasicBlock* root = proc.addBlock();
5555 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5556 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
5557 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
5558 root->appendNewControlValue(proc, Return, Origin(), cast);
5559
5560 CHECK(isIdentical(compileAndRun<double>(proc, &value), bitwise_cast<double>(value)));
5561}
5562
5563void testBitwiseCastOnInt64InMemoryIndexed(int64_t value)
5564{
5565 Procedure proc;
5566 BasicBlock* root = proc.addBlock();
5567 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5568 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
5569 Value* scaledOffset = root->appendNew<Value>(proc, Shl, Origin(),
5570 offset,
5571 root->appendNew<Const32Value>(proc, Origin(), 3));
5572 Value* address = root->appendNew<Value>(proc, Add, Origin(), base, scaledOffset);
5573 MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
5574 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble);
5575 root->appendNewControlValue(proc, Return, Origin(), cast);
5576
5577 CHECK(isIdentical(compileAndRun<double>(proc, &value, 0), bitwise_cast<double>(value)));
5578}
5579
5580void testFloatImmToInt32BitwiseCast(float value)
5581{
5582 Procedure proc;
5583 BasicBlock* root = proc.addBlock();
5584 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), value);
5585
5586 root->appendNewControlValue(
5587 proc, Return, Origin(),
5588 root->appendNew<Value>(
5589 proc, BitwiseCast, Origin(), argument));
5590
5591 CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(value)));
5592}
5593
5594void testBitwiseCastOnFloatInMemory(float value)
5595{
5596 Procedure proc;
5597 BasicBlock* root = proc.addBlock();
5598 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5599 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
5600 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadFloat);
5601 root->appendNewControlValue(proc, Return, Origin(), cast);
5602
5603 CHECK(isIdentical(compileAndRun<int32_t>(proc, &value), bitwise_cast<int32_t>(value)));
5604}
5605
5606void testInt32BArgToFloatBitwiseCast(int32_t value)
5607{
5608 Procedure proc;
5609 BasicBlock* root = proc.addBlock();
5610 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5611
5612 root->appendNewControlValue(
5613 proc, Return, Origin(),
5614 root->appendNew<Value>(
5615 proc, BitwiseCast, Origin(), argument));
5616
5617 CHECK(isIdentical(compileAndRun<float>(proc, value), bitwise_cast<float>(value)));
5618}
5619
5620void testInt32BImmToFloatBitwiseCast(int32_t value)
5621{
5622 Procedure proc;
5623 BasicBlock* root = proc.addBlock();
5624 Value* argument = root->appendNew<Const64Value>(proc, Origin(), value);
5625
5626 root->appendNewControlValue(
5627 proc, Return, Origin(),
5628 root->appendNew<Value>(
5629 proc, BitwiseCast, Origin(), argument));
5630
5631 CHECK(isIdentical(compileAndRun<float>(proc), bitwise_cast<float>(value)));
5632}
5633
5634void testTwoBitwiseCastOnInt32(int32_t value)
5635{
5636 Procedure proc;
5637 BasicBlock* root = proc.addBlock();
5638 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5639 Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument);
5640 Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first);
5641 root->appendNewControlValue(proc, Return, Origin(), second);
5642
5643 CHECK(isIdentical(compileAndRun<int32_t>(proc, value), value));
5644}
5645
5646void testBitwiseCastOnInt32InMemory(int32_t value)
5647{
5648 Procedure proc;
5649 BasicBlock* root = proc.addBlock();
5650 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5651 MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
5652 Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadFloat);
5653 root->appendNewControlValue(proc, Return, Origin(), cast);
5654
5655 CHECK(isIdentical(compileAndRun<float>(proc, &value), bitwise_cast<float>(value)));
5656}
5657
5658void testConvertDoubleToFloatArg(double value)
5659{
5660 Procedure proc;
5661 BasicBlock* root = proc.addBlock();
5662 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
5663 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
5664 root->appendNewControlValue(proc, Return, Origin(), asFloat);
5665
5666 CHECK(isIdentical(compileAndRun<float>(proc, value), static_cast<float>(value)));
5667}
5668
5669void testConvertDoubleToFloatImm(double value)
5670{
5671 Procedure proc;
5672 BasicBlock* root = proc.addBlock();
5673 Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value);
5674 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
5675 root->appendNewControlValue(proc, Return, Origin(), asFloat);
5676
5677 CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
5678}
5679
5680void testConvertDoubleToFloatMem(double value)
5681{
5682 Procedure proc;
5683 BasicBlock* root = proc.addBlock();
5684 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5685 MemoryValue* loadedDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
5686 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), loadedDouble);
5687 root->appendNewControlValue(proc, Return, Origin(), asFloat);
5688
5689 CHECK(isIdentical(compileAndRun<float>(proc, &value), static_cast<float>(value)));
5690}
5691
5692void testConvertFloatToDoubleArg(float value)
5693{
5694 Procedure proc;
5695 BasicBlock* root = proc.addBlock();
5696 Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
5697 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5698 Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
5699 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
5700 root->appendNewControlValue(proc, Return, Origin(), asDouble);
5701
5702 CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int32_t>(value)), static_cast<double>(value)));
5703}
5704
5705void testConvertFloatToDoubleImm(float value)
5706{
5707 Procedure proc;
5708 BasicBlock* root = proc.addBlock();
5709 Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), value);
5710 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument);
5711 root->appendNewControlValue(proc, Return, Origin(), asDouble);
5712
5713 CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
5714}
5715
5716void testConvertFloatToDoubleMem(float value)
5717{
5718 Procedure proc;
5719 BasicBlock* root = proc.addBlock();
5720 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5721 MemoryValue* loadedFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
5722 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), loadedFloat);
5723 root->appendNewControlValue(proc, Return, Origin(), asDouble);
5724
5725 CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(value)));
5726}
5727
5728void testConvertDoubleToFloatToDoubleToFloat(double value)
5729{
5730 Procedure proc;
5731 BasicBlock* root = proc.addBlock();
5732 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
5733 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
5734 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
5735 Value* asFloatAgain = root->appendNew<Value>(proc, DoubleToFloat, Origin(), asDouble);
5736 root->appendNewControlValue(proc, Return, Origin(), asFloatAgain);
5737
5738 CHECK(isIdentical(compileAndRun<float>(proc, value), static_cast<float>(value)));
5739}
5740
5741void testLoadFloatConvertDoubleConvertFloatStoreFloat(float value)
5742{
5743 Procedure proc;
5744 BasicBlock* root = proc.addBlock();
5745 Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5746 Value* dst = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
5747 MemoryValue* loadedFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), src);
5748 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), loadedFloat);
5749 Value* asFloatAgain = root->appendNew<Value>(proc, DoubleToFloat, Origin(), asDouble);
5750 root->appendNew<MemoryValue>(proc, Store, Origin(), asFloatAgain, dst);
5751
5752 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
5753
5754 float input = value;
5755 float output = 0.;
5756 CHECK(!compileAndRun<int64_t>(proc, &input, &output));
5757 CHECK(isIdentical(input, output));
5758}
5759
5760void testFroundArg(double value)
5761{
5762 Procedure proc;
5763 BasicBlock* root = proc.addBlock();
5764 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
5765 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
5766 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
5767 root->appendNewControlValue(proc, Return, Origin(), asDouble);
5768
5769 CHECK(isIdentical(compileAndRun<double>(proc, value), static_cast<double>(static_cast<float>(value))));
5770}
5771
5772void testFroundMem(double value)
5773{
5774 Procedure proc;
5775 BasicBlock* root = proc.addBlock();
5776 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5777 MemoryValue* loadedDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
5778 Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), loadedDouble);
5779 Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat);
5780 root->appendNewControlValue(proc, Return, Origin(), asDouble);
5781
5782 CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(static_cast<float>(value))));
5783}
5784
5785void testIToD64Arg()
5786{
5787 Procedure proc;
5788 BasicBlock* root = proc.addBlock();
5789 Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5790 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
5791 root->appendNewControlValue(proc, Return, Origin(), srcAsDouble);
5792
5793 auto code = compileProc(proc);
5794 for (auto testValue : int64Operands())
5795 CHECK(isIdentical(invoke<double>(*code, testValue.value), static_cast<double>(testValue.value)));
5796}
5797
5798void testIToF64Arg()
5799{
5800 Procedure proc;
5801 BasicBlock* root = proc.addBlock();
5802 Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5803 Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), src);
5804 root->appendNewControlValue(proc, Return, Origin(), srcAsFloat);
5805
5806 auto code = compileProc(proc);
5807 for (auto testValue : int64Operands())
5808 CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
5809}
5810
5811void testIToD32Arg()
5812{
5813 Procedure proc;
5814 BasicBlock* root = proc.addBlock();
5815 Value* src = root->appendNew<Value>(proc, Trunc, Origin(),
5816 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5817 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
5818 root->appendNewControlValue(proc, Return, Origin(), srcAsDouble);
5819
5820 auto code = compileProc(proc);
5821 for (auto testValue : int32Operands())
5822 CHECK(isIdentical(invoke<double>(*code, testValue.value), static_cast<double>(testValue.value)));
5823}
5824
5825void testIToF32Arg()
5826{
5827 Procedure proc;
5828 BasicBlock* root = proc.addBlock();
5829 Value* src = root->appendNew<Value>(proc, Trunc, Origin(),
5830 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5831 Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), src);
5832 root->appendNewControlValue(proc, Return, Origin(), srcAsFloat);
5833
5834 auto code = compileProc(proc);
5835 for (auto testValue : int32Operands())
5836 CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
5837}
5838
5839void testIToD64Mem()
5840{
5841 Procedure proc;
5842 BasicBlock* root = proc.addBlock();
5843 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5844 MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
5845 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), loadedSrc);
5846 root->appendNewControlValue(proc, Return, Origin(), srcAsDouble);
5847
5848 auto code = compileProc(proc);
5849 int64_t inMemoryValue;
5850 for (auto testValue : int64Operands()) {
5851 inMemoryValue = testValue.value;
5852 CHECK(isIdentical(invoke<double>(*code, &inMemoryValue), static_cast<double>(testValue.value)));
5853 CHECK(inMemoryValue == testValue.value);
5854 }
5855}
5856
5857void testIToF64Mem()
5858{
5859 Procedure proc;
5860 BasicBlock* root = proc.addBlock();
5861 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5862 MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
5863 Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), loadedSrc);
5864 root->appendNewControlValue(proc, Return, Origin(), srcAsFloat);
5865
5866 auto code = compileProc(proc);
5867 int64_t inMemoryValue;
5868 for (auto testValue : int64Operands()) {
5869 inMemoryValue = testValue.value;
5870 CHECK(isIdentical(invoke<float>(*code, &inMemoryValue), static_cast<float>(testValue.value)));
5871 CHECK(inMemoryValue == testValue.value);
5872 }
5873}
5874
5875void testIToD32Mem()
5876{
5877 Procedure proc;
5878 BasicBlock* root = proc.addBlock();
5879 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5880 MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
5881 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), loadedSrc);
5882 root->appendNewControlValue(proc, Return, Origin(), srcAsDouble);
5883
5884 auto code = compileProc(proc);
5885 int32_t inMemoryValue;
5886 for (auto testValue : int32Operands()) {
5887 inMemoryValue = testValue.value;
5888 CHECK(isIdentical(invoke<double>(*code, &inMemoryValue), static_cast<double>(testValue.value)));
5889 CHECK(inMemoryValue == testValue.value);
5890 }
5891}
5892
5893void testIToF32Mem()
5894{
5895 Procedure proc;
5896 BasicBlock* root = proc.addBlock();
5897 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5898 MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
5899 Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), loadedSrc);
5900 root->appendNewControlValue(proc, Return, Origin(), srcAsFloat);
5901
5902 auto code = compileProc(proc);
5903 int32_t inMemoryValue;
5904 for (auto testValue : int32Operands()) {
5905 inMemoryValue = testValue.value;
5906 CHECK(isIdentical(invoke<float>(*code, &inMemoryValue), static_cast<float>(testValue.value)));
5907 CHECK(inMemoryValue == testValue.value);
5908 }
5909}
5910
5911void testIToD64Imm(int64_t value)
5912{
5913 Procedure proc;
5914 BasicBlock* root = proc.addBlock();
5915 Value* src = root->appendNew<Const64Value>(proc, Origin(), value);
5916 Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToD, Origin(), src);
5917 root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint);
5918 CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
5919}
5920
5921void testIToF64Imm(int64_t value)
5922{
5923 Procedure proc;
5924 BasicBlock* root = proc.addBlock();
5925 Value* src = root->appendNew<Const64Value>(proc, Origin(), value);
5926 Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToF, Origin(), src);
5927 root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint);
5928 CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
5929}
5930
5931void testIToD32Imm(int32_t value)
5932{
5933 Procedure proc;
5934 BasicBlock* root = proc.addBlock();
5935 Value* src = root->appendNew<Const32Value>(proc, Origin(), value);
5936 Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToD, Origin(), src);
5937 root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint);
5938 CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
5939}
5940
5941void testIToF32Imm(int32_t value)
5942{
5943 Procedure proc;
5944 BasicBlock* root = proc.addBlock();
5945 Value* src = root->appendNew<Const32Value>(proc, Origin(), value);
5946 Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToF, Origin(), src);
5947 root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint);
5948 CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
5949}
5950
5951void testIToDReducedToIToF64Arg()
5952{
5953 Procedure proc;
5954 BasicBlock* root = proc.addBlock();
5955 Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
5956 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
5957 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), srcAsDouble);
5958 root->appendNewControlValue(proc, Return, Origin(), floatResult);
5959
5960 auto code = compileProc(proc);
5961 for (auto testValue : int64Operands())
5962 CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
5963}
5964
5965void testIToDReducedToIToF32Arg()
5966{
5967 Procedure proc;
5968 BasicBlock* root = proc.addBlock();
5969 Value* src = root->appendNew<Value>(proc, Trunc, Origin(),
5970 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
5971 Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
5972 Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), srcAsDouble);
5973 root->appendNewControlValue(proc, Return, Origin(), floatResult);
5974
5975 auto code = compileProc(proc);
5976 for (auto testValue : int32Operands())
5977 CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
5978}
5979
5980void testStore32(int value)
5981{
5982 Procedure proc;
5983 BasicBlock* root = proc.addBlock();
5984 int slot = 0xbaadbeef;
5985 root->appendNew<MemoryValue>(
5986 proc, Store, Origin(),
5987 root->appendNew<Value>(
5988 proc, Trunc, Origin(),
5989 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
5990 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0);
5991 root->appendNewControlValue(
5992 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
5993
5994 CHECK(!compileAndRun<int>(proc, value));
5995 CHECK(slot == value);
5996}
5997
5998void testStoreConstant(int value)
5999{
6000 Procedure proc;
6001 BasicBlock* root = proc.addBlock();
6002 int slot = 0xbaadbeef;
6003 root->appendNew<MemoryValue>(
6004 proc, Store, Origin(),
6005 root->appendNew<Const32Value>(proc, Origin(), value),
6006 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0);
6007 root->appendNewControlValue(
6008 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
6009
6010 CHECK(!compileAndRun<int>(proc));
6011 CHECK(slot == value);
6012}
6013
6014void testStoreConstantPtr(intptr_t value)
6015{
6016 Procedure proc;
6017 BasicBlock* root = proc.addBlock();
6018 intptr_t slot;
6019#if CPU(ADDRESS64)
6020 slot = (static_cast<intptr_t>(0xbaadbeef) << 32) + static_cast<intptr_t>(0xbaadbeef);
6021#else
6022 slot = 0xbaadbeef;
6023#endif
6024 root->appendNew<MemoryValue>(
6025 proc, Store, Origin(),
6026 root->appendNew<ConstPtrValue>(proc, Origin(), value),
6027 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0);
6028 root->appendNewControlValue(
6029 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
6030
6031 CHECK(!compileAndRun<int>(proc));
6032 CHECK(slot == value);
6033}
6034
6035void testStore8Arg()
6036{
6037 { // Direct addressing.
6038 Procedure proc;
6039 BasicBlock* root = proc.addBlock();
6040
6041 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
6042 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
6043 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6044
6045 root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address);
6046 root->appendNewControlValue(proc, Return, Origin(), value);
6047
6048 int8_t storage = 0;
6049 CHECK(compileAndRun<int64_t>(proc, 42, &storage) == 42);
6050 CHECK(storage == 42);
6051 }
6052
6053 { // Indexed addressing.
6054 Procedure proc;
6055 BasicBlock* root = proc.addBlock();
6056
6057 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
6058 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
6059 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6060 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
6061 Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
6062
6063 Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
6064 Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
6065
6066 root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address);
6067 root->appendNewControlValue(proc, Return, Origin(), value);
6068
6069 int8_t storage = 0;
6070 CHECK(compileAndRun<int64_t>(proc, 42, &storage, 1) == 42);
6071 CHECK(storage == 42);
6072 }
6073}
6074
6075void testStore8Imm()
6076{
6077 { // Direct addressing.
6078 Procedure proc;
6079 BasicBlock* root = proc.addBlock();
6080
6081 Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
6082 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6083
6084 root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address);
6085 root->appendNewControlValue(proc, Return, Origin(), value);
6086
6087 int8_t storage = 0;
6088 CHECK(compileAndRun<int64_t>(proc, &storage) == 42);
6089 CHECK(storage == 42);
6090 }
6091
6092 { // Indexed addressing.
6093 Procedure proc;
6094 BasicBlock* root = proc.addBlock();
6095
6096 Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
6097 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6098 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6099 Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
6100
6101 Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
6102 Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
6103
6104 root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address);
6105 root->appendNewControlValue(proc, Return, Origin(), value);
6106
6107 int8_t storage = 0;
6108 CHECK(compileAndRun<int64_t>(proc, &storage, 1) == 42);
6109 CHECK(storage == 42);
6110 }
6111}
6112
6113void testStorePartial8BitRegisterOnX86()
6114{
6115 Procedure proc;
6116 BasicBlock* root = proc.addBlock();
6117
6118 // We want to have this in ECX.
6119 Value* returnValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6120
6121 // We want this suck in EDX.
6122 Value* whereToStore = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6123
6124 // The patch point is there to help us force the hand of the compiler.
6125 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
6126
6127 // For the value above to be materialized and give the allocator
6128 // a stronger insentive to name those register the way we need.
6129 patchpoint->append(ConstrainedValue(returnValue, ValueRep(GPRInfo::regT3)));
6130 patchpoint->append(ConstrainedValue(whereToStore, ValueRep(GPRInfo::regT2)));
6131
6132 // We'll produce EDI.
6133 patchpoint->resultConstraint = ValueRep::reg(GPRInfo::regT6);
6134
6135 // Give the allocator a good reason not to use any other register.
6136 RegisterSet clobberSet = RegisterSet::allGPRs();
6137 clobberSet.exclude(RegisterSet::stackRegisters());
6138 clobberSet.exclude(RegisterSet::reservedHardwareRegisters());
6139 clobberSet.clear(GPRInfo::regT3);
6140 clobberSet.clear(GPRInfo::regT2);
6141 clobberSet.clear(GPRInfo::regT6);
6142 patchpoint->clobberLate(clobberSet);
6143
6144 // Set EDI.
6145 patchpoint->setGenerator(
6146 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
6147 AllowMacroScratchRegisterUsage allowScratch(jit);
6148 jit.xor64(params[0].gpr(), params[0].gpr());
6149 });
6150
6151 // If everything went well, we should have the big number in eax,
6152 // patchpoint == EDI and whereToStore = EDX.
6153 // Since EDI == 5, and AH = 5 on 8 bit store, this would go wrong
6154 // if we use X86 partial registers.
6155 root->appendNew<MemoryValue>(proc, Store8, Origin(), patchpoint, whereToStore);
6156
6157 root->appendNewControlValue(proc, Return, Origin(), returnValue);
6158
6159 int8_t storage = 0xff;
6160 CHECK(compileAndRun<int64_t>(proc, 0x12345678abcdef12, &storage) == 0x12345678abcdef12);
6161 CHECK(!storage);
6162}
6163
6164void testStore16Arg()
6165{
6166 { // Direct addressing.
6167 Procedure proc;
6168 BasicBlock* root = proc.addBlock();
6169
6170 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
6171 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
6172 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6173
6174 root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
6175 root->appendNewControlValue(proc, Return, Origin(), value);
6176
6177 int16_t storage = -1;
6178 CHECK(compileAndRun<int64_t>(proc, 42, &storage) == 42);
6179 CHECK(storage == 42);
6180 }
6181
6182 { // Indexed addressing.
6183 Procedure proc;
6184 BasicBlock* root = proc.addBlock();
6185
6186 Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
6187 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
6188 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6189 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
6190 Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
6191
6192 Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
6193 Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
6194
6195 root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
6196 root->appendNewControlValue(proc, Return, Origin(), value);
6197
6198 int16_t storage = -1;
6199 CHECK(compileAndRun<int64_t>(proc, 42, &storage, 1) == 42);
6200 CHECK(storage == 42);
6201 }
6202}
6203
6204void testStore16Imm()
6205{
6206 { // Direct addressing.
6207 Procedure proc;
6208 BasicBlock* root = proc.addBlock();
6209
6210 Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
6211 Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6212
6213 root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
6214 root->appendNewControlValue(proc, Return, Origin(), value);
6215
6216 int16_t storage = -1;
6217 CHECK(compileAndRun<int64_t>(proc, &storage) == 42);
6218 CHECK(storage == 42);
6219 }
6220
6221 { // Indexed addressing.
6222 Procedure proc;
6223 BasicBlock* root = proc.addBlock();
6224
6225 Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
6226 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6227 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
6228 Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
6229
6230 Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
6231 Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
6232
6233 root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
6234 root->appendNewControlValue(proc, Return, Origin(), value);
6235
6236 int16_t storage = -1;
6237 CHECK(compileAndRun<int64_t>(proc, &storage, 1) == 42);
6238 CHECK(storage == 42);
6239 }
6240}
6241
6242void testTrunc(int64_t value)
6243{
6244 Procedure proc;
6245 BasicBlock* root = proc.addBlock();
6246 root->appendNewControlValue(
6247 proc, Return, Origin(),
6248 root->appendNew<Value>(
6249 proc, Trunc, Origin(),
6250 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
6251
6252 CHECK(compileAndRun<int>(proc, value) == static_cast<int>(value));
6253}
6254
6255void testAdd1(int value)
6256{
6257 Procedure proc;
6258 BasicBlock* root = proc.addBlock();
6259 root->appendNewControlValue(
6260 proc, Return, Origin(),
6261 root->appendNew<Value>(
6262 proc, Add, Origin(),
6263 root->appendNew<Value>(
6264 proc, Trunc, Origin(),
6265 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
6266 root->appendNew<Const32Value>(proc, Origin(), 1)));
6267
6268 CHECK(compileAndRun<int>(proc, value) == value + 1);
6269}
6270
6271void testAdd1Ptr(intptr_t value)
6272{
6273 Procedure proc;
6274 BasicBlock* root = proc.addBlock();
6275 root->appendNewControlValue(
6276 proc, Return, Origin(),
6277 root->appendNew<Value>(
6278 proc, Add, Origin(),
6279 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
6280 root->appendNew<ConstPtrValue>(proc, Origin(), 1)));
6281
6282 CHECK(compileAndRun<intptr_t>(proc, value) == value + 1);
6283}
6284
6285void testNeg32(int32_t value)
6286{
6287 Procedure proc;
6288 BasicBlock* root = proc.addBlock();
6289 root->appendNewControlValue(
6290 proc, Return, Origin(),
6291 root->appendNew<Value>(
6292 proc, Sub, Origin(),
6293 root->appendNew<Const32Value>(proc, Origin(), 0),
6294 root->appendNew<Value>(
6295 proc, Trunc, Origin(),
6296 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
6297
6298 CHECK(compileAndRun<int32_t>(proc, value) == -value);
6299}
6300
6301void testNegPtr(intptr_t value)
6302{
6303 Procedure proc;
6304 BasicBlock* root = proc.addBlock();
6305 root->appendNewControlValue(
6306 proc, Return, Origin(),
6307 root->appendNew<Value>(
6308 proc, Sub, Origin(),
6309 root->appendNew<ConstPtrValue>(proc, Origin(), 0),
6310 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
6311
6312 CHECK(compileAndRun<intptr_t>(proc, value) == -value);
6313}
6314
6315void testStoreAddLoad32(int amount)
6316{
6317 Procedure proc;
6318 BasicBlock* root = proc.addBlock();
6319 int slot = 37;
6320 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6321 root->appendNew<MemoryValue>(
6322 proc, Store, Origin(),
6323 root->appendNew<Value>(
6324 proc, Add, Origin(),
6325 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
6326 root->appendNew<Value>(
6327 proc, Trunc, Origin(),
6328 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6329 slotPtr, 0);
6330 root->appendNewControlValue(
6331 proc, Return, Origin(),
6332 root->appendNew<Const32Value>(proc, Origin(), 0));
6333
6334 CHECK(!compileAndRun<int>(proc, amount));
6335 CHECK(slot == 37 + amount);
6336}
6337
6338void testStoreRelAddLoadAcq32(int amount)
6339{
6340 Procedure proc;
6341 BasicBlock* root = proc.addBlock();
6342 int slot = 37;
6343 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6344 root->appendNew<MemoryValue>(
6345 proc, Store, Origin(),
6346 root->appendNew<Value>(
6347 proc, Add, Origin(),
6348 root->appendNew<MemoryValue>(
6349 proc, Load, Int32, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
6350 root->appendNew<Value>(
6351 proc, Trunc, Origin(),
6352 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6353 slotPtr, 0, HeapRange(42), HeapRange(42));
6354 root->appendNewControlValue(
6355 proc, Return, Origin(),
6356 root->appendNew<Const32Value>(proc, Origin(), 0));
6357
6358 auto code = compileProc(proc);
6359 if (isARM64()) {
6360 checkUsesInstruction(*code, "lda");
6361 checkUsesInstruction(*code, "stl");
6362 }
6363 if (isX86())
6364 checkUsesInstruction(*code, "xchg");
6365 CHECK(!invoke<int>(*code, amount));
6366 CHECK(slot == 37 + amount);
6367}
6368
6369void testStoreAddLoadImm32(int amount)
6370{
6371 Procedure proc;
6372 BasicBlock* root = proc.addBlock();
6373 int slot = 37;
6374 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6375 root->appendNew<MemoryValue>(
6376 proc, Store, Origin(),
6377 root->appendNew<Value>(
6378 proc, Add, Origin(),
6379 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
6380 root->appendNew<Const32Value>(proc, Origin(), amount)),
6381 slotPtr, 0);
6382 root->appendNewControlValue(
6383 proc, Return, Origin(),
6384 root->appendNew<Const32Value>(proc, Origin(), 0));
6385
6386 CHECK(!compileAndRun<int>(proc));
6387 CHECK(slot == 37 + amount);
6388}
6389
6390void testStoreAddLoad8(int amount, B3::Opcode loadOpcode)
6391{
6392 Procedure proc;
6393 BasicBlock* root = proc.addBlock();
6394 int8_t slot = 37;
6395 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6396 root->appendNew<MemoryValue>(
6397 proc, Store8, Origin(),
6398 root->appendNew<Value>(
6399 proc, Add, Origin(),
6400 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
6401 root->appendNew<Value>(
6402 proc, Trunc, Origin(),
6403 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6404 slotPtr, 0);
6405 root->appendNewControlValue(
6406 proc, Return, Origin(),
6407 root->appendNew<Const32Value>(proc, Origin(), 0));
6408
6409 CHECK(!compileAndRun<int>(proc, amount));
6410 CHECK(slot == 37 + amount);
6411}
6412
6413void testStoreRelAddLoadAcq8(int amount, B3::Opcode loadOpcode)
6414{
6415 Procedure proc;
6416 BasicBlock* root = proc.addBlock();
6417 int8_t slot = 37;
6418 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6419 root->appendNew<MemoryValue>(
6420 proc, Store8, Origin(),
6421 root->appendNew<Value>(
6422 proc, Add, Origin(),
6423 root->appendNew<MemoryValue>(
6424 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
6425 root->appendNew<Value>(
6426 proc, Trunc, Origin(),
6427 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6428 slotPtr, 0, HeapRange(42), HeapRange(42));
6429 root->appendNewControlValue(
6430 proc, Return, Origin(),
6431 root->appendNew<Const32Value>(proc, Origin(), 0));
6432
6433 auto code = compileProc(proc);
6434 if (isARM64()) {
6435 checkUsesInstruction(*code, "lda");
6436 checkUsesInstruction(*code, "stl");
6437 }
6438 if (isX86())
6439 checkUsesInstruction(*code, "xchg");
6440 CHECK(!invoke<int>(*code, amount));
6441 CHECK(slot == 37 + amount);
6442}
6443
6444void testStoreRelAddFenceLoadAcq8(int amount, B3::Opcode loadOpcode)
6445{
6446 Procedure proc;
6447 BasicBlock* root = proc.addBlock();
6448 int8_t slot = 37;
6449 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6450 Value* loadedValue = root->appendNew<MemoryValue>(
6451 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42));
6452 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
6453 patchpoint->clobber(RegisterSet::macroScratchRegisters());
6454 patchpoint->setGenerator(
6455 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
6456 AllowMacroScratchRegisterUsage allowScratch(jit);
6457 jit.store8(CCallHelpers::TrustedImm32(0xbeef), &slot);
6458 });
6459 patchpoint->effects = Effects::none();
6460 patchpoint->effects.fence = true;
6461 root->appendNew<MemoryValue>(
6462 proc, Store8, Origin(),
6463 root->appendNew<Value>(
6464 proc, Add, Origin(),
6465 loadedValue,
6466 root->appendNew<Value>(
6467 proc, Trunc, Origin(),
6468 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6469 slotPtr, 0, HeapRange(42), HeapRange(42));
6470 root->appendNewControlValue(
6471 proc, Return, Origin(),
6472 root->appendNew<Const32Value>(proc, Origin(), 0));
6473
6474 auto code = compileProc(proc);
6475 if (isARM64()) {
6476 checkUsesInstruction(*code, "lda");
6477 checkUsesInstruction(*code, "stl");
6478 }
6479 if (isX86())
6480 checkUsesInstruction(*code, "xchg");
6481 CHECK(!invoke<int>(*code, amount));
6482 CHECK(slot == 37 + amount);
6483}
6484
6485void testStoreAddLoadImm8(int amount, B3::Opcode loadOpcode)
6486{
6487 Procedure proc;
6488 BasicBlock* root = proc.addBlock();
6489 int8_t slot = 37;
6490 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6491 root->appendNew<MemoryValue>(
6492 proc, Store8, Origin(),
6493 root->appendNew<Value>(
6494 proc, Add, Origin(),
6495 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
6496 root->appendNew<Const32Value>(proc, Origin(), amount)),
6497 slotPtr, 0);
6498 root->appendNewControlValue(
6499 proc, Return, Origin(),
6500 root->appendNew<Const32Value>(proc, Origin(), 0));
6501
6502 CHECK(!compileAndRun<int>(proc));
6503 CHECK(slot == 37 + amount);
6504}
6505
6506void testStoreAddLoad16(int amount, B3::Opcode loadOpcode)
6507{
6508 Procedure proc;
6509 BasicBlock* root = proc.addBlock();
6510 int16_t slot = 37;
6511 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6512 root->appendNew<MemoryValue>(
6513 proc, Store16, Origin(),
6514 root->appendNew<Value>(
6515 proc, Add, Origin(),
6516 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
6517 root->appendNew<Value>(
6518 proc, Trunc, Origin(),
6519 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6520 slotPtr, 0);
6521 root->appendNewControlValue(
6522 proc, Return, Origin(),
6523 root->appendNew<Const32Value>(proc, Origin(), 0));
6524
6525 CHECK(!compileAndRun<int>(proc, amount));
6526 CHECK(slot == 37 + amount);
6527}
6528
6529void testStoreRelAddLoadAcq16(int amount, B3::Opcode loadOpcode)
6530{
6531 Procedure proc;
6532 BasicBlock* root = proc.addBlock();
6533 int16_t slot = 37;
6534 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6535 root->appendNew<MemoryValue>(
6536 proc, Store16, Origin(),
6537 root->appendNew<Value>(
6538 proc, Add, Origin(),
6539 root->appendNew<MemoryValue>(
6540 proc, loadOpcode, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
6541 root->appendNew<Value>(
6542 proc, Trunc, Origin(),
6543 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6544 slotPtr, 0, HeapRange(42), HeapRange(42));
6545 root->appendNewControlValue(
6546 proc, Return, Origin(),
6547 root->appendNew<Const32Value>(proc, Origin(), 0));
6548
6549 auto code = compileProc(proc);
6550 if (isARM64()) {
6551 checkUsesInstruction(*code, "lda");
6552 checkUsesInstruction(*code, "stl");
6553 }
6554 if (isX86())
6555 checkUsesInstruction(*code, "xchg");
6556 CHECK(!invoke<int>(*code, amount));
6557 CHECK(slot == 37 + amount);
6558}
6559
6560void testStoreAddLoadImm16(int amount, B3::Opcode loadOpcode)
6561{
6562 Procedure proc;
6563 BasicBlock* root = proc.addBlock();
6564 int16_t slot = 37;
6565 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6566 root->appendNew<MemoryValue>(
6567 proc, Store16, Origin(),
6568 root->appendNew<Value>(
6569 proc, Add, Origin(),
6570 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
6571 root->appendNew<Const32Value>(proc, Origin(), amount)),
6572 slotPtr, 0);
6573 root->appendNewControlValue(
6574 proc, Return, Origin(),
6575 root->appendNew<Const32Value>(proc, Origin(), 0));
6576
6577 CHECK(!compileAndRun<int>(proc));
6578 CHECK(slot == 37 + amount);
6579}
6580
6581void testStoreAddLoad64(int amount)
6582{
6583 Procedure proc;
6584 BasicBlock* root = proc.addBlock();
6585 int64_t slot = 37000000000ll;
6586 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6587 root->appendNew<MemoryValue>(
6588 proc, Store, Origin(),
6589 root->appendNew<Value>(
6590 proc, Add, Origin(),
6591 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
6592 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
6593 slotPtr, 0);
6594 root->appendNewControlValue(
6595 proc, Return, Origin(),
6596 root->appendNew<Const32Value>(proc, Origin(), 0));
6597
6598 CHECK(!compileAndRun<int>(proc, amount));
6599 CHECK(slot == 37000000000ll + amount);
6600}
6601
6602void testStoreRelAddLoadAcq64(int amount)
6603{
6604 Procedure proc;
6605 BasicBlock* root = proc.addBlock();
6606 int64_t slot = 37000000000ll;
6607 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6608 root->appendNew<MemoryValue>(
6609 proc, Store, Origin(),
6610 root->appendNew<Value>(
6611 proc, Add, Origin(),
6612 root->appendNew<MemoryValue>(
6613 proc, Load, Int64, Origin(), slotPtr, 0, HeapRange(42), HeapRange(42)),
6614 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
6615 slotPtr, 0, HeapRange(42), HeapRange(42));
6616 root->appendNewControlValue(
6617 proc, Return, Origin(),
6618 root->appendNew<Const32Value>(proc, Origin(), 0));
6619
6620 auto code = compileProc(proc);
6621 if (isARM64()) {
6622 checkUsesInstruction(*code, "lda");
6623 checkUsesInstruction(*code, "stl");
6624 }
6625 if (isX86())
6626 checkUsesInstruction(*code, "xchg");
6627 CHECK(!invoke<int>(*code, amount));
6628 CHECK(slot == 37000000000ll + amount);
6629}
6630
6631void testStoreAddLoadImm64(int64_t amount)
6632{
6633 Procedure proc;
6634 BasicBlock* root = proc.addBlock();
6635 int64_t slot = 370000000000ll;
6636 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6637 root->appendNew<MemoryValue>(
6638 proc, Store, Origin(),
6639 root->appendNew<Value>(
6640 proc, Add, Origin(),
6641 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
6642 root->appendNew<Const64Value>(proc, Origin(), amount)),
6643 slotPtr, 0);
6644 root->appendNewControlValue(
6645 proc, Return, Origin(),
6646 root->appendNew<Const32Value>(proc, Origin(), 0));
6647
6648 CHECK(!compileAndRun<int>(proc));
6649 CHECK(slot == 370000000000ll + amount);
6650}
6651
6652void testStoreAddLoad32Index(int amount)
6653{
6654 Procedure proc;
6655 BasicBlock* root = proc.addBlock();
6656 int slot = 37;
6657 int* ptr = &slot;
6658 intptr_t zero = 0;
6659 Value* slotPtr = root->appendNew<Value>(
6660 proc, Add, Origin(),
6661 root->appendNew<MemoryValue>(
6662 proc, Load, pointerType(), Origin(),
6663 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
6664 root->appendNew<MemoryValue>(
6665 proc, Load, pointerType(), Origin(),
6666 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
6667 root->appendNew<MemoryValue>(
6668 proc, Store, Origin(),
6669 root->appendNew<Value>(
6670 proc, Add, Origin(),
6671 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
6672 root->appendNew<Value>(
6673 proc, Trunc, Origin(),
6674 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6675 slotPtr, 0);
6676 root->appendNewControlValue(
6677 proc, Return, Origin(),
6678 root->appendNew<Const32Value>(proc, Origin(), 0));
6679
6680 CHECK(!compileAndRun<int>(proc, amount));
6681 CHECK(slot == 37 + amount);
6682}
6683
6684void testStoreAddLoadImm32Index(int amount)
6685{
6686 Procedure proc;
6687 BasicBlock* root = proc.addBlock();
6688 int slot = 37;
6689 int* ptr = &slot;
6690 intptr_t zero = 0;
6691 Value* slotPtr = root->appendNew<Value>(
6692 proc, Add, Origin(),
6693 root->appendNew<MemoryValue>(
6694 proc, Load, pointerType(), Origin(),
6695 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
6696 root->appendNew<MemoryValue>(
6697 proc, Load, pointerType(), Origin(),
6698 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
6699 root->appendNew<MemoryValue>(
6700 proc, Store, Origin(),
6701 root->appendNew<Value>(
6702 proc, Add, Origin(),
6703 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
6704 root->appendNew<Const32Value>(proc, Origin(), amount)),
6705 slotPtr, 0);
6706 root->appendNewControlValue(
6707 proc, Return, Origin(),
6708 root->appendNew<Const32Value>(proc, Origin(), 0));
6709
6710 CHECK(!compileAndRun<int>(proc));
6711 CHECK(slot == 37 + amount);
6712}
6713
6714void testStoreAddLoad8Index(int amount, B3::Opcode loadOpcode)
6715{
6716 Procedure proc;
6717 BasicBlock* root = proc.addBlock();
6718 int8_t slot = 37;
6719 int8_t* ptr = &slot;
6720 intptr_t zero = 0;
6721 Value* slotPtr = root->appendNew<Value>(
6722 proc, Add, Origin(),
6723 root->appendNew<MemoryValue>(
6724 proc, Load, pointerType(), Origin(),
6725 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
6726 root->appendNew<MemoryValue>(
6727 proc, Load, pointerType(), Origin(),
6728 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
6729 root->appendNew<MemoryValue>(
6730 proc, Store8, Origin(),
6731 root->appendNew<Value>(
6732 proc, Add, Origin(),
6733 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
6734 root->appendNew<Value>(
6735 proc, Trunc, Origin(),
6736 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6737 slotPtr);
6738 root->appendNewControlValue(
6739 proc, Return, Origin(),
6740 root->appendNew<Const32Value>(proc, Origin(), 0));
6741
6742 CHECK(!compileAndRun<int>(proc, amount));
6743 CHECK(slot == 37 + amount);
6744}
6745
6746void testStoreAddLoadImm8Index(int amount, B3::Opcode loadOpcode)
6747{
6748 Procedure proc;
6749 BasicBlock* root = proc.addBlock();
6750 int8_t slot = 37;
6751 int8_t* ptr = &slot;
6752 intptr_t zero = 0;
6753 Value* slotPtr = root->appendNew<Value>(
6754 proc, Add, Origin(),
6755 root->appendNew<MemoryValue>(
6756 proc, Load, pointerType(), Origin(),
6757 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
6758 root->appendNew<MemoryValue>(
6759 proc, Load, pointerType(), Origin(),
6760 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
6761 root->appendNew<MemoryValue>(
6762 proc, Store8, Origin(),
6763 root->appendNew<Value>(
6764 proc, Add, Origin(),
6765 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
6766 root->appendNew<Const32Value>(proc, Origin(), amount)),
6767 slotPtr);
6768 root->appendNewControlValue(
6769 proc, Return, Origin(),
6770 root->appendNew<Const32Value>(proc, Origin(), 0));
6771
6772 CHECK(!compileAndRun<int>(proc));
6773 CHECK(slot == 37 + amount);
6774}
6775
6776void testStoreAddLoad16Index(int amount, B3::Opcode loadOpcode)
6777{
6778 Procedure proc;
6779 BasicBlock* root = proc.addBlock();
6780 int16_t slot = 37;
6781 int16_t* ptr = &slot;
6782 intptr_t zero = 0;
6783 Value* slotPtr = root->appendNew<Value>(
6784 proc, Add, Origin(),
6785 root->appendNew<MemoryValue>(
6786 proc, Load, pointerType(), Origin(),
6787 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
6788 root->appendNew<MemoryValue>(
6789 proc, Load, pointerType(), Origin(),
6790 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
6791 root->appendNew<MemoryValue>(
6792 proc, Store16, Origin(),
6793 root->appendNew<Value>(
6794 proc, Add, Origin(),
6795 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
6796 root->appendNew<Value>(
6797 proc, Trunc, Origin(),
6798 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6799 slotPtr);
6800 root->appendNewControlValue(
6801 proc, Return, Origin(),
6802 root->appendNew<Const32Value>(proc, Origin(), 0));
6803
6804 CHECK(!compileAndRun<int>(proc, amount));
6805 CHECK(slot == 37 + amount);
6806}
6807
6808void testStoreAddLoadImm16Index(int amount, B3::Opcode loadOpcode)
6809{
6810 Procedure proc;
6811 BasicBlock* root = proc.addBlock();
6812 int16_t slot = 37;
6813 int16_t* ptr = &slot;
6814 intptr_t zero = 0;
6815 Value* slotPtr = root->appendNew<Value>(
6816 proc, Add, Origin(),
6817 root->appendNew<MemoryValue>(
6818 proc, Load, pointerType(), Origin(),
6819 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
6820 root->appendNew<MemoryValue>(
6821 proc, Load, pointerType(), Origin(),
6822 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
6823 root->appendNew<MemoryValue>(
6824 proc, Store16, Origin(),
6825 root->appendNew<Value>(
6826 proc, Add, Origin(),
6827 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
6828 root->appendNew<Const32Value>(proc, Origin(), amount)),
6829 slotPtr);
6830 root->appendNewControlValue(
6831 proc, Return, Origin(),
6832 root->appendNew<Const32Value>(proc, Origin(), 0));
6833
6834 CHECK(!compileAndRun<int>(proc));
6835 CHECK(slot == 37 + amount);
6836}
6837
6838void testStoreAddLoad64Index(int amount)
6839{
6840 Procedure proc;
6841 BasicBlock* root = proc.addBlock();
6842 int64_t slot = 37000000000ll;
6843 int64_t* ptr = &slot;
6844 intptr_t zero = 0;
6845 Value* slotPtr = root->appendNew<Value>(
6846 proc, Add, Origin(),
6847 root->appendNew<MemoryValue>(
6848 proc, Load, pointerType(), Origin(),
6849 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
6850 root->appendNew<MemoryValue>(
6851 proc, Load, pointerType(), Origin(),
6852 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
6853 root->appendNew<MemoryValue>(
6854 proc, Store, Origin(),
6855 root->appendNew<Value>(
6856 proc, Add, Origin(),
6857 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
6858 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
6859 slotPtr, 0);
6860 root->appendNewControlValue(
6861 proc, Return, Origin(),
6862 root->appendNew<Const32Value>(proc, Origin(), 0));
6863
6864 CHECK(!compileAndRun<int>(proc, amount));
6865 CHECK(slot == 37000000000ll + amount);
6866}
6867
6868void testStoreAddLoadImm64Index(int64_t amount)
6869{
6870 Procedure proc;
6871 BasicBlock* root = proc.addBlock();
6872 int64_t slot = 370000000000ll;
6873 int64_t* ptr = &slot;
6874 intptr_t zero = 0;
6875 Value* slotPtr = root->appendNew<Value>(
6876 proc, Add, Origin(),
6877 root->appendNew<MemoryValue>(
6878 proc, Load, pointerType(), Origin(),
6879 root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
6880 root->appendNew<MemoryValue>(
6881 proc, Load, pointerType(), Origin(),
6882 root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
6883 root->appendNew<MemoryValue>(
6884 proc, Store, Origin(),
6885 root->appendNew<Value>(
6886 proc, Add, Origin(),
6887 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
6888 root->appendNew<Const64Value>(proc, Origin(), amount)),
6889 slotPtr, 0);
6890 root->appendNewControlValue(
6891 proc, Return, Origin(),
6892 root->appendNew<Const32Value>(proc, Origin(), 0));
6893
6894 CHECK(!compileAndRun<int>(proc));
6895 CHECK(slot == 370000000000ll + amount);
6896}
6897
6898void testStoreSubLoad(int amount)
6899{
6900 Procedure proc;
6901 BasicBlock* root = proc.addBlock();
6902 int32_t startValue = std::numeric_limits<int32_t>::min();
6903 int32_t slot = startValue;
6904 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6905 root->appendNew<MemoryValue>(
6906 proc, Store, Origin(),
6907 root->appendNew<Value>(
6908 proc, Sub, Origin(),
6909 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
6910 root->appendNew<Value>(
6911 proc, Trunc, Origin(),
6912 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
6913 slotPtr, 0);
6914 root->appendNewControlValue(
6915 proc, Return, Origin(),
6916 root->appendNew<Const32Value>(proc, Origin(), 0));
6917
6918 CHECK(!compileAndRun<int>(proc, amount));
6919 CHECK(slot == startValue - amount);
6920}
6921
6922void testStoreAddLoadInterference(int amount)
6923{
6924 Procedure proc;
6925 BasicBlock* root = proc.addBlock();
6926 int slot = 37;
6927 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6928 ArgumentRegValue* otherSlotPtr =
6929 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
6930 MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr);
6931 root->appendNew<MemoryValue>(
6932 proc, Store, Origin(),
6933 root->appendNew<Const32Value>(proc, Origin(), 666),
6934 otherSlotPtr, 0);
6935 root->appendNew<MemoryValue>(
6936 proc, Store, Origin(),
6937 root->appendNew<Value>(
6938 proc, Add, Origin(),
6939 load, root->appendNew<Const32Value>(proc, Origin(), amount)),
6940 slotPtr, 0);
6941 root->appendNewControlValue(
6942 proc, Return, Origin(),
6943 root->appendNew<Const32Value>(proc, Origin(), 0));
6944
6945 CHECK(!compileAndRun<int>(proc, &slot));
6946 CHECK(slot == 37 + amount);
6947}
6948
6949void testStoreAddAndLoad(int amount, int mask)
6950{
6951 Procedure proc;
6952 BasicBlock* root = proc.addBlock();
6953 int slot = 37;
6954 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6955 root->appendNew<MemoryValue>(
6956 proc, Store, Origin(),
6957 root->appendNew<Value>(
6958 proc, BitAnd, Origin(),
6959 root->appendNew<Value>(
6960 proc, Add, Origin(),
6961 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
6962 root->appendNew<Const32Value>(proc, Origin(), amount)),
6963 root->appendNew<Const32Value>(proc, Origin(), mask)),
6964 slotPtr, 0);
6965 root->appendNewControlValue(
6966 proc, Return, Origin(),
6967 root->appendNew<Const32Value>(proc, Origin(), 0));
6968
6969 CHECK(!compileAndRun<int>(proc));
6970 CHECK(slot == ((37 + amount) & mask));
6971}
6972
6973void testStoreNegLoad32(int32_t value)
6974{
6975 Procedure proc;
6976 BasicBlock* root = proc.addBlock();
6977
6978 int32_t slot = value;
6979
6980 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
6981
6982 root->appendNew<MemoryValue>(
6983 proc, Store, Origin(),
6984 root->appendNew<Value>(
6985 proc, Sub, Origin(),
6986 root->appendNew<Const32Value>(proc, Origin(), 0),
6987 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)),
6988 slotPtr, 0);
6989
6990 root->appendNewControlValue(
6991 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
6992
6993 CHECK(!compileAndRun<int32_t>(proc));
6994 CHECK(slot == -value);
6995}
6996
6997void testStoreNegLoadPtr(intptr_t value)
6998{
6999 Procedure proc;
7000 BasicBlock* root = proc.addBlock();
7001
7002 intptr_t slot = value;
7003
7004 ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
7005
7006 root->appendNew<MemoryValue>(
7007 proc, Store, Origin(),
7008 root->appendNew<Value>(
7009 proc, Sub, Origin(),
7010 root->appendNew<ConstPtrValue>(proc, Origin(), 0),
7011 root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)),
7012 slotPtr, 0);
7013
7014 root->appendNewControlValue(
7015 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
7016
7017 CHECK(!compileAndRun<int32_t>(proc));
7018 CHECK(slot == -value);
7019}
7020
7021void testAdd1Uncommuted(int value)
7022{
7023 Procedure proc;
7024 BasicBlock* root = proc.addBlock();
7025 root->appendNewControlValue(
7026 proc, Return, Origin(),
7027 root->appendNew<Value>(
7028 proc, Add, Origin(),
7029 root->appendNew<Const32Value>(proc, Origin(), 1),
7030 root->appendNew<Value>(
7031 proc, Trunc, Origin(),
7032 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
7033
7034 CHECK(compileAndRun<int>(proc, value) == value + 1);
7035}
7036
7037void testLoadOffset()
7038{
7039 Procedure proc;
7040 BasicBlock* root = proc.addBlock();
7041 int array[] = { 1, 2 };
7042 ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
7043 root->appendNewControlValue(
7044 proc, Return, Origin(),
7045 root->appendNew<Value>(
7046 proc, Add, Origin(),
7047 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
7048 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, static_cast<int32_t>(sizeof(int)))));
7049
7050 CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
7051}
7052
7053void testLoadOffsetNotConstant()
7054{
7055 Procedure proc;
7056 BasicBlock* root = proc.addBlock();
7057 int array[] = { 1, 2 };
7058 Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7059 root->appendNewControlValue(
7060 proc, Return, Origin(),
7061 root->appendNew<Value>(
7062 proc, Add, Origin(),
7063 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0),
7064 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, static_cast<int32_t>(sizeof(int)))));
7065
7066 CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
7067}
7068
7069void testLoadOffsetUsingAdd()
7070{
7071 Procedure proc;
7072 BasicBlock* root = proc.addBlock();
7073 int array[] = { 1, 2 };
7074 ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
7075 root->appendNewControlValue(
7076 proc, Return, Origin(),
7077 root->appendNew<Value>(
7078 proc, Add, Origin(),
7079 root->appendNew<MemoryValue>(
7080 proc, Load, Int32, Origin(),
7081 root->appendNew<Value>(
7082 proc, Add, Origin(), arrayPtr,
7083 root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
7084 root->appendNew<MemoryValue>(
7085 proc, Load, Int32, Origin(),
7086 root->appendNew<Value>(
7087 proc, Add, Origin(), arrayPtr,
7088 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))))));
7089
7090 CHECK(compileAndRun<int>(proc) == array[0] + array[1]);
7091}
7092
7093void testLoadOffsetUsingAddInterference()
7094{
7095 Procedure proc;
7096 BasicBlock* root = proc.addBlock();
7097 int array[] = { 1, 2 };
7098 ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array);
7099 ArgumentRegValue* otherArrayPtr =
7100 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7101 Const32Value* theNumberOfTheBeast = root->appendNew<Const32Value>(proc, Origin(), 666);
7102 MemoryValue* left = root->appendNew<MemoryValue>(
7103 proc, Load, Int32, Origin(),
7104 root->appendNew<Value>(
7105 proc, Add, Origin(), arrayPtr,
7106 root->appendNew<ConstPtrValue>(proc, Origin(), 0)));
7107 MemoryValue* right = root->appendNew<MemoryValue>(
7108 proc, Load, Int32, Origin(),
7109 root->appendNew<Value>(
7110 proc, Add, Origin(), arrayPtr,
7111 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))));
7112 root->appendNew<MemoryValue>(
7113 proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0);
7114 root->appendNew<MemoryValue>(
7115 proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, static_cast<int32_t>(sizeof(int)));
7116 root->appendNewControlValue(
7117 proc, Return, Origin(),
7118 root->appendNew<Value>(
7119 proc, Add, Origin(), left, right));
7120
7121 CHECK(compileAndRun<int>(proc, &array[0]) == 1 + 2);
7122 CHECK(array[0] == 666);
7123 CHECK(array[1] == 666);
7124}
7125
7126void testLoadOffsetUsingAddNotConstant()
7127{
7128 Procedure proc;
7129 BasicBlock* root = proc.addBlock();
7130 int array[] = { 1, 2 };
7131 Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7132 root->appendNewControlValue(
7133 proc, Return, Origin(),
7134 root->appendNew<Value>(
7135 proc, Add, Origin(),
7136 root->appendNew<MemoryValue>(
7137 proc, Load, Int32, Origin(),
7138 root->appendNew<Value>(
7139 proc, Add, Origin(), arrayPtr,
7140 root->appendNew<ConstPtrValue>(proc, Origin(), 0))),
7141 root->appendNew<MemoryValue>(
7142 proc, Load, Int32, Origin(),
7143 root->appendNew<Value>(
7144 proc, Add, Origin(), arrayPtr,
7145 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int)))))));
7146
7147 CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]);
7148}
7149
7150void testLoadAddrShift(unsigned shift)
7151{
7152 Procedure proc;
7153 BasicBlock* root = proc.addBlock();
7154 int slots[2];
7155
7156 // Figure out which slot to use while having proper alignment for the shift.
7157 int* slot;
7158 uintptr_t arg;
7159 for (unsigned i = sizeof(slots)/sizeof(slots[0]); i--;) {
7160 slot = slots + i;
7161 arg = bitwise_cast<uintptr_t>(slot) >> shift;
7162 if (bitwise_cast<int*>(arg << shift) == slot)
7163 break;
7164 }
7165
7166 *slot = 8675309;
7167
7168 root->appendNewControlValue(
7169 proc, Return, Origin(),
7170 root->appendNew<MemoryValue>(
7171 proc, Load, Int32, Origin(),
7172 root->appendNew<Value>(
7173 proc, Shl, Origin(),
7174 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
7175 root->appendNew<Const32Value>(proc, Origin(), shift))));
7176
7177 CHECK(compileAndRun<int>(proc, arg) == 8675309);
7178}
7179
7180void testFramePointer()
7181{
7182 Procedure proc;
7183 BasicBlock* root = proc.addBlock();
7184 root->appendNewControlValue(
7185 proc, Return, Origin(),
7186 root->appendNew<Value>(proc, FramePointer, Origin()));
7187
7188 void* fp = compileAndRun<void*>(proc);
7189 CHECK(fp < &proc);
7190 CHECK(fp >= bitwise_cast<char*>(&proc) - 10000);
7191}
7192
7193void testOverrideFramePointer()
7194{
7195 {
7196 Procedure proc;
7197 BasicBlock* root = proc.addBlock();
7198
7199 // Add a stack slot to make the frame non trivial.
7200 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8));
7201
7202 // Sub on x86 UseDef the source. If FP is not protected correctly, it will be overridden since it is the last visible use.
7203 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7204 Value* fp = root->appendNew<Value>(proc, FramePointer, Origin());
7205 Value* result = root->appendNew<Value>(proc, Sub, Origin(), fp, offset);
7206
7207 root->appendNewControlValue(proc, Return, Origin(), result);
7208 CHECK(compileAndRun<int64_t>(proc, 1));
7209 }
7210 {
7211 Procedure proc;
7212 BasicBlock* root = proc.addBlock();
7213
7214 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8));
7215
7216 Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7217 Value* fp = root->appendNew<Value>(proc, FramePointer, Origin());
7218 Value* offsetFP = root->appendNew<Value>(proc, BitAnd, Origin(), offset, fp);
7219 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
7220 Value* offsetArg = root->appendNew<Value>(proc, Add, Origin(), offset, arg);
7221 Value* result = root->appendNew<Value>(proc, Add, Origin(), offsetArg, offsetFP);
7222
7223 root->appendNewControlValue(proc, Return, Origin(), result);
7224 CHECK(compileAndRun<int64_t>(proc, 1, 2));
7225 }
7226}
7227
7228void testStackSlot()
7229{
7230 Procedure proc;
7231 BasicBlock* root = proc.addBlock();
7232 root->appendNewControlValue(
7233 proc, Return, Origin(),
7234 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(1)));
7235
7236 void* stackSlot = compileAndRun<void*>(proc);
7237 CHECK(stackSlot < &proc);
7238 CHECK(stackSlot >= bitwise_cast<char*>(&proc) - 10000);
7239}
7240
7241void testLoadFromFramePointer()
7242{
7243 Procedure proc;
7244 BasicBlock* root = proc.addBlock();
7245 root->appendNewControlValue(
7246 proc, Return, Origin(),
7247 root->appendNew<MemoryValue>(
7248 proc, Load, pointerType(), Origin(),
7249 root->appendNew<Value>(proc, FramePointer, Origin())));
7250
7251 void* fp = compileAndRun<void*>(proc);
7252 void* myFP = __builtin_frame_address(0);
7253 CHECK(fp <= myFP);
7254 CHECK(fp >= bitwise_cast<char*>(myFP) - 10000);
7255}
7256
7257void testStoreLoadStackSlot(int value)
7258{
7259 Procedure proc;
7260 BasicBlock* root = proc.addBlock();
7261
7262 SlotBaseValue* stack =
7263 root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(sizeof(int)));
7264
7265 root->appendNew<MemoryValue>(
7266 proc, Store, Origin(),
7267 root->appendNew<Value>(
7268 proc, Trunc, Origin(),
7269 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
7270 stack, 0);
7271
7272 root->appendNewControlValue(
7273 proc, Return, Origin(),
7274 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), stack));
7275
7276 CHECK(compileAndRun<int>(proc, value) == value);
7277}
7278
7279template<typename LoadedType, typename EffectiveType>
7280EffectiveType modelLoad(EffectiveType value)
7281{
7282 union {
7283 EffectiveType original;
7284 LoadedType loaded;
7285 } u;
7286
7287 u.original = value;
7288 if (std::is_signed<LoadedType>::value)
7289 return static_cast<EffectiveType>(u.loaded);
7290 return static_cast<EffectiveType>(static_cast<typename std::make_unsigned<EffectiveType>::type>(u.loaded));
7291}
7292
7293template<>
7294float modelLoad<float, float>(float value) { return value; }
7295
7296template<>
7297double modelLoad<double, double>(double value) { return value; }
7298
7299template<B3::Type type, typename CType, typename InputType>
7300void testLoad(B3::Opcode opcode, InputType value)
7301{
7302 // Simple load from an absolute address.
7303 {
7304 Procedure proc;
7305 BasicBlock* root = proc.addBlock();
7306
7307 root->appendNewControlValue(
7308 proc, Return, Origin(),
7309 root->appendNew<MemoryValue>(
7310 proc, opcode, type, Origin(),
7311 root->appendNew<ConstPtrValue>(proc, Origin(), &value)));
7312
7313 CHECK(isIdentical(compileAndRun<CType>(proc), modelLoad<CType>(value)));
7314 }
7315
7316 // Simple load from an address in a register.
7317 {
7318 Procedure proc;
7319 BasicBlock* root = proc.addBlock();
7320
7321 root->appendNewControlValue(
7322 proc, Return, Origin(),
7323 root->appendNew<MemoryValue>(
7324 proc, opcode, type, Origin(),
7325 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
7326
7327 CHECK(isIdentical(compileAndRun<CType>(proc, &value), modelLoad<CType>(value)));
7328 }
7329
7330 // Simple load from an address in a register, at an offset.
7331 {
7332 Procedure proc;
7333 BasicBlock* root = proc.addBlock();
7334
7335 root->appendNewControlValue(
7336 proc, Return, Origin(),
7337 root->appendNew<MemoryValue>(
7338 proc, opcode, type, Origin(),
7339 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
7340 static_cast<int32_t>(sizeof(InputType))));
7341
7342 CHECK(isIdentical(compileAndRun<CType>(proc, &value - 1), modelLoad<CType>(value)));
7343 }
7344
7345 // Load from a simple base-index with various scales.
7346 for (unsigned logScale = 0; logScale <= 3; ++logScale) {
7347 Procedure proc;
7348 BasicBlock* root = proc.addBlock();
7349
7350 root->appendNewControlValue(
7351 proc, Return, Origin(),
7352 root->appendNew<MemoryValue>(
7353 proc, opcode, type, Origin(),
7354 root->appendNew<Value>(
7355 proc, Add, Origin(),
7356 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
7357 root->appendNew<Value>(
7358 proc, Shl, Origin(),
7359 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
7360 root->appendNew<Const32Value>(proc, Origin(), logScale)))));
7361
7362 CHECK(isIdentical(compileAndRun<CType>(proc, &value - 2, (sizeof(InputType) * 2) >> logScale), modelLoad<CType>(value)));
7363 }
7364
7365 // Load from a simple base-index with various scales, but commuted.
7366 for (unsigned logScale = 0; logScale <= 3; ++logScale) {
7367 Procedure proc;
7368 BasicBlock* root = proc.addBlock();
7369
7370 root->appendNewControlValue(
7371 proc, Return, Origin(),
7372 root->appendNew<MemoryValue>(
7373 proc, opcode, type, Origin(),
7374 root->appendNew<Value>(
7375 proc, Add, Origin(),
7376 root->appendNew<Value>(
7377 proc, Shl, Origin(),
7378 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
7379 root->appendNew<Const32Value>(proc, Origin(), logScale)),
7380 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
7381
7382 CHECK(isIdentical(compileAndRun<CType>(proc, &value - 2, (sizeof(InputType) * 2) >> logScale), modelLoad<CType>(value)));
7383 }
7384}
7385
7386template<typename T>
7387void testLoad(B3::Opcode opcode, int32_t value)
7388{
7389 return testLoad<Int32, T>(opcode, value);
7390}
7391
7392template<B3::Type type, typename T>
7393void testLoad(T value)
7394{
7395 return testLoad<type, T>(Load, value);
7396}
7397
7398void testStoreFloat(double input)
7399{
7400 // Simple store from an address in a register.
7401 {
7402 Procedure proc;
7403 BasicBlock* root = proc.addBlock();
7404 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
7405 Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
7406
7407 Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7408 root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
7409
7410 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
7411
7412 float output = 0.;
7413 CHECK(!compileAndRun<int64_t>(proc, input, &output));
7414 CHECK(isIdentical(static_cast<float>(input), output));
7415 }
7416
7417 // Simple indexed store.
7418 {
7419 Procedure proc;
7420 BasicBlock* root = proc.addBlock();
7421 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
7422 Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument);
7423
7424 Value* destinationBaseAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7425 Value* index = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
7426 Value* scaledIndex = root->appendNew<Value>(
7427 proc, Shl, Origin(),
7428 index,
7429 root->appendNew<Const32Value>(proc, Origin(), 2));
7430 Value* destinationAddress = root->appendNew<Value>(proc, Add, Origin(), scaledIndex, destinationBaseAddress);
7431
7432 root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress);
7433
7434 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
7435
7436 float output = 0.;
7437 CHECK(!compileAndRun<int64_t>(proc, input, &output - 1, 1));
7438 CHECK(isIdentical(static_cast<float>(input), output));
7439 }
7440}
7441
7442void testStoreDoubleConstantAsFloat(double input)
7443{
7444 // Simple store from an address in a register.
7445 Procedure proc;
7446 BasicBlock* root = proc.addBlock();
7447 Value* value = root->appendNew<ConstDoubleValue>(proc, Origin(), input);
7448 Value* valueAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), value);
7449
7450 Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7451
7452 root->appendNew<MemoryValue>(proc, Store, Origin(), valueAsFloat, destinationAddress);
7453
7454 root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
7455
7456 float output = 0.;
7457 CHECK(!compileAndRun<int64_t>(proc, input, &output));
7458 CHECK(isIdentical(static_cast<float>(input), output));
7459}
7460
7461void testSpillGP()
7462{
7463 Procedure proc;
7464 BasicBlock* root = proc.addBlock();
7465
7466 Vector<Value*> sources;
7467 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
7468 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
7469
7470 for (unsigned i = 0; i < 30; ++i) {
7471 sources.append(
7472 root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
7473 );
7474 }
7475
7476 Value* total = root->appendNew<Const64Value>(proc, Origin(), 0);
7477 for (Value* value : sources)
7478 total = root->appendNew<Value>(proc, Add, Origin(), total, value);
7479
7480 root->appendNewControlValue(proc, Return, Origin(), total);
7481 compileAndRun<int>(proc, 1, 2);
7482}
7483
7484void testSpillFP()
7485{
7486 Procedure proc;
7487 BasicBlock* root = proc.addBlock();
7488
7489 Vector<Value*> sources;
7490 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
7491 sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
7492
7493 for (unsigned i = 0; i < 30; ++i) {
7494 sources.append(
7495 root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2])
7496 );
7497 }
7498
7499 Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
7500 for (Value* value : sources)
7501 total = root->appendNew<Value>(proc, Add, Origin(), total, value);
7502
7503 root->appendNewControlValue(proc, Return, Origin(), total);
7504 compileAndRun<double>(proc, 1.1, 2.5);
7505}
7506
7507void testInt32ToDoublePartialRegisterStall()
7508{
7509 Procedure proc;
7510 BasicBlock* root = proc.addBlock();
7511 BasicBlock* loop = proc.addBlock();
7512 BasicBlock* done = proc.addBlock();
7513
7514 // Head.
7515 Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
7516 Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7517 UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total);
7518 UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter);
7519 root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop));
7520
7521 // Loop.
7522 Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin());
7523 Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin());
7524 originalCounter->setPhi(loopCounter);
7525 originalTotal->setPhi(loopTotal);
7526
7527 Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter);
7528 Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter);
7529 Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal);
7530 UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
7531 updatedTotalUpsilon->setPhi(loopTotal);
7532
7533 Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1));
7534 UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter);
7535 decCounterUpsilon->setPhi(loopCounter);
7536 loop->appendNewControlValue(
7537 proc, Branch, Origin(),
7538 decCounter,
7539 FrequentedBlock(loop), FrequentedBlock(done));
7540
7541 // Tail.
7542 done->appendNewControlValue(proc, Return, Origin(), updatedTotal);
7543 CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
7544}
7545
7546void testInt32ToDoublePartialRegisterWithoutStall()
7547{
7548 Procedure proc;
7549 BasicBlock* root = proc.addBlock();
7550 BasicBlock* loop = proc.addBlock();
7551 BasicBlock* done = proc.addBlock();
7552
7553 // Head.
7554 Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
7555 Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
7556 UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total);
7557 UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter);
7558 uint64_t forPaddingInput;
7559 Value* forPaddingInputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingInput);
7560 uint64_t forPaddingOutput;
7561 Value* forPaddingOutputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingOutput);
7562 root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop));
7563
7564 // Loop.
7565 Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin());
7566 Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin());
7567 originalCounter->setPhi(loopCounter);
7568 originalTotal->setPhi(loopTotal);
7569
7570 Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter);
7571 Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter);
7572 Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal);
7573
7574 // Add enough padding instructions to avoid a stall.
7575 Value* loadPadding = loop->appendNew<MemoryValue>(proc, Load, Int64, Origin(), forPaddingInputAddress);
7576 Value* padding = loop->appendNew<Value>(proc, BitXor, Origin(), loadPadding, loopCounter);
7577 padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
7578 padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
7579 padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
7580 padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter);
7581 padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
7582 padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
7583 padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
7584 padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter);
7585 padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter);
7586 padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter);
7587 padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter);
7588 loop->appendNew<MemoryValue>(proc, Store, Origin(), padding, forPaddingOutputAddress);
7589
7590 UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal);
7591 updatedTotalUpsilon->setPhi(loopTotal);
7592
7593 Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1));
7594 UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter);
7595 decCounterUpsilon->setPhi(loopCounter);
7596 loop->appendNewControlValue(
7597 proc, Branch, Origin(),
7598 decCounter,
7599 FrequentedBlock(loop), FrequentedBlock(done));
7600
7601 // Tail.
7602 done->appendNewControlValue(proc, Return, Origin(), updatedTotal);
7603 CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.));
7604}
7605
7606void testBranch()
7607{
7608 Procedure proc;
7609 BasicBlock* root = proc.addBlock();
7610 BasicBlock* thenCase = proc.addBlock();
7611 BasicBlock* elseCase = proc.addBlock();
7612
7613 root->appendNewControlValue(
7614 proc, Branch, Origin(),
7615 root->appendNew<Value>(
7616 proc, Trunc, Origin(),
7617 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
7618 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7619
7620 thenCase->appendNewControlValue(
7621 proc, Return, Origin(),
7622 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
7623
7624 elseCase->appendNewControlValue(
7625 proc, Return, Origin(),
7626 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
7627
7628 auto code = compileProc(proc);
7629 CHECK(invoke<int>(*code, 42) == 1);
7630 CHECK(invoke<int>(*code, 0) == 0);
7631}
7632
7633void testBranchPtr()
7634{
7635 Procedure proc;
7636 BasicBlock* root = proc.addBlock();
7637 BasicBlock* thenCase = proc.addBlock();
7638 BasicBlock* elseCase = proc.addBlock();
7639
7640 root->appendNewControlValue(
7641 proc, Branch, Origin(),
7642 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
7643 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7644
7645 thenCase->appendNewControlValue(
7646 proc, Return, Origin(),
7647 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
7648
7649 elseCase->appendNewControlValue(
7650 proc, Return, Origin(),
7651 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
7652
7653 auto code = compileProc(proc);
7654 CHECK(invoke<int>(*code, static_cast<intptr_t>(42)) == 1);
7655 CHECK(invoke<int>(*code, static_cast<intptr_t>(0)) == 0);
7656}
7657
7658void testDiamond()
7659{
7660 Procedure proc;
7661 BasicBlock* root = proc.addBlock();
7662 BasicBlock* thenCase = proc.addBlock();
7663 BasicBlock* elseCase = proc.addBlock();
7664 BasicBlock* done = proc.addBlock();
7665
7666 root->appendNewControlValue(
7667 proc, Branch, Origin(),
7668 root->appendNew<Value>(
7669 proc, Trunc, Origin(),
7670 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
7671 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7672
7673 UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
7674 proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
7675 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
7676
7677 UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
7678 proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
7679 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
7680
7681 Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
7682 thenResult->setPhi(phi);
7683 elseResult->setPhi(phi);
7684 done->appendNewControlValue(proc, Return, Origin(), phi);
7685
7686 auto code = compileProc(proc);
7687 CHECK(invoke<int>(*code, 42) == 1);
7688 CHECK(invoke<int>(*code, 0) == 0);
7689}
7690
7691void testBranchNotEqual()
7692{
7693 Procedure proc;
7694 BasicBlock* root = proc.addBlock();
7695 BasicBlock* thenCase = proc.addBlock();
7696 BasicBlock* elseCase = proc.addBlock();
7697
7698 root->appendNewControlValue(
7699 proc, Branch, Origin(),
7700 root->appendNew<Value>(
7701 proc, NotEqual, Origin(),
7702 root->appendNew<Value>(
7703 proc, Trunc, Origin(),
7704 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
7705 root->appendNew<Const32Value>(proc, Origin(), 0)),
7706 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7707
7708 thenCase->appendNewControlValue(
7709 proc, Return, Origin(),
7710 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
7711
7712 elseCase->appendNewControlValue(
7713 proc, Return, Origin(),
7714 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
7715
7716 auto code = compileProc(proc);
7717 CHECK(invoke<int>(*code, 42) == 1);
7718 CHECK(invoke<int>(*code, 0) == 0);
7719}
7720
7721void testBranchNotEqualCommute()
7722{
7723 Procedure proc;
7724 BasicBlock* root = proc.addBlock();
7725 BasicBlock* thenCase = proc.addBlock();
7726 BasicBlock* elseCase = proc.addBlock();
7727
7728 root->appendNewControlValue(
7729 proc, Branch, Origin(),
7730 root->appendNew<Value>(
7731 proc, NotEqual, Origin(),
7732 root->appendNew<Const32Value>(proc, Origin(), 0),
7733 root->appendNew<Value>(
7734 proc, Trunc, Origin(),
7735 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
7736 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7737
7738 thenCase->appendNewControlValue(
7739 proc, Return, Origin(),
7740 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
7741
7742 elseCase->appendNewControlValue(
7743 proc, Return, Origin(),
7744 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
7745
7746 auto code = compileProc(proc);
7747 CHECK(invoke<int>(*code, 42) == 1);
7748 CHECK(invoke<int>(*code, 0) == 0);
7749}
7750
7751void testBranchNotEqualNotEqual()
7752{
7753 Procedure proc;
7754 BasicBlock* root = proc.addBlock();
7755 BasicBlock* thenCase = proc.addBlock();
7756 BasicBlock* elseCase = proc.addBlock();
7757
7758 root->appendNewControlValue(
7759 proc, Branch, Origin(),
7760 root->appendNew<Value>(
7761 proc, NotEqual, Origin(),
7762 root->appendNew<Value>(
7763 proc, NotEqual, Origin(),
7764 root->appendNew<Value>(
7765 proc, Trunc, Origin(),
7766 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
7767 root->appendNew<Const32Value>(proc, Origin(), 0)),
7768 root->appendNew<Const32Value>(proc, Origin(), 0)),
7769 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7770
7771 thenCase->appendNewControlValue(
7772 proc, Return, Origin(),
7773 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
7774
7775 elseCase->appendNewControlValue(
7776 proc, Return, Origin(),
7777 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
7778
7779 auto code = compileProc(proc);
7780 CHECK(invoke<int>(*code, 42) == 1);
7781 CHECK(invoke<int>(*code, 0) == 0);
7782}
7783
7784void testBranchEqual()
7785{
7786 Procedure proc;
7787 BasicBlock* root = proc.addBlock();
7788 BasicBlock* thenCase = proc.addBlock();
7789 BasicBlock* elseCase = proc.addBlock();
7790
7791 root->appendNewControlValue(
7792 proc, Branch, Origin(),
7793 root->appendNew<Value>(
7794 proc, Equal, Origin(),
7795 root->appendNew<Value>(
7796 proc, Trunc, Origin(),
7797 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
7798 root->appendNew<Const32Value>(proc, Origin(), 0)),
7799 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7800
7801 thenCase->appendNewControlValue(
7802 proc, Return, Origin(),
7803 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
7804
7805 elseCase->appendNewControlValue(
7806 proc, Return, Origin(),
7807 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
7808
7809 auto code = compileProc(proc);
7810 CHECK(invoke<int>(*code, 42) == 1);
7811 CHECK(invoke<int>(*code, 0) == 0);
7812}
7813
7814void testBranchEqualEqual()
7815{
7816 Procedure proc;
7817 BasicBlock* root = proc.addBlock();
7818 BasicBlock* thenCase = proc.addBlock();
7819 BasicBlock* elseCase = proc.addBlock();
7820
7821 root->appendNewControlValue(
7822 proc, Branch, Origin(),
7823 root->appendNew<Value>(
7824 proc, Equal, Origin(),
7825 root->appendNew<Value>(
7826 proc, Equal, Origin(),
7827 root->appendNew<Value>(
7828 proc, Trunc, Origin(),
7829 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
7830 root->appendNew<Const32Value>(proc, Origin(), 0)),
7831 root->appendNew<Const32Value>(proc, Origin(), 0)),
7832 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7833
7834 thenCase->appendNewControlValue(
7835 proc, Return, Origin(),
7836 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
7837
7838 elseCase->appendNewControlValue(
7839 proc, Return, Origin(),
7840 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
7841
7842 auto code = compileProc(proc);
7843 CHECK(invoke<int>(*code, 42) == 1);
7844 CHECK(invoke<int>(*code, 0) == 0);
7845}
7846
7847void testBranchEqualCommute()
7848{
7849 Procedure proc;
7850 BasicBlock* root = proc.addBlock();
7851 BasicBlock* thenCase = proc.addBlock();
7852 BasicBlock* elseCase = proc.addBlock();
7853
7854 root->appendNewControlValue(
7855 proc, Branch, Origin(),
7856 root->appendNew<Value>(
7857 proc, Equal, Origin(),
7858 root->appendNew<Const32Value>(proc, Origin(), 0),
7859 root->appendNew<Value>(
7860 proc, Trunc, Origin(),
7861 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
7862 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7863
7864 thenCase->appendNewControlValue(
7865 proc, Return, Origin(),
7866 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
7867
7868 elseCase->appendNewControlValue(
7869 proc, Return, Origin(),
7870 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
7871
7872 auto code = compileProc(proc);
7873 CHECK(invoke<int>(*code, 42) == 1);
7874 CHECK(invoke<int>(*code, 0) == 0);
7875}
7876
7877void testBranchEqualEqual1()
7878{
7879 Procedure proc;
7880 BasicBlock* root = proc.addBlock();
7881 BasicBlock* thenCase = proc.addBlock();
7882 BasicBlock* elseCase = proc.addBlock();
7883
7884 root->appendNewControlValue(
7885 proc, Branch, Origin(),
7886 root->appendNew<Value>(
7887 proc, Equal, Origin(),
7888 root->appendNew<Value>(
7889 proc, Equal, Origin(),
7890 root->appendNew<Value>(
7891 proc, Trunc, Origin(),
7892 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
7893 root->appendNew<Const32Value>(proc, Origin(), 0)),
7894 root->appendNew<Const32Value>(proc, Origin(), 1)),
7895 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7896
7897 thenCase->appendNewControlValue(
7898 proc, Return, Origin(),
7899 thenCase->appendNew<Const32Value>(proc, Origin(), 0));
7900
7901 elseCase->appendNewControlValue(
7902 proc, Return, Origin(),
7903 elseCase->appendNew<Const32Value>(proc, Origin(), 1));
7904
7905 auto code = compileProc(proc);
7906 CHECK(invoke<int>(*code, 42) == 1);
7907 CHECK(invoke<int>(*code, 0) == 0);
7908}
7909
7910void testBranchEqualOrUnorderedArgs(double a, double b)
7911{
7912 Procedure proc;
7913 BasicBlock* root = proc.addBlock();
7914 BasicBlock* thenCase = proc.addBlock();
7915 BasicBlock* elseCase = proc.addBlock();
7916
7917 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
7918 Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
7919 root->appendNewControlValue(
7920 proc, Branch, Origin(),
7921 root->appendNew<Value>(
7922 proc, EqualOrUnordered, Origin(),
7923 argumentA,
7924 argumentB),
7925 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7926
7927 thenCase->appendNewControlValue(
7928 proc, Return, Origin(),
7929 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
7930
7931 elseCase->appendNewControlValue(
7932 proc, Return, Origin(),
7933 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
7934
7935 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
7936 CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
7937}
7938
7939void testBranchEqualOrUnorderedArgs(float a, float b)
7940{
7941 Procedure proc;
7942 BasicBlock* root = proc.addBlock();
7943 BasicBlock* thenCase = proc.addBlock();
7944 BasicBlock* elseCase = proc.addBlock();
7945
7946 Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
7947 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
7948 Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
7949 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
7950
7951 root->appendNewControlValue(
7952 proc, Branch, Origin(),
7953 root->appendNew<Value>(
7954 proc, EqualOrUnordered, Origin(),
7955 argumentA,
7956 argumentB),
7957 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7958
7959 thenCase->appendNewControlValue(
7960 proc, Return, Origin(),
7961 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
7962
7963 elseCase->appendNewControlValue(
7964 proc, Return, Origin(),
7965 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
7966
7967 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
7968 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
7969}
7970
7971void testBranchNotEqualAndOrderedArgs(double a, double b)
7972{
7973 Procedure proc;
7974 BasicBlock* root = proc.addBlock();
7975 BasicBlock* thenCase = proc.addBlock();
7976 BasicBlock* elseCase = proc.addBlock();
7977
7978 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
7979 Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
7980 Value* equalOrUnordered = root->appendNew<Value>(
7981 proc, EqualOrUnordered, Origin(),
7982 argumentA,
7983 argumentB);
7984 Value* notEqualAndOrdered = root->appendNew<Value>(
7985 proc, Equal, Origin(),
7986 root->appendNew<Const32Value>(proc, Origin(), 0),
7987 equalOrUnordered);
7988 root->appendNewControlValue(
7989 proc, Branch, Origin(),
7990 notEqualAndOrdered,
7991 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
7992
7993 thenCase->appendNewControlValue(
7994 proc, Return, Origin(),
7995 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
7996
7997 elseCase->appendNewControlValue(
7998 proc, Return, Origin(),
7999 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
8000
8001 int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
8002 CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
8003}
8004
8005void testBranchNotEqualAndOrderedArgs(float a, float b)
8006{
8007 Procedure proc;
8008 BasicBlock* root = proc.addBlock();
8009 BasicBlock* thenCase = proc.addBlock();
8010 BasicBlock* elseCase = proc.addBlock();
8011
8012 Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
8013 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
8014 Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
8015 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
8016 Value* equalOrUnordered = root->appendNew<Value>(
8017 proc, EqualOrUnordered, Origin(),
8018 argumentA,
8019 argumentB);
8020 Value* notEqualAndOrdered = root->appendNew<Value>(
8021 proc, Equal, Origin(),
8022 root->appendNew<Const32Value>(proc, Origin(), 0),
8023 equalOrUnordered);
8024 root->appendNewControlValue(
8025 proc, Branch, Origin(),
8026 notEqualAndOrdered,
8027 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8028
8029 thenCase->appendNewControlValue(
8030 proc, Return, Origin(),
8031 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
8032
8033 elseCase->appendNewControlValue(
8034 proc, Return, Origin(),
8035 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
8036
8037 int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
8038 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
8039}
8040
8041void testBranchEqualOrUnorderedDoubleArgImm(double a, double b)
8042{
8043 Procedure proc;
8044 BasicBlock* root = proc.addBlock();
8045 BasicBlock* thenCase = proc.addBlock();
8046 BasicBlock* elseCase = proc.addBlock();
8047
8048 Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
8049 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
8050 root->appendNewControlValue(
8051 proc, Branch, Origin(),
8052 root->appendNew<Value>(
8053 proc, EqualOrUnordered, Origin(),
8054 argumentA,
8055 argumentB),
8056 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8057
8058 thenCase->appendNewControlValue(
8059 proc, Return, Origin(),
8060 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
8061
8062 elseCase->appendNewControlValue(
8063 proc, Return, Origin(),
8064 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
8065
8066 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
8067 CHECK(compileAndRun<int64_t>(proc, a) == expected);
8068}
8069
8070void testBranchEqualOrUnorderedFloatArgImm(float a, float b)
8071{
8072 Procedure proc;
8073 BasicBlock* root = proc.addBlock();
8074 BasicBlock* thenCase = proc.addBlock();
8075 BasicBlock* elseCase = proc.addBlock();
8076
8077 Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
8078 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
8079 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
8080
8081 root->appendNewControlValue(
8082 proc, Branch, Origin(),
8083 root->appendNew<Value>(
8084 proc, EqualOrUnordered, Origin(),
8085 argumentA,
8086 argumentB),
8087 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8088
8089 thenCase->appendNewControlValue(
8090 proc, Return, Origin(),
8091 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
8092
8093 elseCase->appendNewControlValue(
8094 proc, Return, Origin(),
8095 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
8096
8097 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
8098 CHECK(compileAndRun<int64_t>(proc, &a) == expected);
8099}
8100
8101void testBranchEqualOrUnorderedDoubleImms(double a, double b)
8102{
8103 Procedure proc;
8104 BasicBlock* root = proc.addBlock();
8105 BasicBlock* thenCase = proc.addBlock();
8106 BasicBlock* elseCase = proc.addBlock();
8107
8108 Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
8109 Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
8110 root->appendNewControlValue(
8111 proc, Branch, Origin(),
8112 root->appendNew<Value>(
8113 proc, EqualOrUnordered, Origin(),
8114 argumentA,
8115 argumentB),
8116 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8117
8118 thenCase->appendNewControlValue(
8119 proc, Return, Origin(),
8120 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
8121
8122 elseCase->appendNewControlValue(
8123 proc, Return, Origin(),
8124 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
8125
8126 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
8127 CHECK(compileAndRun<int64_t>(proc) == expected);
8128}
8129
8130void testBranchEqualOrUnorderedFloatImms(float a, float b)
8131{
8132 Procedure proc;
8133 BasicBlock* root = proc.addBlock();
8134 BasicBlock* thenCase = proc.addBlock();
8135 BasicBlock* elseCase = proc.addBlock();
8136
8137 Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
8138 Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
8139
8140 root->appendNewControlValue(
8141 proc, Branch, Origin(),
8142 root->appendNew<Value>(
8143 proc, EqualOrUnordered, Origin(),
8144 argumentA,
8145 argumentB),
8146 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8147
8148 thenCase->appendNewControlValue(
8149 proc, Return, Origin(),
8150 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
8151
8152 elseCase->appendNewControlValue(
8153 proc, Return, Origin(),
8154 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
8155
8156 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
8157 CHECK(compileAndRun<int64_t>(proc) == expected);
8158}
8159
8160void testBranchEqualOrUnorderedFloatWithUselessDoubleConversion(float a, float b)
8161{
8162 Procedure proc;
8163 BasicBlock* root = proc.addBlock();
8164 BasicBlock* thenCase = proc.addBlock();
8165 BasicBlock* elseCase = proc.addBlock();
8166
8167 Value* argument1 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
8168 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
8169 Value* argument2 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
8170 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
8171 Value* argument1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument1);
8172 Value* argument2AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument2);
8173
8174 root->appendNewControlValue(
8175 proc, Branch, Origin(),
8176 root->appendNew<Value>(
8177 proc, EqualOrUnordered, Origin(),
8178 argument1AsDouble,
8179 argument2AsDouble),
8180 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8181
8182 thenCase->appendNewControlValue(
8183 proc, Return, Origin(),
8184 thenCase->appendNew<Const32Value>(proc, Origin(), 42));
8185
8186 elseCase->appendNewControlValue(
8187 proc, Return, Origin(),
8188 elseCase->appendNew<Const32Value>(proc, Origin(), -13));
8189
8190 int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
8191 CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
8192}
8193
8194void testBranchFold(int value)
8195{
8196 Procedure proc;
8197 BasicBlock* root = proc.addBlock();
8198 BasicBlock* thenCase = proc.addBlock();
8199 BasicBlock* elseCase = proc.addBlock();
8200
8201 root->appendNewControlValue(
8202 proc, Branch, Origin(),
8203 root->appendNew<Const32Value>(proc, Origin(), value),
8204 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8205
8206 thenCase->appendNewControlValue(
8207 proc, Return, Origin(),
8208 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8209
8210 elseCase->appendNewControlValue(
8211 proc, Return, Origin(),
8212 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8213
8214 CHECK(compileAndRun<int>(proc) == !!value);
8215}
8216
8217void testDiamondFold(int value)
8218{
8219 Procedure proc;
8220 BasicBlock* root = proc.addBlock();
8221 BasicBlock* thenCase = proc.addBlock();
8222 BasicBlock* elseCase = proc.addBlock();
8223 BasicBlock* done = proc.addBlock();
8224
8225 root->appendNewControlValue(
8226 proc, Branch, Origin(),
8227 root->appendNew<Const32Value>(proc, Origin(), value),
8228 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8229
8230 UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(
8231 proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8232 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
8233
8234 UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(
8235 proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8236 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done));
8237
8238 Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin());
8239 thenResult->setPhi(phi);
8240 elseResult->setPhi(phi);
8241 done->appendNewControlValue(proc, Return, Origin(), phi);
8242
8243 CHECK(compileAndRun<int>(proc) == !!value);
8244}
8245
8246void testBranchNotEqualFoldPtr(intptr_t value)
8247{
8248 Procedure proc;
8249 BasicBlock* root = proc.addBlock();
8250 BasicBlock* thenCase = proc.addBlock();
8251 BasicBlock* elseCase = proc.addBlock();
8252
8253 root->appendNewControlValue(
8254 proc, Branch, Origin(),
8255 root->appendNew<Value>(
8256 proc, NotEqual, Origin(),
8257 root->appendNew<ConstPtrValue>(proc, Origin(), value),
8258 root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
8259 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8260
8261 thenCase->appendNewControlValue(
8262 proc, Return, Origin(),
8263 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8264
8265 elseCase->appendNewControlValue(
8266 proc, Return, Origin(),
8267 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8268
8269 CHECK(compileAndRun<int>(proc) == !!value);
8270}
8271
8272void testBranchEqualFoldPtr(intptr_t value)
8273{
8274 Procedure proc;
8275 BasicBlock* root = proc.addBlock();
8276 BasicBlock* thenCase = proc.addBlock();
8277 BasicBlock* elseCase = proc.addBlock();
8278
8279 root->appendNewControlValue(
8280 proc, Branch, Origin(),
8281 root->appendNew<Value>(
8282 proc, Equal, Origin(),
8283 root->appendNew<ConstPtrValue>(proc, Origin(), value),
8284 root->appendNew<ConstPtrValue>(proc, Origin(), 0)),
8285 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8286
8287 thenCase->appendNewControlValue(
8288 proc, Return, Origin(),
8289 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8290
8291 elseCase->appendNewControlValue(
8292 proc, Return, Origin(),
8293 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8294
8295 CHECK(compileAndRun<int>(proc) == !value);
8296}
8297
8298void testBranchLoadPtr()
8299{
8300 Procedure proc;
8301 BasicBlock* root = proc.addBlock();
8302 BasicBlock* thenCase = proc.addBlock();
8303 BasicBlock* elseCase = proc.addBlock();
8304
8305 root->appendNewControlValue(
8306 proc, Branch, Origin(),
8307 root->appendNew<MemoryValue>(
8308 proc, Load, pointerType(), Origin(),
8309 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
8310 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8311
8312 thenCase->appendNewControlValue(
8313 proc, Return, Origin(),
8314 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8315
8316 elseCase->appendNewControlValue(
8317 proc, Return, Origin(),
8318 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8319
8320 auto code = compileProc(proc);
8321 intptr_t cond;
8322 cond = 42;
8323 CHECK(invoke<int>(*code, &cond) == 1);
8324 cond = 0;
8325 CHECK(invoke<int>(*code, &cond) == 0);
8326}
8327
8328void testBranchLoad32()
8329{
8330 Procedure proc;
8331 BasicBlock* root = proc.addBlock();
8332 BasicBlock* thenCase = proc.addBlock();
8333 BasicBlock* elseCase = proc.addBlock();
8334
8335 root->appendNewControlValue(
8336 proc, Branch, Origin(),
8337 root->appendNew<MemoryValue>(
8338 proc, Load, Int32, Origin(),
8339 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
8340 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8341
8342 thenCase->appendNewControlValue(
8343 proc, Return, Origin(),
8344 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8345
8346 elseCase->appendNewControlValue(
8347 proc, Return, Origin(),
8348 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8349
8350 auto code = compileProc(proc);
8351 int32_t cond;
8352 cond = 42;
8353 CHECK(invoke<int>(*code, &cond) == 1);
8354 cond = 0;
8355 CHECK(invoke<int>(*code, &cond) == 0);
8356}
8357
8358void testBranchLoad8S()
8359{
8360 Procedure proc;
8361 BasicBlock* root = proc.addBlock();
8362 BasicBlock* thenCase = proc.addBlock();
8363 BasicBlock* elseCase = proc.addBlock();
8364
8365 root->appendNewControlValue(
8366 proc, Branch, Origin(),
8367 root->appendNew<MemoryValue>(
8368 proc, Load8S, Origin(),
8369 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
8370 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8371
8372 thenCase->appendNewControlValue(
8373 proc, Return, Origin(),
8374 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8375
8376 elseCase->appendNewControlValue(
8377 proc, Return, Origin(),
8378 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8379
8380 auto code = compileProc(proc);
8381 int8_t cond;
8382 cond = -1;
8383 CHECK(invoke<int>(*code, &cond) == 1);
8384 cond = 0;
8385 CHECK(invoke<int>(*code, &cond) == 0);
8386}
8387
8388void testBranchLoad8Z()
8389{
8390 Procedure proc;
8391 BasicBlock* root = proc.addBlock();
8392 BasicBlock* thenCase = proc.addBlock();
8393 BasicBlock* elseCase = proc.addBlock();
8394
8395 root->appendNewControlValue(
8396 proc, Branch, Origin(),
8397 root->appendNew<MemoryValue>(
8398 proc, Load8Z, Origin(),
8399 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
8400 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8401
8402 thenCase->appendNewControlValue(
8403 proc, Return, Origin(),
8404 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8405
8406 elseCase->appendNewControlValue(
8407 proc, Return, Origin(),
8408 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8409
8410 auto code = compileProc(proc);
8411 uint8_t cond;
8412 cond = 1;
8413 CHECK(invoke<int>(*code, &cond) == 1);
8414 cond = 0;
8415 CHECK(invoke<int>(*code, &cond) == 0);
8416}
8417
8418void testBranchLoad16S()
8419{
8420 Procedure proc;
8421 BasicBlock* root = proc.addBlock();
8422 BasicBlock* thenCase = proc.addBlock();
8423 BasicBlock* elseCase = proc.addBlock();
8424
8425 root->appendNewControlValue(
8426 proc, Branch, Origin(),
8427 root->appendNew<MemoryValue>(
8428 proc, Load16S, Origin(),
8429 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
8430 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8431
8432 thenCase->appendNewControlValue(
8433 proc, Return, Origin(),
8434 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8435
8436 elseCase->appendNewControlValue(
8437 proc, Return, Origin(),
8438 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8439
8440 auto code = compileProc(proc);
8441 int16_t cond;
8442 cond = -1;
8443 CHECK(invoke<int>(*code, &cond) == 1);
8444 cond = 0;
8445 CHECK(invoke<int>(*code, &cond) == 0);
8446}
8447
8448void testBranchLoad16Z()
8449{
8450 Procedure proc;
8451 BasicBlock* root = proc.addBlock();
8452 BasicBlock* thenCase = proc.addBlock();
8453 BasicBlock* elseCase = proc.addBlock();
8454
8455 root->appendNewControlValue(
8456 proc, Branch, Origin(),
8457 root->appendNew<MemoryValue>(
8458 proc, Load16Z, Origin(),
8459 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
8460 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8461
8462 thenCase->appendNewControlValue(
8463 proc, Return, Origin(),
8464 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8465
8466 elseCase->appendNewControlValue(
8467 proc, Return, Origin(),
8468 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8469
8470 auto code = compileProc(proc);
8471 uint16_t cond;
8472 cond = 1;
8473 CHECK(invoke<int>(*code, &cond) == 1);
8474 cond = 0;
8475 CHECK(invoke<int>(*code, &cond) == 0);
8476}
8477
8478void testBranch8WithLoad8ZIndex()
8479{
8480 Procedure proc;
8481 BasicBlock* root = proc.addBlock();
8482 BasicBlock* thenCase = proc.addBlock();
8483 BasicBlock* elseCase = proc.addBlock();
8484
8485 int logScale = 1;
8486 root->appendNewControlValue(
8487 proc, Branch, Origin(),
8488 root->appendNew<Value>(
8489 proc, Above, Origin(),
8490 root->appendNew<MemoryValue>(
8491 proc, Load8Z, Origin(),
8492 root->appendNew<Value>(
8493 proc, Add, Origin(),
8494 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
8495 root->appendNew<Value>(
8496 proc, Shl, Origin(),
8497 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
8498 root->appendNew<Const32Value>(proc, Origin(), logScale)))),
8499 root->appendNew<Const32Value>(proc, Origin(), 250)),
8500 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
8501
8502 thenCase->appendNewControlValue(
8503 proc, Return, Origin(),
8504 thenCase->appendNew<Const32Value>(proc, Origin(), 1));
8505
8506 elseCase->appendNewControlValue(
8507 proc, Return, Origin(),
8508 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
8509
8510 auto code = compileProc(proc);
8511 uint32_t cond;
8512 cond = 0xffffffffU; // All bytes are 0xff.
8513 CHECK(invoke<int>(*code, &cond - 2, (sizeof(uint32_t) * 2) >> logScale) == 1);
8514 cond = 0x00000000U; // All bytes are 0.
8515 CHECK(invoke<int>(*code, &cond - 2, (sizeof(uint32_t) * 2) >> logScale) == 0);
8516}
8517
8518void testComplex(unsigned numVars, unsigned numConstructs)
8519{
8520 MonotonicTime before = MonotonicTime::now();
8521
8522 Procedure proc;
8523 BasicBlock* current = proc.addBlock();
8524
8525 Const32Value* one = current->appendNew<Const32Value>(proc, Origin(), 1);
8526
8527 Vector<int32_t> varSlots;
8528 for (unsigned i = numVars; i--;)
8529 varSlots.append(i);
8530
8531 Vector<Value*> vars;
8532 for (int32_t& varSlot : varSlots) {
8533 Value* varSlotPtr = current->appendNew<ConstPtrValue>(proc, Origin(), &varSlot);
8534 vars.append(current->appendNew<MemoryValue>(proc, Load, Int32, Origin(), varSlotPtr));
8535 }
8536
8537 for (unsigned i = 0; i < numConstructs; ++i) {
8538 if (i & 1) {
8539 // Control flow diamond.
8540 unsigned predicateVarIndex = ((i >> 1) + 2) % numVars;
8541 unsigned thenIncVarIndex = ((i >> 1) + 0) % numVars;
8542 unsigned elseIncVarIndex = ((i >> 1) + 1) % numVars;
8543
8544 BasicBlock* thenBlock = proc.addBlock();
8545 BasicBlock* elseBlock = proc.addBlock();
8546 BasicBlock* continuation = proc.addBlock();
8547
8548 current->appendNewControlValue(
8549 proc, Branch, Origin(), vars[predicateVarIndex],
8550 FrequentedBlock(thenBlock), FrequentedBlock(elseBlock));
8551
8552 UpsilonValue* thenThenResult = thenBlock->appendNew<UpsilonValue>(
8553 proc, Origin(),
8554 thenBlock->appendNew<Value>(proc, Add, Origin(), vars[thenIncVarIndex], one));
8555 UpsilonValue* thenElseResult = thenBlock->appendNew<UpsilonValue>(
8556 proc, Origin(), vars[elseIncVarIndex]);
8557 thenBlock->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
8558
8559 UpsilonValue* elseElseResult = elseBlock->appendNew<UpsilonValue>(
8560 proc, Origin(),
8561 elseBlock->appendNew<Value>(proc, Add, Origin(), vars[elseIncVarIndex], one));
8562 UpsilonValue* elseThenResult = elseBlock->appendNew<UpsilonValue>(
8563 proc, Origin(), vars[thenIncVarIndex]);
8564 elseBlock->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
8565
8566 Value* thenPhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
8567 thenThenResult->setPhi(thenPhi);
8568 elseThenResult->setPhi(thenPhi);
8569 vars[thenIncVarIndex] = thenPhi;
8570
8571 Value* elsePhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
8572 thenElseResult->setPhi(elsePhi);
8573 elseElseResult->setPhi(elsePhi);
8574 vars[elseIncVarIndex] = thenPhi;
8575
8576 current = continuation;
8577 } else {
8578 // Loop.
8579
8580 BasicBlock* loopEntry = proc.addBlock();
8581 BasicBlock* loopReentry = proc.addBlock();
8582 BasicBlock* loopBody = proc.addBlock();
8583 BasicBlock* loopExit = proc.addBlock();
8584 BasicBlock* loopSkip = proc.addBlock();
8585 BasicBlock* continuation = proc.addBlock();
8586
8587 Value* startIndex = vars[((i >> 1) + 1) % numVars];
8588 Value* startSum = current->appendNew<Const32Value>(proc, Origin(), 0);
8589 current->appendNewControlValue(
8590 proc, Branch, Origin(), startIndex,
8591 FrequentedBlock(loopEntry), FrequentedBlock(loopSkip));
8592
8593 UpsilonValue* startIndexForBody = loopEntry->appendNew<UpsilonValue>(
8594 proc, Origin(), startIndex);
8595 UpsilonValue* startSumForBody = loopEntry->appendNew<UpsilonValue>(
8596 proc, Origin(), startSum);
8597 loopEntry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody));
8598
8599 Value* bodyIndex = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
8600 startIndexForBody->setPhi(bodyIndex);
8601 Value* bodySum = loopBody->appendNew<Value>(proc, Phi, Int32, Origin());
8602 startSumForBody->setPhi(bodySum);
8603 Value* newBodyIndex = loopBody->appendNew<Value>(proc, Sub, Origin(), bodyIndex, one);
8604 Value* newBodySum = loopBody->appendNew<Value>(
8605 proc, Add, Origin(),
8606 bodySum,
8607 loopBody->appendNew<MemoryValue>(
8608 proc, Load, Int32, Origin(),
8609 loopBody->appendNew<Value>(
8610 proc, Add, Origin(),
8611 loopBody->appendNew<ConstPtrValue>(proc, Origin(), varSlots.data()),
8612 loopBody->appendNew<Value>(
8613 proc, Shl, Origin(),
8614 loopBody->appendNew<Value>(
8615 proc, ZExt32, Origin(),
8616 loopBody->appendNew<Value>(
8617 proc, BitAnd, Origin(),
8618 newBodyIndex,
8619 loopBody->appendNew<Const32Value>(
8620 proc, Origin(), numVars - 1))),
8621 loopBody->appendNew<Const32Value>(proc, Origin(), 2)))));
8622 loopBody->appendNewControlValue(
8623 proc, Branch, Origin(), newBodyIndex,
8624 FrequentedBlock(loopReentry), FrequentedBlock(loopExit));
8625
8626 loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodyIndex, bodyIndex);
8627 loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodySum, bodySum);
8628 loopReentry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody));
8629
8630 UpsilonValue* exitSum = loopExit->appendNew<UpsilonValue>(proc, Origin(), newBodySum);
8631 loopExit->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
8632
8633 UpsilonValue* skipSum = loopSkip->appendNew<UpsilonValue>(proc, Origin(), startSum);
8634 loopSkip->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation));
8635
8636 Value* finalSum = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
8637 exitSum->setPhi(finalSum);
8638 skipSum->setPhi(finalSum);
8639
8640 current = continuation;
8641 vars[((i >> 1) + 0) % numVars] = finalSum;
8642 }
8643 }
8644
8645 current->appendNewControlValue(proc, Return, Origin(), vars[0]);
8646
8647 compileProc(proc);
8648
8649 MonotonicTime after = MonotonicTime::now();
8650 dataLog(toCString(" That took ", (after - before).milliseconds(), " ms.\n"));
8651}
8652
8653void testSimplePatchpoint()
8654{
8655 Procedure proc;
8656 BasicBlock* root = proc.addBlock();
8657 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8658 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8659 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
8660 patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
8661 patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
8662 patchpoint->setGenerator(
8663 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8664 AllowMacroScratchRegisterUsage allowScratch(jit);
8665 CHECK(params.size() == 3);
8666 CHECK(params[0].isGPR());
8667 CHECK(params[1].isGPR());
8668 CHECK(params[2].isGPR());
8669 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
8670 });
8671 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
8672
8673 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
8674}
8675
8676void testSimplePatchpointWithoutOuputClobbersGPArgs()
8677{
8678 Procedure proc;
8679 BasicBlock* root = proc.addBlock();
8680 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8681 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8682 Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42);
8683 Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
8684
8685 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
8686 patchpoint->clobberLate(RegisterSet(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1));
8687 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
8688 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
8689 patchpoint->setGenerator(
8690 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8691 AllowMacroScratchRegisterUsage allowScratch(jit);
8692 CHECK(params.size() == 2);
8693 CHECK(params[0].isGPR());
8694 CHECK(params[1].isGPR());
8695 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params[0].gpr());
8696 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params[1].gpr());
8697 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR0);
8698 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR1);
8699 });
8700
8701 Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
8702 root->appendNewControlValue(proc, Return, Origin(), result);
8703
8704 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
8705}
8706
8707void testSimplePatchpointWithOuputClobbersGPArgs()
8708{
8709 // We can't predict where the output will be but we want to be sure it is not
8710 // one of the clobbered registers which is a bit hard to test.
8711 //
8712 // What we do is force the hand of our register allocator by clobbering absolutely
8713 // everything but 1. The only valid allocation is to give it to the result and
8714 // spill everything else.
8715
8716 Procedure proc;
8717 if (proc.optLevel() < 1) {
8718 // FIXME: Air O0 allocator can't handle such programs. We rely on WasmAirIRGenerator
8719 // to not use any such constructs where the register allocator is cornered in such
8720 // a way.
8721 // https://bugs.webkit.org/show_bug.cgi?id=194633
8722 return;
8723 }
8724 BasicBlock* root = proc.addBlock();
8725 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8726 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8727 Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42);
8728 Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13);
8729
8730 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int64, Origin());
8731
8732 RegisterSet clobberAll = RegisterSet::allGPRs();
8733 clobberAll.exclude(RegisterSet::stackRegisters());
8734 clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
8735 clobberAll.clear(GPRInfo::argumentGPR2);
8736 patchpoint->clobberLate(clobberAll);
8737
8738 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
8739 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
8740
8741 patchpoint->setGenerator(
8742 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8743 AllowMacroScratchRegisterUsage allowScratch(jit);
8744 CHECK(params.size() == 3);
8745 CHECK(params[0].isGPR());
8746 CHECK(params[1].isGPR());
8747 CHECK(params[2].isGPR());
8748 jit.move(params[1].gpr(), params[0].gpr());
8749 jit.add64(params[2].gpr(), params[0].gpr());
8750
8751 clobberAll.forEach([&] (Reg reg) {
8752 jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), reg.gpr());
8753 });
8754 });
8755
8756 Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint,
8757 root->appendNew<Value>(proc, Add, Origin(), arg1, arg2));
8758 root->appendNewControlValue(proc, Return, Origin(), result);
8759
8760 CHECK(compileAndRun<int>(proc, 1, 2) == 58);
8761}
8762
8763void testSimplePatchpointWithoutOuputClobbersFPArgs()
8764{
8765 Procedure proc;
8766 BasicBlock* root = proc.addBlock();
8767 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
8768 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
8769 Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
8770 Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
8771
8772 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
8773 patchpoint->clobberLate(RegisterSet(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1));
8774 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
8775 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
8776 patchpoint->setGenerator(
8777 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8778 AllowMacroScratchRegisterUsage allowScratch(jit);
8779 CHECK(params.size() == 2);
8780 CHECK(params[0].isFPR());
8781 CHECK(params[1].isFPR());
8782 jit.moveZeroToDouble(params[0].fpr());
8783 jit.moveZeroToDouble(params[1].fpr());
8784 jit.moveZeroToDouble(FPRInfo::argumentFPR0);
8785 jit.moveZeroToDouble(FPRInfo::argumentFPR1);
8786 });
8787
8788 Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2);
8789 root->appendNewControlValue(proc, Return, Origin(), result);
8790
8791 CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 4);
8792}
8793
8794void testSimplePatchpointWithOuputClobbersFPArgs()
8795{
8796 Procedure proc;
8797 if (proc.optLevel() < 1) {
8798 // FIXME: Air O0 allocator can't handle such programs. We rely on WasmAirIRGenerator
8799 // to not use any such constructs where the register allocator is cornered in such
8800 // a way.
8801 // https://bugs.webkit.org/show_bug.cgi?id=194633
8802 return;
8803 }
8804 BasicBlock* root = proc.addBlock();
8805 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
8806 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
8807 Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
8808 Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1);
8809
8810 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin());
8811
8812 RegisterSet clobberAll = RegisterSet::allFPRs();
8813 clobberAll.exclude(RegisterSet::stackRegisters());
8814 clobberAll.exclude(RegisterSet::reservedHardwareRegisters());
8815 clobberAll.clear(FPRInfo::argumentFPR2);
8816 patchpoint->clobberLate(clobberAll);
8817
8818 patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister));
8819 patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister));
8820
8821 patchpoint->setGenerator(
8822 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8823 AllowMacroScratchRegisterUsage allowScratch(jit);
8824 CHECK(params.size() == 3);
8825 CHECK(params[0].isFPR());
8826 CHECK(params[1].isFPR());
8827 CHECK(params[2].isFPR());
8828 jit.addDouble(params[1].fpr(), params[2].fpr(), params[0].fpr());
8829
8830 clobberAll.forEach([&] (Reg reg) {
8831 jit.moveZeroToDouble(reg.fpr());
8832 });
8833 });
8834
8835 Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint,
8836 root->appendNew<Value>(proc, Add, Origin(), arg1, arg2));
8837 root->appendNewControlValue(proc, Return, Origin(), result);
8838
8839 CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 59.6);
8840}
8841
8842void testPatchpointWithEarlyClobber()
8843{
8844 auto test = [] (GPRReg registerToClobber, bool arg1InArgGPR, bool arg2InArgGPR) {
8845 Procedure proc;
8846 BasicBlock* root = proc.addBlock();
8847 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8848 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8849
8850 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
8851 patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
8852 patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
8853 patchpoint->clobberEarly(RegisterSet(registerToClobber));
8854 unsigned optLevel = proc.optLevel();
8855 patchpoint->setGenerator(
8856 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8857 if (optLevel > 1) {
8858 CHECK((params[1].gpr() == GPRInfo::argumentGPR0) == arg1InArgGPR);
8859 CHECK((params[2].gpr() == GPRInfo::argumentGPR1) == arg2InArgGPR);
8860 }
8861
8862 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
8863 });
8864
8865 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
8866
8867 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
8868 };
8869
8870 test(GPRInfo::nonArgGPR0, true, true);
8871 test(GPRInfo::argumentGPR0, false, true);
8872 test(GPRInfo::argumentGPR1, true, false);
8873}
8874
8875void testPatchpointCallArg()
8876{
8877 Procedure proc;
8878 BasicBlock* root = proc.addBlock();
8879 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8880 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8881 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
8882 patchpoint->append(ConstrainedValue(arg1, ValueRep::stackArgument(0)));
8883 patchpoint->append(ConstrainedValue(arg2, ValueRep::stackArgument(8)));
8884 patchpoint->setGenerator(
8885 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8886 AllowMacroScratchRegisterUsage allowScratch(jit);
8887 CHECK(params.size() == 3);
8888 CHECK(params[0].isGPR());
8889 CHECK(params[1].isStack());
8890 CHECK(params[2].isStack());
8891 jit.load32(
8892 CCallHelpers::Address(GPRInfo::callFrameRegister, params[1].offsetFromFP()),
8893 params[0].gpr());
8894 jit.add32(
8895 CCallHelpers::Address(GPRInfo::callFrameRegister, params[2].offsetFromFP()),
8896 params[0].gpr());
8897 });
8898 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
8899
8900 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
8901}
8902
8903void testPatchpointFixedRegister()
8904{
8905 Procedure proc;
8906 BasicBlock* root = proc.addBlock();
8907 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8908 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8909 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
8910 patchpoint->append(ConstrainedValue(arg1, ValueRep(GPRInfo::regT0)));
8911 patchpoint->append(ConstrainedValue(arg2, ValueRep(GPRInfo::regT1)));
8912 patchpoint->setGenerator(
8913 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8914 AllowMacroScratchRegisterUsage allowScratch(jit);
8915 CHECK(params.size() == 3);
8916 CHECK(params[0].isGPR());
8917 CHECK(params[1] == ValueRep(GPRInfo::regT0));
8918 CHECK(params[2] == ValueRep(GPRInfo::regT1));
8919 add32(jit, GPRInfo::regT0, GPRInfo::regT1, params[0].gpr());
8920 });
8921 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
8922
8923 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
8924}
8925
8926void testPatchpointAny(ValueRep rep)
8927{
8928 Procedure proc;
8929 BasicBlock* root = proc.addBlock();
8930 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8931 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8932 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
8933 patchpoint->append(ConstrainedValue(arg1, rep));
8934 patchpoint->append(ConstrainedValue(arg2, rep));
8935 patchpoint->setGenerator(
8936 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8937 AllowMacroScratchRegisterUsage allowScratch(jit);
8938 // We shouldn't have spilled the inputs, so we assert that they're in registers.
8939 CHECK(params.size() == 3);
8940 CHECK(params[0].isGPR());
8941 CHECK(params[1].isGPR());
8942 CHECK(params[2].isGPR());
8943 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
8944 });
8945 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
8946
8947 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
8948}
8949
8950void testPatchpointGPScratch()
8951{
8952 Procedure proc;
8953 BasicBlock* root = proc.addBlock();
8954 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8955 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8956 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
8957 patchpoint->append(arg1, ValueRep::SomeRegister);
8958 patchpoint->append(arg2, ValueRep::SomeRegister);
8959 patchpoint->numGPScratchRegisters = 2;
8960 patchpoint->setGenerator(
8961 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8962 AllowMacroScratchRegisterUsage allowScratch(jit);
8963 // We shouldn't have spilled the inputs, so we assert that they're in registers.
8964 CHECK(params.size() == 3);
8965 CHECK(params[0].isGPR());
8966 CHECK(params[1].isGPR());
8967 CHECK(params[2].isGPR());
8968 CHECK(params.gpScratch(0) != InvalidGPRReg);
8969 CHECK(params.gpScratch(0) != params[0].gpr());
8970 CHECK(params.gpScratch(0) != params[1].gpr());
8971 CHECK(params.gpScratch(0) != params[2].gpr());
8972 CHECK(params.gpScratch(1) != InvalidGPRReg);
8973 CHECK(params.gpScratch(1) != params.gpScratch(0));
8974 CHECK(params.gpScratch(1) != params[0].gpr());
8975 CHECK(params.gpScratch(1) != params[1].gpr());
8976 CHECK(params.gpScratch(1) != params[2].gpr());
8977 CHECK(!params.unavailableRegisters().get(params.gpScratch(0)));
8978 CHECK(!params.unavailableRegisters().get(params.gpScratch(1)));
8979 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
8980 });
8981 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
8982
8983 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
8984}
8985
8986void testPatchpointFPScratch()
8987{
8988 Procedure proc;
8989 BasicBlock* root = proc.addBlock();
8990 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
8991 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
8992 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
8993 patchpoint->append(arg1, ValueRep::SomeRegister);
8994 patchpoint->append(arg2, ValueRep::SomeRegister);
8995 patchpoint->numFPScratchRegisters = 2;
8996 patchpoint->setGenerator(
8997 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8998 AllowMacroScratchRegisterUsage allowScratch(jit);
8999 // We shouldn't have spilled the inputs, so we assert that they're in registers.
9000 CHECK(params.size() == 3);
9001 CHECK(params[0].isGPR());
9002 CHECK(params[1].isGPR());
9003 CHECK(params[2].isGPR());
9004 CHECK(params.fpScratch(0) != InvalidFPRReg);
9005 CHECK(params.fpScratch(1) != InvalidFPRReg);
9006 CHECK(params.fpScratch(1) != params.fpScratch(0));
9007 CHECK(!params.unavailableRegisters().get(params.fpScratch(0)));
9008 CHECK(!params.unavailableRegisters().get(params.fpScratch(1)));
9009 add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr());
9010 });
9011 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
9012
9013 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
9014}
9015
9016void testPatchpointLotsOfLateAnys()
9017{
9018 Procedure proc;
9019 BasicBlock* root = proc.addBlock();
9020 Vector<int> things;
9021 for (unsigned i = 200; i--;)
9022 things.append(i);
9023
9024 Vector<Value*> values;
9025 for (int& thing : things) {
9026 Value* value = root->appendNew<MemoryValue>(
9027 proc, Load, Int32, Origin(),
9028 root->appendNew<ConstPtrValue>(proc, Origin(), &thing));
9029 values.append(value);
9030 }
9031
9032 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
9033 patchpoint->clobber(RegisterSet::macroScratchRegisters());
9034 for (Value* value : values)
9035 patchpoint->append(ConstrainedValue(value, ValueRep::LateColdAny));
9036 patchpoint->setGenerator(
9037 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9038 AllowMacroScratchRegisterUsage allowScratch(jit);
9039 // We shouldn't have spilled the inputs, so we assert that they're in registers.
9040 CHECK(params.size() == things.size() + 1);
9041 CHECK(params[0].isGPR());
9042 jit.move(CCallHelpers::TrustedImm32(0), params[0].gpr());
9043 for (unsigned i = 1; i < params.size(); ++i) {
9044 if (params[i].isGPR()) {
9045 CHECK(params[i] != params[0]);
9046 jit.add32(params[i].gpr(), params[0].gpr());
9047 } else {
9048 CHECK(params[i].isStack());
9049 jit.add32(CCallHelpers::Address(GPRInfo::callFrameRegister, params[i].offsetFromFP()), params[0].gpr());
9050 }
9051 }
9052 });
9053 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
9054
9055 CHECK(static_cast<size_t>(compileAndRun<int>(proc)) == (things.size() * (things.size() - 1)) / 2);
9056}
9057
9058void testPatchpointAnyImm(ValueRep rep)
9059{
9060 Procedure proc;
9061 BasicBlock* root = proc.addBlock();
9062 Value* arg1 = root->appendNew<Value>(
9063 proc, Trunc, Origin(),
9064 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9065 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
9066 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
9067 patchpoint->append(ConstrainedValue(arg1, rep));
9068 patchpoint->append(ConstrainedValue(arg2, rep));
9069 patchpoint->setGenerator(
9070 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9071 AllowMacroScratchRegisterUsage allowScratch(jit);
9072 CHECK(params.size() == 3);
9073 CHECK(params[0].isGPR());
9074 CHECK(params[1].isGPR());
9075 CHECK(params[2].isConstant());
9076 CHECK(params[2].value() == 42);
9077 jit.add32(
9078 CCallHelpers::TrustedImm32(static_cast<int32_t>(params[2].value())),
9079 params[1].gpr(), params[0].gpr());
9080 });
9081 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
9082
9083 CHECK(compileAndRun<int>(proc, 1) == 43);
9084}
9085
9086void testPatchpointManyImms()
9087{
9088 Procedure proc;
9089 BasicBlock* root = proc.addBlock();
9090 Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), 42);
9091 Value* arg2 = root->appendNew<Const64Value>(proc, Origin(), 43);
9092 Value* arg3 = root->appendNew<Const64Value>(proc, Origin(), 43000000000000ll);
9093 Value* arg4 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5);
9094 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
9095 patchpoint->append(ConstrainedValue(arg1, ValueRep::WarmAny));
9096 patchpoint->append(ConstrainedValue(arg2, ValueRep::WarmAny));
9097 patchpoint->append(ConstrainedValue(arg3, ValueRep::WarmAny));
9098 patchpoint->append(ConstrainedValue(arg4, ValueRep::WarmAny));
9099 patchpoint->setGenerator(
9100 [&] (CCallHelpers&, const StackmapGenerationParams& params) {
9101 CHECK(params.size() == 4);
9102 CHECK(params[0] == ValueRep::constant(42));
9103 CHECK(params[1] == ValueRep::constant(43));
9104 CHECK(params[2] == ValueRep::constant(43000000000000ll));
9105 CHECK(params[3] == ValueRep::constant(bitwise_cast<int64_t>(42.5)));
9106 });
9107 root->appendNewControlValue(
9108 proc, Return, Origin(),
9109 root->appendNew<Const32Value>(proc, Origin(), 0));
9110
9111 CHECK(!compileAndRun<int>(proc));
9112}
9113
9114void testPatchpointWithRegisterResult()
9115{
9116 Procedure proc;
9117 BasicBlock* root = proc.addBlock();
9118 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9119 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
9120 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
9121 patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
9122 patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
9123 patchpoint->resultConstraint = ValueRep::reg(GPRInfo::nonArgGPR0);
9124 patchpoint->setGenerator(
9125 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9126 AllowMacroScratchRegisterUsage allowScratch(jit);
9127 CHECK(params.size() == 3);
9128 CHECK(params[0] == ValueRep::reg(GPRInfo::nonArgGPR0));
9129 CHECK(params[1].isGPR());
9130 CHECK(params[2].isGPR());
9131 add32(jit, params[1].gpr(), params[2].gpr(), GPRInfo::nonArgGPR0);
9132 });
9133 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
9134
9135 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
9136}
9137
9138void testPatchpointWithStackArgumentResult()
9139{
9140 Procedure proc;
9141 BasicBlock* root = proc.addBlock();
9142 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9143 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
9144 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
9145 patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
9146 patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
9147 patchpoint->resultConstraint = ValueRep::stackArgument(0);
9148 patchpoint->clobber(RegisterSet::macroScratchRegisters());
9149 patchpoint->setGenerator(
9150 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9151 AllowMacroScratchRegisterUsage allowScratch(jit);
9152 CHECK(params.size() == 3);
9153 CHECK(params[0] == ValueRep::stack(-static_cast<intptr_t>(proc.frameSize())));
9154 CHECK(params[1].isGPR());
9155 CHECK(params[2].isGPR());
9156 jit.add32(params[1].gpr(), params[2].gpr(), jit.scratchRegister());
9157 jit.store32(jit.scratchRegister(), CCallHelpers::Address(CCallHelpers::stackPointerRegister, 0));
9158 });
9159 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
9160
9161 CHECK(compileAndRun<int>(proc, 1, 2) == 3);
9162}
9163
9164void testPatchpointWithAnyResult()
9165{
9166 Procedure proc;
9167 BasicBlock* root = proc.addBlock();
9168 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9169 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
9170 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin());
9171 patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
9172 patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
9173 patchpoint->resultConstraint = ValueRep::WarmAny;
9174 patchpoint->clobberLate(RegisterSet::allFPRs());
9175 patchpoint->clobber(RegisterSet::macroScratchRegisters());
9176 patchpoint->clobber(RegisterSet(GPRInfo::regT0));
9177 patchpoint->setGenerator(
9178 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9179 AllowMacroScratchRegisterUsage allowScratch(jit);
9180 CHECK(params.size() == 3);
9181 CHECK(params[0].isStack());
9182 CHECK(params[1].isGPR());
9183 CHECK(params[2].isGPR());
9184 add32(jit, params[1].gpr(), params[2].gpr(), GPRInfo::regT0);
9185 jit.convertInt32ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0);
9186 jit.storeDouble(FPRInfo::fpRegT0, CCallHelpers::Address(GPRInfo::callFrameRegister, params[0].offsetFromFP()));
9187 });
9188 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
9189
9190 CHECK(compileAndRun<double>(proc, 1, 2) == 3);
9191}
9192
9193void testSimpleCheck()
9194{
9195 Procedure proc;
9196 if (proc.optLevel() < 1)
9197 return;
9198 BasicBlock* root = proc.addBlock();
9199 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9200 CheckValue* check = root->appendNew<CheckValue>(proc, Check, Origin(), arg);
9201 check->setGenerator(
9202 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9203 AllowMacroScratchRegisterUsage allowScratch(jit);
9204 CHECK(!params.size());
9205
9206 // This should always work because a function this simple should never have callee
9207 // saves.
9208 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
9209 jit.emitFunctionEpilogue();
9210 jit.ret();
9211 });
9212 root->appendNewControlValue(
9213 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
9214
9215 auto code = compileProc(proc);
9216
9217 CHECK(invoke<int>(*code, 0) == 0);
9218 CHECK(invoke<int>(*code, 1) == 42);
9219}
9220
9221void testCheckFalse()
9222{
9223 Procedure proc;
9224 BasicBlock* root = proc.addBlock();
9225 CheckValue* check = root->appendNew<CheckValue>(
9226 proc, Check, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
9227 unsigned optLevel = proc.optLevel();
9228 check->setGenerator(
9229 [&] (CCallHelpers&, const StackmapGenerationParams&) {
9230 if (optLevel > 1)
9231 CHECK(!"This should not have executed");
9232 });
9233 root->appendNewControlValue(
9234 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
9235
9236 auto code = compileProc(proc);
9237
9238 CHECK(invoke<int>(*code) == 0);
9239}
9240
9241void testCheckTrue()
9242{
9243 Procedure proc;
9244 if (proc.optLevel() < 1)
9245 return;
9246 BasicBlock* root = proc.addBlock();
9247 CheckValue* check = root->appendNew<CheckValue>(
9248 proc, Check, Origin(), root->appendNew<Const32Value>(proc, Origin(), 1));
9249 unsigned optLevel = proc.optLevel();
9250 check->setGenerator(
9251 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9252 AllowMacroScratchRegisterUsage allowScratch(jit);
9253 if (optLevel > 1)
9254 CHECK(params.value()->opcode() == Patchpoint);
9255 CHECK(!params.size());
9256
9257 // This should always work because a function this simple should never have callee
9258 // saves.
9259 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
9260 jit.emitFunctionEpilogue();
9261 jit.ret();
9262 });
9263 root->appendNewControlValue(
9264 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
9265
9266 auto code = compileProc(proc);
9267
9268 CHECK(invoke<int>(*code) == 42);
9269}
9270
9271void testCheckLessThan()
9272{
9273 Procedure proc;
9274 if (proc.optLevel() < 1)
9275 return;
9276 BasicBlock* root = proc.addBlock();
9277 Value* arg = root->appendNew<Value>(
9278 proc, Trunc, Origin(),
9279 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9280 CheckValue* check = root->appendNew<CheckValue>(
9281 proc, Check, Origin(),
9282 root->appendNew<Value>(
9283 proc, LessThan, Origin(), arg,
9284 root->appendNew<Const32Value>(proc, Origin(), 42)));
9285 check->setGenerator(
9286 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9287 AllowMacroScratchRegisterUsage allowScratch(jit);
9288 CHECK(!params.size());
9289
9290 // This should always work because a function this simple should never have callee
9291 // saves.
9292 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
9293 jit.emitFunctionEpilogue();
9294 jit.ret();
9295 });
9296 root->appendNewControlValue(
9297 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
9298
9299 auto code = compileProc(proc);
9300
9301 CHECK(invoke<int>(*code, 42) == 0);
9302 CHECK(invoke<int>(*code, 1000) == 0);
9303 CHECK(invoke<int>(*code, 41) == 42);
9304 CHECK(invoke<int>(*code, 0) == 42);
9305 CHECK(invoke<int>(*code, -1) == 42);
9306}
9307
9308void testCheckMegaCombo()
9309{
9310 Procedure proc;
9311 if (proc.optLevel() < 1)
9312 return;
9313 BasicBlock* root = proc.addBlock();
9314 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9315 Value* index = root->appendNew<Value>(
9316 proc, ZExt32, Origin(),
9317 root->appendNew<Value>(
9318 proc, Trunc, Origin(),
9319 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
9320
9321 Value* ptr = root->appendNew<Value>(
9322 proc, Add, Origin(), base,
9323 root->appendNew<Value>(
9324 proc, Shl, Origin(), index,
9325 root->appendNew<Const32Value>(proc, Origin(), 1)));
9326
9327 CheckValue* check = root->appendNew<CheckValue>(
9328 proc, Check, Origin(),
9329 root->appendNew<Value>(
9330 proc, LessThan, Origin(),
9331 root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr),
9332 root->appendNew<Const32Value>(proc, Origin(), 42)));
9333 check->setGenerator(
9334 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9335 AllowMacroScratchRegisterUsage allowScratch(jit);
9336 CHECK(!params.size());
9337
9338 // This should always work because a function this simple should never have callee
9339 // saves.
9340 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
9341 jit.emitFunctionEpilogue();
9342 jit.ret();
9343 });
9344 root->appendNewControlValue(
9345 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
9346
9347 auto code = compileProc(proc);
9348
9349 int8_t value;
9350 value = 42;
9351 CHECK(invoke<int>(*code, &value - 2, 1) == 0);
9352 value = 127;
9353 CHECK(invoke<int>(*code, &value - 2, 1) == 0);
9354 value = 41;
9355 CHECK(invoke<int>(*code, &value - 2, 1) == 42);
9356 value = 0;
9357 CHECK(invoke<int>(*code, &value - 2, 1) == 42);
9358 value = -1;
9359 CHECK(invoke<int>(*code, &value - 2, 1) == 42);
9360}
9361
9362void testCheckTrickyMegaCombo()
9363{
9364 Procedure proc;
9365 if (proc.optLevel() < 1)
9366 return;
9367 BasicBlock* root = proc.addBlock();
9368 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9369 Value* index = root->appendNew<Value>(
9370 proc, ZExt32, Origin(),
9371 root->appendNew<Value>(
9372 proc, Add, Origin(),
9373 root->appendNew<Value>(
9374 proc, Trunc, Origin(),
9375 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)),
9376 root->appendNew<Const32Value>(proc, Origin(), 1)));
9377
9378 Value* ptr = root->appendNew<Value>(
9379 proc, Add, Origin(), base,
9380 root->appendNew<Value>(
9381 proc, Shl, Origin(), index,
9382 root->appendNew<Const32Value>(proc, Origin(), 1)));
9383
9384 CheckValue* check = root->appendNew<CheckValue>(
9385 proc, Check, Origin(),
9386 root->appendNew<Value>(
9387 proc, LessThan, Origin(),
9388 root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr),
9389 root->appendNew<Const32Value>(proc, Origin(), 42)));
9390 check->setGenerator(
9391 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9392 AllowMacroScratchRegisterUsage allowScratch(jit);
9393 CHECK(!params.size());
9394
9395 // This should always work because a function this simple should never have callee
9396 // saves.
9397 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
9398 jit.emitFunctionEpilogue();
9399 jit.ret();
9400 });
9401 root->appendNewControlValue(
9402 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
9403
9404 auto code = compileProc(proc);
9405
9406 int8_t value;
9407 value = 42;
9408 CHECK(invoke<int>(*code, &value - 2, 0) == 0);
9409 value = 127;
9410 CHECK(invoke<int>(*code, &value - 2, 0) == 0);
9411 value = 41;
9412 CHECK(invoke<int>(*code, &value - 2, 0) == 42);
9413 value = 0;
9414 CHECK(invoke<int>(*code, &value - 2, 0) == 42);
9415 value = -1;
9416 CHECK(invoke<int>(*code, &value - 2, 0) == 42);
9417}
9418
9419void testCheckTwoMegaCombos()
9420{
9421 Procedure proc;
9422 if (proc.optLevel() < 1)
9423 return;
9424 BasicBlock* root = proc.addBlock();
9425 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9426 Value* index = root->appendNew<Value>(
9427 proc, ZExt32, Origin(),
9428 root->appendNew<Value>(
9429 proc, Trunc, Origin(),
9430 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
9431
9432 Value* ptr = root->appendNew<Value>(
9433 proc, Add, Origin(), base,
9434 root->appendNew<Value>(
9435 proc, Shl, Origin(), index,
9436 root->appendNew<Const32Value>(proc, Origin(), 1)));
9437
9438 Value* predicate = root->appendNew<Value>(
9439 proc, LessThan, Origin(),
9440 root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr),
9441 root->appendNew<Const32Value>(proc, Origin(), 42));
9442
9443 CheckValue* check = root->appendNew<CheckValue>(proc, Check, Origin(), predicate);
9444 check->setGenerator(
9445 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9446 AllowMacroScratchRegisterUsage allowScratch(jit);
9447 CHECK(!params.size());
9448
9449 // This should always work because a function this simple should never have callee
9450 // saves.
9451 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
9452 jit.emitFunctionEpilogue();
9453 jit.ret();
9454 });
9455 CheckValue* check2 = root->appendNew<CheckValue>(proc, Check, Origin(), predicate);
9456 check2->setGenerator(
9457 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9458 AllowMacroScratchRegisterUsage allowScratch(jit);
9459 CHECK(!params.size());
9460
9461 // This should always work because a function this simple should never have callee
9462 // saves.
9463 jit.move(CCallHelpers::TrustedImm32(43), GPRInfo::returnValueGPR);
9464 jit.emitFunctionEpilogue();
9465 jit.ret();
9466 });
9467 root->appendNewControlValue(
9468 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
9469
9470 auto code = compileProc(proc);
9471
9472 int8_t value;
9473 value = 42;
9474 CHECK(invoke<int>(*code, &value - 2, 1) == 0);
9475 value = 127;
9476 CHECK(invoke<int>(*code, &value - 2, 1) == 0);
9477 value = 41;
9478 CHECK(invoke<int>(*code, &value - 2, 1) == 42);
9479 value = 0;
9480 CHECK(invoke<int>(*code, &value - 2, 1) == 42);
9481 value = -1;
9482 CHECK(invoke<int>(*code, &value - 2, 1) == 42);
9483}
9484
9485void testCheckTwoNonRedundantMegaCombos()
9486{
9487 Procedure proc;
9488 if (proc.optLevel() < 1)
9489 return;
9490
9491 BasicBlock* root = proc.addBlock();
9492 BasicBlock* thenCase = proc.addBlock();
9493 BasicBlock* elseCase = proc.addBlock();
9494
9495 Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9496 Value* index = root->appendNew<Value>(
9497 proc, ZExt32, Origin(),
9498 root->appendNew<Value>(
9499 proc, Trunc, Origin(),
9500 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
9501 Value* branchPredicate = root->appendNew<Value>(
9502 proc, BitAnd, Origin(),
9503 root->appendNew<Value>(
9504 proc, Trunc, Origin(),
9505 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)),
9506 root->appendNew<Const32Value>(proc, Origin(), 0xff));
9507
9508 Value* ptr = root->appendNew<Value>(
9509 proc, Add, Origin(), base,
9510 root->appendNew<Value>(
9511 proc, Shl, Origin(), index,
9512 root->appendNew<Const32Value>(proc, Origin(), 1)));
9513
9514 Value* checkPredicate = root->appendNew<Value>(
9515 proc, LessThan, Origin(),
9516 root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr),
9517 root->appendNew<Const32Value>(proc, Origin(), 42));
9518
9519 root->appendNewControlValue(
9520 proc, Branch, Origin(), branchPredicate,
9521 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
9522
9523 CheckValue* check = thenCase->appendNew<CheckValue>(proc, Check, Origin(), checkPredicate);
9524 check->setGenerator(
9525 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9526 AllowMacroScratchRegisterUsage allowScratch(jit);
9527 CHECK(!params.size());
9528
9529 // This should always work because a function this simple should never have callee
9530 // saves.
9531 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
9532 jit.emitFunctionEpilogue();
9533 jit.ret();
9534 });
9535 thenCase->appendNewControlValue(
9536 proc, Return, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 43));
9537
9538 CheckValue* check2 = elseCase->appendNew<CheckValue>(proc, Check, Origin(), checkPredicate);
9539 check2->setGenerator(
9540 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9541 AllowMacroScratchRegisterUsage allowScratch(jit);
9542 CHECK(!params.size());
9543
9544 // This should always work because a function this simple should never have callee
9545 // saves.
9546 jit.move(CCallHelpers::TrustedImm32(44), GPRInfo::returnValueGPR);
9547 jit.emitFunctionEpilogue();
9548 jit.ret();
9549 });
9550 elseCase->appendNewControlValue(
9551 proc, Return, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 45));
9552
9553 auto code = compileProc(proc);
9554
9555 int8_t value;
9556
9557 value = 42;
9558 CHECK(invoke<int>(*code, &value - 2, 1, true) == 43);
9559 value = 127;
9560 CHECK(invoke<int>(*code, &value - 2, 1, true) == 43);
9561 value = 41;
9562 CHECK(invoke<int>(*code, &value - 2, 1, true) == 42);
9563 value = 0;
9564 CHECK(invoke<int>(*code, &value - 2, 1, true) == 42);
9565 value = -1;
9566 CHECK(invoke<int>(*code, &value - 2, 1, true) == 42);
9567
9568 value = 42;
9569 CHECK(invoke<int>(*code, &value - 2, 1, false) == 45);
9570 value = 127;
9571 CHECK(invoke<int>(*code, &value - 2, 1, false) == 45);
9572 value = 41;
9573 CHECK(invoke<int>(*code, &value - 2, 1, false) == 44);
9574 value = 0;
9575 CHECK(invoke<int>(*code, &value - 2, 1, false) == 44);
9576 value = -1;
9577 CHECK(invoke<int>(*code, &value - 2, 1, false) == 44);
9578}
9579
9580void testCheckAddImm()
9581{
9582 Procedure proc;
9583 if (proc.optLevel() < 1)
9584 return;
9585 BasicBlock* root = proc.addBlock();
9586 Value* arg1 = root->appendNew<Value>(
9587 proc, Trunc, Origin(),
9588 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9589 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
9590 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
9591 checkAdd->append(arg1);
9592 checkAdd->append(arg2);
9593 checkAdd->setGenerator(
9594 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9595 AllowMacroScratchRegisterUsage allowScratch(jit);
9596 CHECK(params.size() == 2);
9597 CHECK(params[0].isGPR());
9598 CHECK(params[1].isConstant());
9599 CHECK(params[1].value() == 42);
9600 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
9601 jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1);
9602 jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
9603 jit.emitFunctionEpilogue();
9604 jit.ret();
9605 });
9606 root->appendNewControlValue(
9607 proc, Return, Origin(),
9608 root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
9609
9610 auto code = compileProc(proc);
9611
9612 CHECK(invoke<double>(*code, 0) == 42.0);
9613 CHECK(invoke<double>(*code, 1) == 43.0);
9614 CHECK(invoke<double>(*code, 42) == 84.0);
9615 CHECK(invoke<double>(*code, 2147483647) == 2147483689.0);
9616}
9617
9618void testCheckAddImmCommute()
9619{
9620 Procedure proc;
9621 if (proc.optLevel() < 1)
9622 return;
9623 BasicBlock* root = proc.addBlock();
9624 Value* arg1 = root->appendNew<Value>(
9625 proc, Trunc, Origin(),
9626 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9627 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
9628 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg2, arg1);
9629 checkAdd->append(arg1);
9630 checkAdd->append(arg2);
9631 checkAdd->setGenerator(
9632 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9633 AllowMacroScratchRegisterUsage allowScratch(jit);
9634 CHECK(params.size() == 2);
9635 CHECK(params[0].isGPR());
9636 CHECK(params[1].isConstant());
9637 CHECK(params[1].value() == 42);
9638 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
9639 jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1);
9640 jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
9641 jit.emitFunctionEpilogue();
9642 jit.ret();
9643 });
9644 root->appendNewControlValue(
9645 proc, Return, Origin(),
9646 root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
9647
9648 auto code = compileProc(proc);
9649
9650 CHECK(invoke<double>(*code, 0) == 42.0);
9651 CHECK(invoke<double>(*code, 1) == 43.0);
9652 CHECK(invoke<double>(*code, 42) == 84.0);
9653 CHECK(invoke<double>(*code, 2147483647) == 2147483689.0);
9654}
9655
9656void testCheckAddImmSomeRegister()
9657{
9658 Procedure proc;
9659 if (proc.optLevel() < 1)
9660 return;
9661 BasicBlock* root = proc.addBlock();
9662 Value* arg1 = root->appendNew<Value>(
9663 proc, Trunc, Origin(),
9664 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9665 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
9666 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
9667 checkAdd->appendSomeRegister(arg1);
9668 checkAdd->appendSomeRegister(arg2);
9669 checkAdd->setGenerator(
9670 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9671 AllowMacroScratchRegisterUsage allowScratch(jit);
9672 CHECK(params.size() == 2);
9673 CHECK(params[0].isGPR());
9674 CHECK(params[1].isGPR());
9675 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
9676 jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
9677 jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
9678 jit.emitFunctionEpilogue();
9679 jit.ret();
9680 });
9681 root->appendNewControlValue(
9682 proc, Return, Origin(),
9683 root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
9684
9685 auto code = compileProc(proc);
9686
9687 CHECK(invoke<double>(*code, 0) == 42.0);
9688 CHECK(invoke<double>(*code, 1) == 43.0);
9689 CHECK(invoke<double>(*code, 42) == 84.0);
9690 CHECK(invoke<double>(*code, 2147483647) == 2147483689.0);
9691}
9692
9693void testCheckAdd()
9694{
9695 Procedure proc;
9696 if (proc.optLevel() < 1)
9697 return;
9698 BasicBlock* root = proc.addBlock();
9699 Value* arg1 = root->appendNew<Value>(
9700 proc, Trunc, Origin(),
9701 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9702 Value* arg2 = root->appendNew<Value>(
9703 proc, Trunc, Origin(),
9704 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
9705 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
9706 checkAdd->appendSomeRegister(arg1);
9707 checkAdd->appendSomeRegister(arg2);
9708 checkAdd->setGenerator(
9709 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9710 AllowMacroScratchRegisterUsage allowScratch(jit);
9711 CHECK(params.size() == 2);
9712 CHECK(params[0].isGPR());
9713 CHECK(params[1].isGPR());
9714 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
9715 jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
9716 jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
9717 jit.emitFunctionEpilogue();
9718 jit.ret();
9719 });
9720 root->appendNewControlValue(
9721 proc, Return, Origin(),
9722 root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
9723
9724 auto code = compileProc(proc);
9725
9726 CHECK(invoke<double>(*code, 0, 42) == 42.0);
9727 CHECK(invoke<double>(*code, 1, 42) == 43.0);
9728 CHECK(invoke<double>(*code, 42, 42) == 84.0);
9729 CHECK(invoke<double>(*code, 2147483647, 42) == 2147483689.0);
9730}
9731
9732void testCheckAdd64()
9733{
9734 Procedure proc;
9735 if (proc.optLevel() < 1)
9736 return;
9737 BasicBlock* root = proc.addBlock();
9738 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9739 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
9740 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
9741 checkAdd->appendSomeRegister(arg1);
9742 checkAdd->appendSomeRegister(arg2);
9743 checkAdd->setGenerator(
9744 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9745 AllowMacroScratchRegisterUsage allowScratch(jit);
9746 CHECK(params.size() == 2);
9747 CHECK(params[0].isGPR());
9748 CHECK(params[1].isGPR());
9749 jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
9750 jit.convertInt64ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
9751 jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
9752 jit.emitFunctionEpilogue();
9753 jit.ret();
9754 });
9755 root->appendNewControlValue(
9756 proc, Return, Origin(),
9757 root->appendNew<Value>(proc, IToD, Origin(), checkAdd));
9758
9759 auto code = compileProc(proc);
9760
9761 CHECK(invoke<double>(*code, 0ll, 42ll) == 42.0);
9762 CHECK(invoke<double>(*code, 1ll, 42ll) == 43.0);
9763 CHECK(invoke<double>(*code, 42ll, 42ll) == 84.0);
9764 CHECK(invoke<double>(*code, 9223372036854775807ll, 42ll) == static_cast<double>(9223372036854775807ll) + 42.0);
9765}
9766
9767void testCheckAddFold(int a, int b)
9768{
9769 Procedure proc;
9770 BasicBlock* root = proc.addBlock();
9771 Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
9772 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
9773 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
9774 unsigned optLevel = proc.optLevel();
9775 checkAdd->setGenerator(
9776 [&] (CCallHelpers&, const StackmapGenerationParams&) {
9777 if (optLevel > 1)
9778 CHECK(!"Should have been folded");
9779 });
9780 root->appendNewControlValue(proc, Return, Origin(), checkAdd);
9781
9782 auto code = compileProc(proc);
9783
9784 CHECK(invoke<int>(*code) == a + b);
9785}
9786
9787void testCheckAddFoldFail(int a, int b)
9788{
9789 Procedure proc;
9790 if (proc.optLevel() < 1)
9791 return;
9792 BasicBlock* root = proc.addBlock();
9793 Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
9794 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
9795 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
9796 checkAdd->setGenerator(
9797 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
9798 AllowMacroScratchRegisterUsage allowScratch(jit);
9799 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
9800 jit.emitFunctionEpilogue();
9801 jit.ret();
9802 });
9803 root->appendNewControlValue(proc, Return, Origin(), checkAdd);
9804
9805 auto code = compileProc(proc);
9806
9807 CHECK(invoke<int>(*code) == 42);
9808}
9809
9810void testCheckAddArgumentAliasing64()
9811{
9812 Procedure proc;
9813 BasicBlock* root = proc.addBlock();
9814 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9815 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
9816 Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
9817
9818 // Pretend to use all the args.
9819 PatchpointValue* useArgs = root->appendNew<PatchpointValue>(proc, Void, Origin());
9820 useArgs->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
9821 useArgs->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
9822 useArgs->append(ConstrainedValue(arg3, ValueRep::SomeRegister));
9823 useArgs->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
9824
9825 // Last use of first arg (here, arg1).
9826 CheckValue* checkAdd1 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
9827 checkAdd1->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
9828
9829 // Last use of second arg (here, arg2).
9830 CheckValue* checkAdd2 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg3, arg2);
9831 checkAdd2->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
9832
9833 // Keep arg3 live.
9834 PatchpointValue* keepArg2Live = root->appendNew<PatchpointValue>(proc, Void, Origin());
9835 keepArg2Live->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
9836 keepArg2Live->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
9837
9838 // Only use of checkAdd1 and checkAdd2.
9839 CheckValue* checkAdd3 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), checkAdd1, checkAdd2);
9840 checkAdd3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
9841
9842 root->appendNewControlValue(proc, Return, Origin(), checkAdd3);
9843
9844 CHECK(compileAndRun<int64_t>(proc, 1, 2, 3) == 8);
9845}
9846
9847void testCheckAddArgumentAliasing32()
9848{
9849 Procedure proc;
9850 BasicBlock* root = proc.addBlock();
9851 Value* arg1 = root->appendNew<Value>(
9852 proc, Trunc, Origin(),
9853 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9854 Value* arg2 = root->appendNew<Value>(
9855 proc, Trunc, Origin(),
9856 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
9857 Value* arg3 = root->appendNew<Value>(
9858 proc, Trunc, Origin(),
9859 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
9860
9861 // Pretend to use all the args.
9862 PatchpointValue* useArgs = root->appendNew<PatchpointValue>(proc, Void, Origin());
9863 useArgs->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
9864 useArgs->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
9865 useArgs->append(ConstrainedValue(arg3, ValueRep::SomeRegister));
9866 useArgs->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
9867
9868 // Last use of first arg (here, arg1).
9869 CheckValue* checkAdd1 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2);
9870 checkAdd1->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
9871
9872 // Last use of second arg (here, arg3).
9873 CheckValue* checkAdd2 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg2, arg3);
9874 checkAdd2->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
9875
9876 // Keep arg3 live.
9877 PatchpointValue* keepArg2Live = root->appendNew<PatchpointValue>(proc, Void, Origin());
9878 keepArg2Live->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
9879 keepArg2Live->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
9880
9881 // Only use of checkAdd1 and checkAdd2.
9882 CheckValue* checkAdd3 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), checkAdd1, checkAdd2);
9883 checkAdd3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
9884
9885 root->appendNewControlValue(proc, Return, Origin(), checkAdd3);
9886
9887 CHECK(compileAndRun<int32_t>(proc, 1, 2, 3) == 8);
9888}
9889
9890void testCheckAddSelfOverflow64()
9891{
9892 Procedure proc;
9893 if (proc.optLevel() < 1)
9894 return;
9895 BasicBlock* root = proc.addBlock();
9896 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
9897 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg, arg);
9898 checkAdd->append(arg);
9899 checkAdd->setGenerator(
9900 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9901 AllowMacroScratchRegisterUsage allowScratch(jit);
9902 jit.move(params[0].gpr(), GPRInfo::returnValueGPR);
9903 jit.emitFunctionEpilogue();
9904 jit.ret();
9905 });
9906
9907 // Make sure the arg is not the destination of the operation.
9908 PatchpointValue* opaqueUse = root->appendNew<PatchpointValue>(proc, Void, Origin());
9909 opaqueUse->append(ConstrainedValue(arg, ValueRep::SomeRegister));
9910 opaqueUse->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
9911
9912 root->appendNewControlValue(proc, Return, Origin(), checkAdd);
9913
9914 auto code = compileProc(proc);
9915
9916 CHECK(invoke<int64_t>(*code, 0ll) == 0);
9917 CHECK(invoke<int64_t>(*code, 1ll) == 2);
9918 CHECK(invoke<int64_t>(*code, std::numeric_limits<int64_t>::max()) == std::numeric_limits<int64_t>::max());
9919}
9920
9921void testCheckAddSelfOverflow32()
9922{
9923 Procedure proc;
9924 if (proc.optLevel() < 1)
9925 return;
9926 BasicBlock* root = proc.addBlock();
9927 Value* arg = root->appendNew<Value>(
9928 proc, Trunc, Origin(),
9929 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9930 CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg, arg);
9931 checkAdd->append(arg);
9932 checkAdd->setGenerator(
9933 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9934 AllowMacroScratchRegisterUsage allowScratch(jit);
9935 jit.move(params[0].gpr(), GPRInfo::returnValueGPR);
9936 jit.emitFunctionEpilogue();
9937 jit.ret();
9938 });
9939
9940 // Make sure the arg is not the destination of the operation.
9941 PatchpointValue* opaqueUse = root->appendNew<PatchpointValue>(proc, Void, Origin());
9942 opaqueUse->append(ConstrainedValue(arg, ValueRep::SomeRegister));
9943 opaqueUse->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
9944
9945 root->appendNewControlValue(proc, Return, Origin(), checkAdd);
9946
9947 auto code = compileProc(proc);
9948
9949 CHECK(invoke<int32_t>(*code, 0ll) == 0);
9950 CHECK(invoke<int32_t>(*code, 1ll) == 2);
9951 CHECK(invoke<int32_t>(*code, std::numeric_limits<int32_t>::max()) == std::numeric_limits<int32_t>::max());
9952}
9953
9954void testCheckSubImm()
9955{
9956 Procedure proc;
9957 if (proc.optLevel() < 1)
9958 return;
9959 BasicBlock* root = proc.addBlock();
9960 Value* arg1 = root->appendNew<Value>(
9961 proc, Trunc, Origin(),
9962 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
9963 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42);
9964 CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
9965 checkSub->append(arg1);
9966 checkSub->append(arg2);
9967 checkSub->setGenerator(
9968 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9969 AllowMacroScratchRegisterUsage allowScratch(jit);
9970 CHECK(params.size() == 2);
9971 CHECK(params[0].isGPR());
9972 CHECK(params[1].isConstant());
9973 CHECK(params[1].value() == 42);
9974 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
9975 jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1);
9976 jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
9977 jit.emitFunctionEpilogue();
9978 jit.ret();
9979 });
9980 root->appendNewControlValue(
9981 proc, Return, Origin(),
9982 root->appendNew<Value>(proc, IToD, Origin(), checkSub));
9983
9984 auto code = compileProc(proc);
9985
9986 CHECK(invoke<double>(*code, 0) == -42.0);
9987 CHECK(invoke<double>(*code, 1) == -41.0);
9988 CHECK(invoke<double>(*code, 42) == 0.0);
9989 CHECK(invoke<double>(*code, -2147483647) == -2147483689.0);
9990}
9991
9992void testCheckSubBadImm()
9993{
9994 Procedure proc;
9995 if (proc.optLevel() < 1)
9996 return;
9997 BasicBlock* root = proc.addBlock();
9998 Value* arg1 = root->appendNew<Value>(
9999 proc, Trunc, Origin(),
10000 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10001 int32_t badImm = std::numeric_limits<int>::min();
10002 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), badImm);
10003 CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
10004 checkSub->append(arg1);
10005 checkSub->append(arg2);
10006 checkSub->setGenerator(
10007 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10008 AllowMacroScratchRegisterUsage allowScratch(jit);
10009 CHECK(params.size() == 2);
10010 CHECK(params[0].isGPR());
10011 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
10012
10013 if (params[1].isConstant()) {
10014 CHECK(params[1].value() == badImm);
10015 jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(badImm), FPRInfo::fpRegT1);
10016 } else {
10017 CHECK(params[1].isGPR());
10018 jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
10019 }
10020 jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10021 jit.emitFunctionEpilogue();
10022 jit.ret();
10023 });
10024 root->appendNewControlValue(
10025 proc, Return, Origin(),
10026 root->appendNew<Value>(proc, IToD, Origin(), checkSub));
10027
10028 auto code = compileProc(proc);
10029
10030 CHECK(invoke<double>(*code, 0) == -static_cast<double>(badImm));
10031 CHECK(invoke<double>(*code, -1) == -static_cast<double>(badImm) - 1);
10032 CHECK(invoke<double>(*code, 1) == -static_cast<double>(badImm) + 1);
10033 CHECK(invoke<double>(*code, 42) == -static_cast<double>(badImm) + 42);
10034}
10035
10036void testCheckSub()
10037{
10038 Procedure proc;
10039 if (proc.optLevel() < 1)
10040 return;
10041 BasicBlock* root = proc.addBlock();
10042 Value* arg1 = root->appendNew<Value>(
10043 proc, Trunc, Origin(),
10044 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10045 Value* arg2 = root->appendNew<Value>(
10046 proc, Trunc, Origin(),
10047 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
10048 CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
10049 checkSub->append(arg1);
10050 checkSub->append(arg2);
10051 checkSub->setGenerator(
10052 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10053 AllowMacroScratchRegisterUsage allowScratch(jit);
10054 CHECK(params.size() == 2);
10055 CHECK(params[0].isGPR());
10056 CHECK(params[1].isGPR());
10057 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
10058 jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
10059 jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10060 jit.emitFunctionEpilogue();
10061 jit.ret();
10062 });
10063 root->appendNewControlValue(
10064 proc, Return, Origin(),
10065 root->appendNew<Value>(proc, IToD, Origin(), checkSub));
10066
10067 auto code = compileProc(proc);
10068
10069 CHECK(invoke<double>(*code, 0, 42) == -42.0);
10070 CHECK(invoke<double>(*code, 1, 42) == -41.0);
10071 CHECK(invoke<double>(*code, 42, 42) == 0.0);
10072 CHECK(invoke<double>(*code, -2147483647, 42) == -2147483689.0);
10073}
10074
10075NEVER_INLINE double doubleSub(double a, double b)
10076{
10077 return a - b;
10078}
10079
10080void testCheckSub64()
10081{
10082 Procedure proc;
10083 if (proc.optLevel() < 1)
10084 return;
10085 BasicBlock* root = proc.addBlock();
10086 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
10087 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
10088 CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
10089 checkSub->append(arg1);
10090 checkSub->append(arg2);
10091 checkSub->setGenerator(
10092 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10093 AllowMacroScratchRegisterUsage allowScratch(jit);
10094 CHECK(params.size() == 2);
10095 CHECK(params[0].isGPR());
10096 CHECK(params[1].isGPR());
10097 jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
10098 jit.convertInt64ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
10099 jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10100 jit.emitFunctionEpilogue();
10101 jit.ret();
10102 });
10103 root->appendNewControlValue(
10104 proc, Return, Origin(),
10105 root->appendNew<Value>(proc, IToD, Origin(), checkSub));
10106
10107 auto code = compileProc(proc);
10108
10109 CHECK(invoke<double>(*code, 0ll, 42ll) == -42.0);
10110 CHECK(invoke<double>(*code, 1ll, 42ll) == -41.0);
10111 CHECK(invoke<double>(*code, 42ll, 42ll) == 0.0);
10112 CHECK(invoke<double>(*code, -9223372036854775807ll, 42ll) == doubleSub(static_cast<double>(-9223372036854775807ll), 42.0));
10113}
10114
10115void testCheckSubFold(int a, int b)
10116{
10117 Procedure proc;
10118 BasicBlock* root = proc.addBlock();
10119 Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
10120 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
10121 CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
10122 unsigned optLevel = proc.optLevel();
10123 checkSub->setGenerator(
10124 [&] (CCallHelpers&, const StackmapGenerationParams&) {
10125 if (optLevel > 1)
10126 CHECK(!"Should have been folded");
10127 });
10128 root->appendNewControlValue(proc, Return, Origin(), checkSub);
10129
10130 auto code = compileProc(proc);
10131
10132 CHECK(invoke<int>(*code) == a - b);
10133}
10134
10135void testCheckSubFoldFail(int a, int b)
10136{
10137 Procedure proc;
10138 if (proc.optLevel() < 1)
10139 return;
10140 BasicBlock* root = proc.addBlock();
10141 Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
10142 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
10143 CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
10144 checkSub->setGenerator(
10145 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
10146 AllowMacroScratchRegisterUsage allowScratch(jit);
10147 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
10148 jit.emitFunctionEpilogue();
10149 jit.ret();
10150 });
10151 root->appendNewControlValue(proc, Return, Origin(), checkSub);
10152
10153 auto code = compileProc(proc);
10154
10155 CHECK(invoke<int>(*code) == 42);
10156}
10157
10158void testCheckNeg()
10159{
10160 Procedure proc;
10161 if (proc.optLevel() < 1)
10162 return;
10163 BasicBlock* root = proc.addBlock();
10164 Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), 0);
10165 Value* arg2 = root->appendNew<Value>(
10166 proc, Trunc, Origin(),
10167 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10168 CheckValue* checkNeg = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
10169 checkNeg->append(arg2);
10170 checkNeg->setGenerator(
10171 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10172 AllowMacroScratchRegisterUsage allowScratch(jit);
10173 CHECK(params.size() == 1);
10174 CHECK(params[0].isGPR());
10175 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT1);
10176 jit.negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10177 jit.emitFunctionEpilogue();
10178 jit.ret();
10179 });
10180 root->appendNewControlValue(
10181 proc, Return, Origin(),
10182 root->appendNew<Value>(proc, IToD, Origin(), checkNeg));
10183
10184 auto code = compileProc(proc);
10185
10186 CHECK(invoke<double>(*code, 0) == 0.0);
10187 CHECK(invoke<double>(*code, 1) == -1.0);
10188 CHECK(invoke<double>(*code, 42) == -42.0);
10189 CHECK(invoke<double>(*code, -2147483647 - 1) == 2147483648.0);
10190}
10191
10192void testCheckNeg64()
10193{
10194 Procedure proc;
10195 if (proc.optLevel() < 1)
10196 return;
10197 BasicBlock* root = proc.addBlock();
10198 Value* arg1 = root->appendNew<Const64Value>(proc, Origin(), 0);
10199 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
10200 CheckValue* checkNeg = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2);
10201 checkNeg->append(arg2);
10202 checkNeg->setGenerator(
10203 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10204 AllowMacroScratchRegisterUsage allowScratch(jit);
10205 CHECK(params.size() == 1);
10206 CHECK(params[0].isGPR());
10207 jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT1);
10208 jit.negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10209 jit.emitFunctionEpilogue();
10210 jit.ret();
10211 });
10212 root->appendNewControlValue(
10213 proc, Return, Origin(),
10214 root->appendNew<Value>(proc, IToD, Origin(), checkNeg));
10215
10216 auto code = compileProc(proc);
10217
10218 CHECK(invoke<double>(*code, 0ll) == 0.0);
10219 CHECK(invoke<double>(*code, 1ll) == -1.0);
10220 CHECK(invoke<double>(*code, 42ll) == -42.0);
10221 CHECK(invoke<double>(*code, -9223372036854775807ll - 1) == 9223372036854775808.0);
10222}
10223
10224void testCheckMul()
10225{
10226 Procedure proc;
10227 if (proc.optLevel() < 1)
10228 return;
10229 BasicBlock* root = proc.addBlock();
10230 Value* arg1 = root->appendNew<Value>(
10231 proc, Trunc, Origin(),
10232 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10233 Value* arg2 = root->appendNew<Value>(
10234 proc, Trunc, Origin(),
10235 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
10236 CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10237 checkMul->append(arg1);
10238 checkMul->append(arg2);
10239 checkMul->setGenerator(
10240 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10241 AllowMacroScratchRegisterUsage allowScratch(jit);
10242 CHECK(params.size() == 2);
10243 CHECK(params[0].isGPR());
10244 CHECK(params[1].isGPR());
10245 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
10246 jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
10247 jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10248 jit.emitFunctionEpilogue();
10249 jit.ret();
10250 });
10251 root->appendNewControlValue(
10252 proc, Return, Origin(),
10253 root->appendNew<Value>(proc, IToD, Origin(), checkMul));
10254
10255 auto code = compileProc(proc);
10256
10257 CHECK(invoke<double>(*code, 0, 42) == 0.0);
10258 CHECK(invoke<double>(*code, 1, 42) == 42.0);
10259 CHECK(invoke<double>(*code, 42, 42) == 42.0 * 42.0);
10260 CHECK(invoke<double>(*code, 2147483647, 42) == 2147483647.0 * 42.0);
10261}
10262
10263void testCheckMulMemory()
10264{
10265 Procedure proc;
10266 if (proc.optLevel() < 1)
10267 return;
10268 BasicBlock* root = proc.addBlock();
10269
10270 int left;
10271 int right;
10272
10273 Value* arg1 = root->appendNew<MemoryValue>(
10274 proc, Load, Int32, Origin(),
10275 root->appendNew<ConstPtrValue>(proc, Origin(), &left));
10276 Value* arg2 = root->appendNew<MemoryValue>(
10277 proc, Load, Int32, Origin(),
10278 root->appendNew<ConstPtrValue>(proc, Origin(), &right));
10279 CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10280 checkMul->append(arg1);
10281 checkMul->append(arg2);
10282 checkMul->setGenerator(
10283 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10284 AllowMacroScratchRegisterUsage allowScratch(jit);
10285 CHECK(params.size() == 2);
10286 CHECK(params[0].isGPR());
10287 CHECK(params[1].isGPR());
10288 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
10289 jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
10290 jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10291 jit.emitFunctionEpilogue();
10292 jit.ret();
10293 });
10294 root->appendNewControlValue(
10295 proc, Return, Origin(),
10296 root->appendNew<Value>(proc, IToD, Origin(), checkMul));
10297
10298 auto code = compileProc(proc);
10299
10300 left = 0;
10301 right = 42;
10302 CHECK(invoke<double>(*code) == 0.0);
10303
10304 left = 1;
10305 right = 42;
10306 CHECK(invoke<double>(*code) == 42.0);
10307
10308 left = 42;
10309 right = 42;
10310 CHECK(invoke<double>(*code) == 42.0 * 42.0);
10311
10312 left = 2147483647;
10313 right = 42;
10314 CHECK(invoke<double>(*code) == 2147483647.0 * 42.0);
10315}
10316
10317void testCheckMul2()
10318{
10319 Procedure proc;
10320 if (proc.optLevel() < 1)
10321 return;
10322 BasicBlock* root = proc.addBlock();
10323 Value* arg1 = root->appendNew<Value>(
10324 proc, Trunc, Origin(),
10325 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10326 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 2);
10327 CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10328 checkMul->append(arg1);
10329 checkMul->append(arg2);
10330 checkMul->setGenerator(
10331 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10332 AllowMacroScratchRegisterUsage allowScratch(jit);
10333 CHECK(params.size() == 2);
10334 CHECK(params[0].isGPR());
10335 CHECK(params[1].isConstant());
10336 CHECK(params[1].value() == 2);
10337 jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
10338 jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(2), FPRInfo::fpRegT1);
10339 jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10340 jit.emitFunctionEpilogue();
10341 jit.ret();
10342 });
10343 root->appendNewControlValue(
10344 proc, Return, Origin(),
10345 root->appendNew<Value>(proc, IToD, Origin(), checkMul));
10346
10347 auto code = compileProc(proc);
10348
10349 CHECK(invoke<double>(*code, 0) == 0.0);
10350 CHECK(invoke<double>(*code, 1) == 2.0);
10351 CHECK(invoke<double>(*code, 42) == 42.0 * 2.0);
10352 CHECK(invoke<double>(*code, 2147483647) == 2147483647.0 * 2.0);
10353}
10354
10355void testCheckMul64()
10356{
10357 Procedure proc;
10358 if (proc.optLevel() < 1)
10359 return;
10360 BasicBlock* root = proc.addBlock();
10361 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
10362 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
10363 CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10364 checkMul->append(arg1);
10365 checkMul->append(arg2);
10366 checkMul->setGenerator(
10367 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10368 AllowMacroScratchRegisterUsage allowScratch(jit);
10369 CHECK(params.size() == 2);
10370 CHECK(params[0].isGPR());
10371 CHECK(params[1].isGPR());
10372 jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
10373 jit.convertInt64ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
10374 jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10375 jit.emitFunctionEpilogue();
10376 jit.ret();
10377 });
10378 root->appendNewControlValue(
10379 proc, Return, Origin(),
10380 root->appendNew<Value>(proc, IToD, Origin(), checkMul));
10381
10382 auto code = compileProc(proc);
10383
10384 CHECK(invoke<double>(*code, 0, 42) == 0.0);
10385 CHECK(invoke<double>(*code, 1, 42) == 42.0);
10386 CHECK(invoke<double>(*code, 42, 42) == 42.0 * 42.0);
10387 CHECK(invoke<double>(*code, 9223372036854775807ll, 42) == static_cast<double>(9223372036854775807ll) * 42.0);
10388}
10389
10390void testCheckMulFold(int a, int b)
10391{
10392 Procedure proc;
10393 BasicBlock* root = proc.addBlock();
10394 Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
10395 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
10396 CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10397 unsigned optLevel = proc.optLevel();
10398 checkMul->setGenerator(
10399 [&] (CCallHelpers&, const StackmapGenerationParams&) {
10400 if (optLevel > 1)
10401 CHECK(!"Should have been folded");
10402 });
10403 root->appendNewControlValue(proc, Return, Origin(), checkMul);
10404
10405 auto code = compileProc(proc);
10406
10407 CHECK(invoke<int>(*code) == a * b);
10408}
10409
10410void testCheckMulFoldFail(int a, int b)
10411{
10412 Procedure proc;
10413 if (proc.optLevel() < 1)
10414 return;
10415 BasicBlock* root = proc.addBlock();
10416 Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a);
10417 Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b);
10418 CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10419 checkMul->setGenerator(
10420 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
10421 AllowMacroScratchRegisterUsage allowScratch(jit);
10422 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
10423 jit.emitFunctionEpilogue();
10424 jit.ret();
10425 });
10426 root->appendNewControlValue(proc, Return, Origin(), checkMul);
10427
10428 auto code = compileProc(proc);
10429
10430 CHECK(invoke<int>(*code) == 42);
10431}
10432
10433void testCheckMulArgumentAliasing64()
10434{
10435 Procedure proc;
10436 BasicBlock* root = proc.addBlock();
10437 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
10438 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
10439 Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
10440
10441 // Pretend to use all the args.
10442 PatchpointValue* useArgs = root->appendNew<PatchpointValue>(proc, Void, Origin());
10443 useArgs->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
10444 useArgs->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
10445 useArgs->append(ConstrainedValue(arg3, ValueRep::SomeRegister));
10446 useArgs->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
10447
10448 // Last use of first arg (here, arg1).
10449 CheckValue* checkMul1 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10450 checkMul1->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
10451
10452 // Last use of second arg (here, arg2).
10453 CheckValue* checkMul2 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg3, arg2);
10454 checkMul2->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
10455
10456 // Keep arg3 live.
10457 PatchpointValue* keepArg2Live = root->appendNew<PatchpointValue>(proc, Void, Origin());
10458 keepArg2Live->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
10459 keepArg2Live->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
10460
10461 // Only use of checkMul1 and checkMul2.
10462 CheckValue* checkMul3 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), checkMul1, checkMul2);
10463 checkMul3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
10464
10465 root->appendNewControlValue(proc, Return, Origin(), checkMul3);
10466
10467 CHECK(compileAndRun<int64_t>(proc, 2, 3, 4) == 72);
10468}
10469
10470void testCheckMulArgumentAliasing32()
10471{
10472 Procedure proc;
10473 BasicBlock* root = proc.addBlock();
10474 Value* arg1 = root->appendNew<Value>(
10475 proc, Trunc, Origin(),
10476 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10477 Value* arg2 = root->appendNew<Value>(
10478 proc, Trunc, Origin(),
10479 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
10480 Value* arg3 = root->appendNew<Value>(
10481 proc, Trunc, Origin(),
10482 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
10483
10484 // Pretend to use all the args.
10485 PatchpointValue* useArgs = root->appendNew<PatchpointValue>(proc, Void, Origin());
10486 useArgs->append(ConstrainedValue(arg1, ValueRep::SomeRegister));
10487 useArgs->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
10488 useArgs->append(ConstrainedValue(arg3, ValueRep::SomeRegister));
10489 useArgs->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
10490
10491 // Last use of first arg (here, arg1).
10492 CheckValue* checkMul1 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10493 checkMul1->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
10494
10495 // Last use of second arg (here, arg3).
10496 CheckValue* checkMul2 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg2, arg3);
10497 checkMul2->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
10498
10499 // Keep arg3 live.
10500 PatchpointValue* keepArg2Live = root->appendNew<PatchpointValue>(proc, Void, Origin());
10501 keepArg2Live->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
10502 keepArg2Live->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
10503
10504 // Only use of checkMul1 and checkMul2.
10505 CheckValue* checkMul3 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), checkMul1, checkMul2);
10506 checkMul3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); });
10507
10508 root->appendNewControlValue(proc, Return, Origin(), checkMul3);
10509
10510 CHECK(compileAndRun<int32_t>(proc, 2, 3, 4) == 72);
10511}
10512
10513void testCheckMul64SShr()
10514{
10515 Procedure proc;
10516 if (proc.optLevel() < 1)
10517 return;
10518 BasicBlock* root = proc.addBlock();
10519 Value* arg1 = root->appendNew<Value>(
10520 proc, SShr, Origin(),
10521 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
10522 root->appendNew<Const32Value>(proc, Origin(), 1));
10523 Value* arg2 = root->appendNew<Value>(
10524 proc, SShr, Origin(),
10525 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
10526 root->appendNew<Const32Value>(proc, Origin(), 1));
10527 CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2);
10528 checkMul->append(arg1);
10529 checkMul->append(arg2);
10530 checkMul->setGenerator(
10531 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10532 AllowMacroScratchRegisterUsage allowScratch(jit);
10533 CHECK(params.size() == 2);
10534 CHECK(params[0].isGPR());
10535 CHECK(params[1].isGPR());
10536 jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT0);
10537 jit.convertInt64ToDouble(params[1].gpr(), FPRInfo::fpRegT1);
10538 jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
10539 jit.emitFunctionEpilogue();
10540 jit.ret();
10541 });
10542 root->appendNewControlValue(
10543 proc, Return, Origin(),
10544 root->appendNew<Value>(proc, IToD, Origin(), checkMul));
10545
10546 auto code = compileProc(proc);
10547
10548 CHECK(invoke<double>(*code, 0ll, 42ll) == 0.0);
10549 CHECK(invoke<double>(*code, 1ll, 42ll) == 0.0);
10550 CHECK(invoke<double>(*code, 42ll, 42ll) == (42.0 / 2.0) * (42.0 / 2.0));
10551 CHECK(invoke<double>(*code, 10000000000ll, 10000000000ll) == 25000000000000000000.0);
10552}
10553
10554template<typename LeftFunctor, typename RightFunctor, typename InputType>
10555void genericTestCompare(
10556 B3::Opcode opcode, const LeftFunctor& leftFunctor, const RightFunctor& rightFunctor,
10557 InputType left, InputType right, int result)
10558{
10559 // Using a compare.
10560 {
10561 Procedure proc;
10562 BasicBlock* root = proc.addBlock();
10563
10564 Value* leftValue = leftFunctor(root, proc);
10565 Value* rightValue = rightFunctor(root, proc);
10566 Value* comparisonResult = root->appendNew<Value>(proc, opcode, Origin(), leftValue, rightValue);
10567
10568 root->appendNewControlValue(
10569 proc, Return, Origin(),
10570 root->appendNew<Value>(
10571 proc, NotEqual, Origin(),
10572 comparisonResult,
10573 root->appendIntConstant(proc, Origin(), comparisonResult->type(), 0)));
10574
10575 CHECK(compileAndRun<int>(proc, left, right) == result);
10576 }
10577
10578 // Using a branch.
10579 {
10580 Procedure proc;
10581 BasicBlock* root = proc.addBlock();
10582 BasicBlock* thenCase = proc.addBlock();
10583 BasicBlock* elseCase = proc.addBlock();
10584
10585 Value* leftValue = leftFunctor(root, proc);
10586 Value* rightValue = rightFunctor(root, proc);
10587
10588 root->appendNewControlValue(
10589 proc, Branch, Origin(),
10590 root->appendNew<Value>(proc, opcode, Origin(), leftValue, rightValue),
10591 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
10592
10593 // We use a patchpoint on the then case to ensure that this doesn't get if-converted.
10594 PatchpointValue* patchpoint = thenCase->appendNew<PatchpointValue>(proc, Int32, Origin());
10595 patchpoint->setGenerator(
10596 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10597 AllowMacroScratchRegisterUsage allowScratch(jit);
10598 CHECK(params.size() == 1);
10599 CHECK(params[0].isGPR());
10600 jit.move(CCallHelpers::TrustedImm32(1), params[0].gpr());
10601 });
10602 thenCase->appendNewControlValue(proc, Return, Origin(), patchpoint);
10603
10604 elseCase->appendNewControlValue(
10605 proc, Return, Origin(),
10606 elseCase->appendNew<Const32Value>(proc, Origin(), 0));
10607
10608 CHECK(compileAndRun<int>(proc, left, right) == result);
10609 }
10610}
10611
10612template<typename InputType>
10613InputType modelCompare(B3::Opcode opcode, InputType left, InputType right)
10614{
10615 switch (opcode) {
10616 case Equal:
10617 return left == right;
10618 case NotEqual:
10619 return left != right;
10620 case LessThan:
10621 return left < right;
10622 case GreaterThan:
10623 return left > right;
10624 case LessEqual:
10625 return left <= right;
10626 case GreaterEqual:
10627 return left >= right;
10628 case Above:
10629 return static_cast<typename std::make_unsigned<InputType>::type>(left) >
10630 static_cast<typename std::make_unsigned<InputType>::type>(right);
10631 case Below:
10632 return static_cast<typename std::make_unsigned<InputType>::type>(left) <
10633 static_cast<typename std::make_unsigned<InputType>::type>(right);
10634 case AboveEqual:
10635 return static_cast<typename std::make_unsigned<InputType>::type>(left) >=
10636 static_cast<typename std::make_unsigned<InputType>::type>(right);
10637 case BelowEqual:
10638 return static_cast<typename std::make_unsigned<InputType>::type>(left) <=
10639 static_cast<typename std::make_unsigned<InputType>::type>(right);
10640 case BitAnd:
10641 return !!(left & right);
10642 default:
10643 RELEASE_ASSERT_NOT_REACHED();
10644 return 0;
10645 }
10646}
10647
10648template<typename T>
10649void testCompareLoad(B3::Opcode opcode, B3::Opcode loadOpcode, int left, int right)
10650{
10651 int result = modelCompare(opcode, modelLoad<T>(left), right);
10652
10653 // Test addr-to-tmp
10654 int slot = left;
10655 genericTestCompare(
10656 opcode,
10657 [&] (BasicBlock* block, Procedure& proc) {
10658 return block->appendNew<MemoryValue>(
10659 proc, loadOpcode, Int32, Origin(),
10660 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
10661 },
10662 [&] (BasicBlock* block, Procedure& proc) {
10663 return block->appendNew<Value>(
10664 proc, Trunc, Origin(),
10665 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
10666 },
10667 left, right, result);
10668
10669 // Test addr-to-imm
10670 slot = left;
10671 genericTestCompare(
10672 opcode,
10673 [&] (BasicBlock* block, Procedure& proc) {
10674 return block->appendNew<MemoryValue>(
10675 proc, loadOpcode, Int32, Origin(),
10676 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
10677 },
10678 [&] (BasicBlock* block, Procedure& proc) {
10679 return block->appendNew<Const32Value>(proc, Origin(), right);
10680 },
10681 left, right, result);
10682
10683 result = modelCompare(opcode, left, modelLoad<T>(right));
10684
10685 // Test tmp-to-addr
10686 slot = right;
10687 genericTestCompare(
10688 opcode,
10689 [&] (BasicBlock* block, Procedure& proc) {
10690 return block->appendNew<Value>(
10691 proc, Trunc, Origin(),
10692 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10693 },
10694 [&] (BasicBlock* block, Procedure& proc) {
10695 return block->appendNew<MemoryValue>(
10696 proc, loadOpcode, Int32, Origin(),
10697 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
10698 },
10699 left, right, result);
10700
10701 // Test imm-to-addr
10702 slot = right;
10703 genericTestCompare(
10704 opcode,
10705 [&] (BasicBlock* block, Procedure& proc) {
10706 return block->appendNew<Const32Value>(proc, Origin(), left);
10707 },
10708 [&] (BasicBlock* block, Procedure& proc) {
10709 return block->appendNew<MemoryValue>(
10710 proc, loadOpcode, Int32, Origin(),
10711 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
10712 },
10713 left, right, result);
10714
10715 // Test addr-to-addr, with the same addr.
10716 slot = left;
10717 Value* value;
10718 genericTestCompare(
10719 opcode,
10720 [&] (BasicBlock* block, Procedure& proc) {
10721 value = block->appendNew<MemoryValue>(
10722 proc, loadOpcode, Int32, Origin(),
10723 block->appendNew<ConstPtrValue>(proc, Origin(), &slot));
10724 return value;
10725 },
10726 [&] (BasicBlock*, Procedure&) {
10727 return value;
10728 },
10729 left, left, modelCompare(opcode, modelLoad<T>(left), modelLoad<T>(left)));
10730}
10731
10732void testCompareImpl(B3::Opcode opcode, int64_t left, int64_t right)
10733{
10734 int64_t result = modelCompare(opcode, left, right);
10735 int32_t int32Result = modelCompare(opcode, static_cast<int32_t>(left), static_cast<int32_t>(right));
10736
10737 // Test tmp-to-tmp.
10738 genericTestCompare(
10739 opcode,
10740 [&] (BasicBlock* block, Procedure& proc) {
10741 return block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
10742 },
10743 [&] (BasicBlock* block, Procedure& proc) {
10744 return block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
10745 },
10746 left, right, result);
10747 genericTestCompare(
10748 opcode,
10749 [&] (BasicBlock* block, Procedure& proc) {
10750 return block->appendNew<Value>(
10751 proc, Trunc, Origin(),
10752 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10753 },
10754 [&] (BasicBlock* block, Procedure& proc) {
10755 return block->appendNew<Value>(
10756 proc, Trunc, Origin(),
10757 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
10758 },
10759 left, right, int32Result);
10760
10761 // Test imm-to-tmp.
10762 genericTestCompare(
10763 opcode,
10764 [&] (BasicBlock* block, Procedure& proc) {
10765 return block->appendNew<Const64Value>(proc, Origin(), left);
10766 },
10767 [&] (BasicBlock* block, Procedure& proc) {
10768 return block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
10769 },
10770 left, right, result);
10771 genericTestCompare(
10772 opcode,
10773 [&] (BasicBlock* block, Procedure& proc) {
10774 return block->appendNew<Const32Value>(proc, Origin(), left);
10775 },
10776 [&] (BasicBlock* block, Procedure& proc) {
10777 return block->appendNew<Value>(
10778 proc, Trunc, Origin(),
10779 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
10780 },
10781 left, right, int32Result);
10782
10783 // Test tmp-to-imm.
10784 genericTestCompare(
10785 opcode,
10786 [&] (BasicBlock* block, Procedure& proc) {
10787 return block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
10788 },
10789 [&] (BasicBlock* block, Procedure& proc) {
10790 return block->appendNew<Const64Value>(proc, Origin(), right);
10791 },
10792 left, right, result);
10793 genericTestCompare(
10794 opcode,
10795 [&] (BasicBlock* block, Procedure& proc) {
10796 return block->appendNew<Value>(
10797 proc, Trunc, Origin(),
10798 block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
10799 },
10800 [&] (BasicBlock* block, Procedure& proc) {
10801 return block->appendNew<Const32Value>(proc, Origin(), right);
10802 },
10803 left, right, int32Result);
10804
10805 // Test imm-to-imm.
10806 genericTestCompare(
10807 opcode,
10808 [&] (BasicBlock* block, Procedure& proc) {
10809 return block->appendNew<Const64Value>(proc, Origin(), left);
10810 },
10811 [&] (BasicBlock* block, Procedure& proc) {
10812 return block->appendNew<Const64Value>(proc, Origin(), right);
10813 },
10814 left, right, result);
10815 genericTestCompare(
10816 opcode,
10817 [&] (BasicBlock* block, Procedure& proc) {
10818 return block->appendNew<Const32Value>(proc, Origin(), left);
10819 },
10820 [&] (BasicBlock* block, Procedure& proc) {
10821 return block->appendNew<Const32Value>(proc, Origin(), right);
10822 },
10823 left, right, int32Result);
10824
10825 testCompareLoad<int32_t>(opcode, Load, left, right);
10826 testCompareLoad<int8_t>(opcode, Load8S, left, right);
10827 testCompareLoad<uint8_t>(opcode, Load8Z, left, right);
10828 testCompareLoad<int16_t>(opcode, Load16S, left, right);
10829 testCompareLoad<uint16_t>(opcode, Load16Z, left, right);
10830}
10831
10832void testCompare(B3::Opcode opcode, int64_t left, int64_t right)
10833{
10834 testCompareImpl(opcode, left, right);
10835 testCompareImpl(opcode, left, right + 1);
10836 testCompareImpl(opcode, left, right - 1);
10837}
10838
10839void testEqualDouble(double left, double right, bool result)
10840{
10841 Procedure proc;
10842 BasicBlock* root = proc.addBlock();
10843 root->appendNewControlValue(
10844 proc, Return, Origin(),
10845 root->appendNew<Value>(
10846 proc, Equal, Origin(),
10847 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0),
10848 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)));
10849
10850 CHECK(compileAndRun<bool>(proc, left, right) == result);
10851}
10852
10853int simpleFunction(int a, int b)
10854{
10855 return a + b;
10856}
10857
10858void testCallSimple(int a, int b)
10859{
10860 Procedure proc;
10861 BasicBlock* root = proc.addBlock();
10862 root->appendNewControlValue(
10863 proc, Return, Origin(),
10864 root->appendNew<CCallValue>(
10865 proc, Int32, Origin(),
10866 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(simpleFunction, B3CCallPtrTag)),
10867 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
10868 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
10869
10870 CHECK(compileAndRun<int>(proc, a, b) == a + b);
10871}
10872
10873void testCallRare(int a, int b)
10874{
10875 Procedure proc;
10876 BasicBlock* root = proc.addBlock();
10877 BasicBlock* common = proc.addBlock();
10878 BasicBlock* rare = proc.addBlock();
10879
10880 root->appendNewControlValue(
10881 proc, Branch, Origin(),
10882 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
10883 FrequentedBlock(rare, FrequencyClass::Rare),
10884 FrequentedBlock(common));
10885
10886 common->appendNewControlValue(
10887 proc, Return, Origin(), common->appendNew<Const32Value>(proc, Origin(), 0));
10888
10889 rare->appendNewControlValue(
10890 proc, Return, Origin(),
10891 rare->appendNew<CCallValue>(
10892 proc, Int32, Origin(),
10893 rare->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(simpleFunction, B3CCallPtrTag)),
10894 rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
10895 rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
10896
10897 CHECK(compileAndRun<int>(proc, true, a, b) == a + b);
10898}
10899
10900void testCallRareLive(int a, int b, int c)
10901{
10902 Procedure proc;
10903 BasicBlock* root = proc.addBlock();
10904 BasicBlock* common = proc.addBlock();
10905 BasicBlock* rare = proc.addBlock();
10906
10907 root->appendNewControlValue(
10908 proc, Branch, Origin(),
10909 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
10910 FrequentedBlock(rare, FrequencyClass::Rare),
10911 FrequentedBlock(common));
10912
10913 common->appendNewControlValue(
10914 proc, Return, Origin(), common->appendNew<Const32Value>(proc, Origin(), 0));
10915
10916 rare->appendNewControlValue(
10917 proc, Return, Origin(),
10918 rare->appendNew<Value>(
10919 proc, Add, Origin(),
10920 rare->appendNew<CCallValue>(
10921 proc, Int32, Origin(),
10922 rare->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(simpleFunction, B3CCallPtrTag)),
10923 rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
10924 rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)),
10925 rare->appendNew<Value>(
10926 proc, Trunc, Origin(),
10927 rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3))));
10928
10929 CHECK(compileAndRun<int>(proc, true, a, b, c) == a + b + c);
10930}
10931
10932void testCallSimplePure(int a, int b)
10933{
10934 Procedure proc;
10935 BasicBlock* root = proc.addBlock();
10936 root->appendNewControlValue(
10937 proc, Return, Origin(),
10938 root->appendNew<CCallValue>(
10939 proc, Int32, Origin(), Effects::none(),
10940 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(simpleFunction, B3CCallPtrTag)),
10941 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
10942 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
10943
10944 CHECK(compileAndRun<int>(proc, a, b) == a + b);
10945}
10946
10947int functionWithHellaArguments(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, int n, int o, int p, int q, int r, int s, int t, int u, int v, int w, int x, int y, int z)
10948{
10949 return (a << 0) + (b << 1) + (c << 2) + (d << 3) + (e << 4) + (f << 5) + (g << 6) + (h << 7) + (i << 8) + (j << 9) + (k << 10) + (l << 11) + (m << 12) + (n << 13) + (o << 14) + (p << 15) + (q << 16) + (r << 17) + (s << 18) + (t << 19) + (u << 20) + (v << 21) + (w << 22) + (x << 23) + (y << 24) + (z << 25);
10950}
10951
10952void testCallFunctionWithHellaArguments()
10953{
10954 Procedure proc;
10955 BasicBlock* root = proc.addBlock();
10956
10957 Vector<Value*> args;
10958 for (unsigned i = 0; i < 26; ++i)
10959 args.append(root->appendNew<Const32Value>(proc, Origin(), i + 1));
10960
10961 CCallValue* call = root->appendNew<CCallValue>(
10962 proc, Int32, Origin(),
10963 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaArguments, B3CCallPtrTag)));
10964 call->appendArgs(args);
10965
10966 root->appendNewControlValue(proc, Return, Origin(), call);
10967
10968 CHECK(compileAndRun<int>(proc) == functionWithHellaArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26));
10969}
10970
10971uint64_t functionWithHellaArguments2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g, uint64_t h, uint64_t i, uint64_t j, uint64_t k, uint64_t l, uint64_t m, uint64_t n, uint64_t o, uint64_t p, uint64_t q, uint64_t r, uint64_t s, uint64_t t, uint64_t u, uint64_t v, uint64_t w, uint64_t x, uint64_t y, uint64_t z)
10972{
10973 return (a << 0) + (b << 1) + (c << 2) + (d << 3) + (e << 4) + (f << 5) + (g << 6) + (h << 7) + (i << 8) + (j << 9) + (k << 10) + (l << 11) + (m << 12) + (n << 13) + (o << 14) + (p << 15) + (q << 16) + (r << 17) + (s << 18) + (t << 19) + (u << 20) + (v << 21) + (w << 22) + (x << 23) + (y << 24) + (z << 25);
10974}
10975
10976void testCallFunctionWithHellaArguments2()
10977{
10978 Procedure proc;
10979 BasicBlock* root = proc.addBlock();
10980
10981 uint64_t limit = static_cast<uint64_t>((1 << 12) - 1); // UINT12_MAX, for arm64 testing.
10982
10983 Vector<Value*> args;
10984 for (unsigned i = 0; i < 26; ++i)
10985 args.append(root->appendNew<Const64Value>(proc, Origin(), limit - i));
10986
10987 CCallValue* call = root->appendNew<CCallValue>(
10988 proc, Int64, Origin(),
10989 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaArguments2, B3CCallPtrTag)));
10990 call->appendArgs(args);
10991
10992 root->appendNewControlValue(proc, Return, Origin(), call);
10993
10994 auto a = compileAndRun<uint64_t>(proc);
10995 auto b = functionWithHellaArguments2(limit, limit-1, limit-2, limit-3, limit-4, limit-5, limit-6, limit-7, limit-8, limit-9, limit-10, limit-11, limit-12, limit-13, limit-14, limit-15, limit-16, limit-17, limit-18, limit-19, limit-20, limit-21, limit-22, limit-23, limit-24, limit-25);
10996 CHECK(a == b);
10997}
10998
10999int functionWithHellaArguments3(int arg0,int arg1,int arg2,int arg3,int arg4,int arg5,int arg6,int arg7,int arg8,int arg9,int arg10,int arg11,int arg12,int arg13,int arg14,int arg15,int arg16,int arg17,int arg18,int arg19,int arg20,int arg21,int arg22,int arg23,int arg24,int arg25,int arg26,int arg27,int arg28,int arg29,int arg30,int arg31,int arg32,int arg33,int arg34,int arg35,int arg36,int arg37,int arg38,int arg39,int arg40,int arg41,int arg42,int arg43,int arg44,int arg45,int arg46,int arg47,int arg48,int arg49,int arg50,int arg51,int arg52,int arg53,int arg54,int arg55,int arg56,int arg57,int arg58,int arg59,int arg60,int arg61,int arg62,int arg63,int arg64,int arg65,int arg66,int arg67,int arg68,int arg69,int arg70,int arg71,int arg72,int arg73,int arg74,int arg75,int arg76,int arg77,int arg78,int arg79,int arg80,int arg81,int arg82,int arg83,int arg84,int arg85,int arg86,int arg87,int arg88,int arg89,int arg90,int arg91,int arg92,int arg93,int arg94,int arg95,int arg96,int arg97,int arg98,int arg99,int arg100,int arg101,int arg102,int arg103,int arg104,int arg105,int arg106,int arg107,int arg108,int arg109,int arg110,int arg111,int arg112,int arg113,int arg114,int arg115,int arg116,int arg117,int arg118,int arg119,int arg120,int arg121,int arg122,int arg123,int arg124,int arg125,int arg126,int arg127,int arg128,int arg129,int arg130,int arg131,int arg132,int arg133,int arg134,int arg135,int arg136,int arg137,int arg138,int arg139,int arg140,int arg141,int arg142,int arg143,int arg144,int arg145,int arg146,int arg147,int arg148,int arg149,int arg150,int arg151,int arg152,int arg153,int arg154,int arg155,int arg156,int arg157,int arg158,int arg159,int arg160,int arg161,int arg162,int arg163,int arg164,int arg165,int arg166,int arg167,int arg168,int arg169,int arg170,int arg171,int arg172,int arg173,int arg174,int arg175,int arg176,int arg177,int arg178,int arg179,int arg180,int arg181,int arg182,int arg183,int arg184,int arg185,int arg186,int arg187,int arg188,int arg189,int arg190,int arg191,int arg192,int arg193,int arg194,int arg195,int arg196,int arg197,int arg198,int arg199,int arg200,int arg201,int arg202,int arg203,int arg204,int arg205,int arg206,int arg207,int arg208,int arg209,int arg210,int arg211,int arg212,int arg213,int arg214,int arg215,int arg216,int arg217,int arg218,int arg219,int arg220,int arg221,int arg222,int arg223,int arg224,int arg225,int arg226,int arg227,int arg228,int arg229,int arg230,int arg231,int arg232,int arg233,int arg234,int arg235,int arg236,int arg237,int arg238,int arg239,int arg240,int arg241,int arg242,int arg243,int arg244,int arg245,int arg246,int arg247,int arg248,int arg249,int arg250,int arg251,int arg252,int arg253,int arg254,int arg255,int arg256,int arg257,int arg258,int arg259,int arg260,int arg261,int arg262,int arg263,int arg264,int arg265,int arg266,int arg267,int arg268,int arg269,int arg270,int arg271,int arg272,int arg273,int arg274,int arg275,int arg276,int arg277,int arg278,int arg279,int arg280,int arg281,int arg282,int arg283,int arg284,int arg285,int arg286,int arg287,int arg288,int arg289,int arg290,int arg291,int arg292,int arg293,int arg294,int arg295,int arg296,int arg297,int arg298,int arg299,int arg300,int arg301,int arg302,int arg303,int arg304,int arg305,int arg306,int arg307,int arg308,int arg309,int arg310,int arg311,int arg312,int arg313,int arg314,int arg315,int arg316,int arg317,int arg318,int arg319,int arg320,int arg321,int arg322,int arg323,int arg324,int arg325,int arg326,int arg327,int arg328,int arg329,int arg330,int arg331,int arg332,int arg333,int arg334,int arg335,int arg336,int arg337,int arg338,int arg339,int arg340,int arg341,int arg342,int arg343,int arg344,int arg345,int arg346,int arg347,int arg348,int arg349,int arg350,int arg351,int arg352,int arg353,int arg354,int arg355,int arg356,int arg357,int arg358,int arg359,int arg360,int arg361,int arg362,int arg363,int arg364,int arg365,int arg366,int arg367,int arg368,int arg369,int arg370,int arg371,int arg372,int arg373,int arg374,int arg375,int arg376,int arg377,int arg378,int arg379,int arg380,int arg381,int arg382,int arg383,int arg384,int arg385,int arg386,int arg387,int arg388,int arg389,int arg390,int arg391,int arg392,int arg393,int arg394,int arg395,int arg396,int arg397,int arg398,int arg399,int arg400,int arg401,int arg402,int arg403,int arg404,int arg405,int arg406,int arg407,int arg408,int arg409,int arg410,int arg411,int arg412,int arg413,int arg414,int arg415,int arg416,int arg417,int arg418,int arg419,int arg420,int arg421,int arg422,int arg423,int arg424,int arg425,int arg426,int arg427,int arg428,int arg429,int arg430,int arg431,int arg432,int arg433,int arg434,int arg435,int arg436,int arg437,int arg438,int arg439,int arg440,int arg441,int arg442,int arg443,int arg444,int arg445,int arg446,int arg447,int arg448,int arg449,int arg450,int arg451,int arg452,int arg453,int arg454,int arg455,int arg456,int arg457,int arg458,int arg459,int arg460,int arg461,int arg462,int arg463,int arg464,int arg465,int arg466,int arg467,int arg468,int arg469,int arg470,int arg471,int arg472,int arg473,int arg474,int arg475,int arg476,int arg477,int arg478,int arg479,int arg480,int arg481,int arg482,int arg483,int arg484,int arg485,int arg486,int arg487,int arg488,int arg489,int arg490,int arg491,int arg492,int arg493,int arg494,int arg495,int arg496,int arg497,int arg498,int arg499,int arg500,int arg501,int arg502,int arg503,int arg504,int arg505,int arg506,int arg507,int arg508,int arg509,int arg510,int arg511,int arg512,int arg513,int arg514,int arg515,int arg516,int arg517,int arg518,int arg519,int arg520,int arg521,int arg522,int arg523,int arg524,int arg525,int arg526,int arg527,int arg528,int arg529,int arg530,int arg531,int arg532,int arg533,int arg534,int arg535,int arg536,int arg537,int arg538,int arg539,int arg540,int arg541,int arg542,int arg543,int arg544,int arg545,int arg546,int arg547,int arg548,int arg549,int arg550,int arg551,int arg552,int arg553,int arg554,int arg555,int arg556,int arg557,int arg558,int arg559,int arg560,int arg561,int arg562,int arg563,int arg564,int arg565,int arg566,int arg567,int arg568,int arg569,int arg570,int arg571,int arg572,int arg573,int arg574,int arg575,int arg576,int arg577,int arg578,int arg579,int arg580,int arg581,int arg582,int arg583,int arg584,int arg585,int arg586,int arg587,int arg588,int arg589,int arg590,int arg591,int arg592,int arg593,int arg594,int arg595,int arg596,int arg597,int arg598,int arg599,int arg600,int arg601,int arg602,int arg603,int arg604,int arg605,int arg606,int arg607,int arg608,int arg609,int arg610,int arg611,int arg612,int arg613,int arg614,int arg615,int arg616,int arg617,int arg618,int arg619,int arg620,int arg621,int arg622,int arg623,int arg624,int arg625,int arg626,int arg627,int arg628,int arg629,int arg630,int arg631,int arg632,int arg633,int arg634,int arg635,int arg636,int arg637,int arg638,int arg639,int arg640,int arg641,int arg642,int arg643,int arg644,int arg645,int arg646,int arg647,int arg648,int arg649,int arg650,int arg651,int arg652,int arg653,int arg654,int arg655,int arg656,int arg657,int arg658,int arg659,int arg660,int arg661,int arg662,int arg663,int arg664,int arg665,int arg666,int arg667,int arg668,int arg669,int arg670,int arg671,int arg672,int arg673,int arg674,int arg675,int arg676,int arg677,int arg678,int arg679,int arg680,int arg681,int arg682,int arg683,int arg684,int arg685,int arg686,int arg687,int arg688,int arg689,int arg690,int arg691,int arg692,int arg693,int arg694,int arg695,int arg696,int arg697,int arg698,int arg699,int arg700,int arg701,int arg702,int arg703,int arg704,int arg705,int arg706,int arg707,int arg708,int arg709,int arg710,int arg711,int arg712,int arg713,int arg714,int arg715,int arg716,int arg717,int arg718,int arg719,int arg720,int arg721,int arg722,int arg723,int arg724,int arg725,int arg726,int arg727,int arg728,int arg729,int arg730,int arg731,int arg732,int arg733,int arg734,int arg735,int arg736,int arg737,int arg738,int arg739,int arg740,int arg741,int arg742,int arg743,int arg744,int arg745,int arg746,int arg747,int arg748,int arg749,int arg750,int arg751,int arg752,int arg753,int arg754,int arg755,int arg756,int arg757,int arg758,int arg759,int arg760,int arg761,int arg762,int arg763,int arg764,int arg765,int arg766,int arg767,int arg768,int arg769,int arg770,int arg771,int arg772,int arg773,int arg774,int arg775,int arg776,int arg777,int arg778,int arg779,int arg780,int arg781,int arg782,int arg783,int arg784,int arg785,int arg786,int arg787,int arg788,int arg789,int arg790,int arg791,int arg792,int arg793,int arg794,int arg795,int arg796,int arg797,int arg798,int arg799,int arg800,int arg801,int arg802,int arg803,int arg804,int arg805,int arg806,int arg807,int arg808,int arg809,int arg810,int arg811,int arg812,int arg813,int arg814,int arg815,int arg816,int arg817,int arg818,int arg819,int arg820,int arg821,int arg822,int arg823,int arg824,int arg825,int arg826,int arg827,int arg828,int arg829,int arg830,int arg831,int arg832,int arg833,int arg834,int arg835,int arg836,int arg837,int arg838,int arg839,int arg840,int arg841,int arg842,int arg843,int arg844,int arg845,int arg846,int arg847,int arg848,int arg849,int arg850,int arg851,int arg852,int arg853,int arg854,int arg855,int arg856,int arg857,int arg858,int arg859,int arg860,int arg861,int arg862,int arg863,int arg864,int arg865,int arg866,int arg867,int arg868,int arg869,int arg870,int arg871,int arg872,int arg873,int arg874,int arg875,int arg876,int arg877,int arg878,int arg879,int arg880,int arg881,int arg882,int arg883,int arg884,int arg885,int arg886,int arg887,int arg888,int arg889,int arg890,int arg891,int arg892,int arg893,int arg894,int arg895,int arg896,int arg897,int arg898,int arg899,int arg900,int arg901,int arg902,int arg903,int arg904,int arg905,int arg906,int arg907,int arg908,int arg909,int arg910,int arg911,int arg912,int arg913,int arg914,int arg915,int arg916,int arg917,int arg918,int arg919,int arg920,int arg921,int arg922,int arg923,int arg924,int arg925,int arg926,int arg927,int arg928,int arg929,int arg930,int arg931,int arg932,int arg933,int arg934,int arg935,int arg936,int arg937,int arg938,int arg939,int arg940,int arg941,int arg942,int arg943,int arg944,int arg945,int arg946,int arg947,int arg948,int arg949,int arg950,int arg951,int arg952,int arg953,int arg954,int arg955,int arg956,int arg957,int arg958,int arg959,int arg960,int arg961,int arg962,int arg963,int arg964,int arg965,int arg966,int arg967,int arg968,int arg969,int arg970,int arg971,int arg972,int arg973,int arg974,int arg975,int arg976,int arg977,int arg978,int arg979,int arg980,int arg981,int arg982,int arg983,int arg984,int arg985,int arg986,int arg987,int arg988,int arg989,int arg990,int arg991,int arg992,int arg993,int arg994,int arg995,int arg996,int arg997,int arg998,int arg999,int arg1000,int arg1001,int arg1002,int arg1003,int arg1004,int arg1005,int arg1006,int arg1007,int arg1008,int arg1009,int arg1010,int arg1011,int arg1012,int arg1013,int arg1014,int arg1015,int arg1016,int arg1017,int arg1018,int arg1019,int arg1020,int arg1021,int arg1022,int arg1023,int arg1024,int arg1025,int arg1026,int arg1027,int arg1028,int arg1029,int arg1030,int arg1031,int arg1032,int arg1033,int arg1034,int arg1035,int arg1036,int arg1037,int arg1038,int arg1039,int arg1040,int arg1041,int arg1042,int arg1043,int arg1044,int arg1045,int arg1046,int arg1047,int arg1048,int arg1049,int arg1050,int arg1051,int arg1052,int arg1053,int arg1054,int arg1055,int arg1056,int arg1057,int arg1058,int arg1059,int arg1060,int arg1061,int arg1062,int arg1063,int arg1064,int arg1065,int arg1066,int arg1067,int arg1068,int arg1069,int arg1070,int arg1071,int arg1072,int arg1073,int arg1074,int arg1075,int arg1076,int arg1077,int arg1078,int arg1079,int arg1080,int arg1081,int arg1082,int arg1083,int arg1084,int arg1085,int arg1086,int arg1087,int arg1088,int arg1089,int arg1090,int arg1091,int arg1092,int arg1093,int arg1094,int arg1095,int arg1096,int arg1097,int arg1098,int arg1099,int arg1100,int arg1101,int arg1102,int arg1103,int arg1104,int arg1105,int arg1106,int arg1107,int arg1108,int arg1109,int arg1110,int arg1111,int arg1112,int arg1113,int arg1114,int arg1115,int arg1116,int arg1117,int arg1118,int arg1119,int arg1120,int arg1121,int arg1122,int arg1123,int arg1124,int arg1125,int arg1126,int arg1127,int arg1128,int arg1129,int arg1130,int arg1131,int arg1132,int arg1133,int arg1134,int arg1135,int arg1136,int arg1137,int arg1138,int arg1139,int arg1140,int arg1141,int arg1142,int arg1143,int arg1144,int arg1145,int arg1146,int arg1147,int arg1148,int arg1149,int arg1150,int arg1151,int arg1152,int arg1153,int arg1154,int arg1155,int arg1156,int arg1157,int arg1158,int arg1159,int arg1160,int arg1161,int arg1162,int arg1163,int arg1164,int arg1165,int arg1166,int arg1167,int arg1168,int arg1169,int arg1170,int arg1171,int arg1172,int arg1173,int arg1174,int arg1175,int arg1176,int arg1177,int arg1178,int arg1179,int arg1180,int arg1181,int arg1182,int arg1183,int arg1184,int arg1185,int arg1186,int arg1187,int arg1188,int arg1189,int arg1190,int arg1191,int arg1192,int arg1193,int arg1194,int arg1195,int arg1196,int arg1197,int arg1198,int arg1199,int arg1200,int arg1201,int arg1202,int arg1203,int arg1204,int arg1205,int arg1206,int arg1207,int arg1208,int arg1209,int arg1210,int arg1211,int arg1212,int arg1213,int arg1214,int arg1215,int arg1216,int arg1217,int arg1218,int arg1219,int arg1220,int arg1221,int arg1222,int arg1223,int arg1224,int arg1225,int arg1226,int arg1227,int arg1228,int arg1229,int arg1230,int arg1231,int arg1232,int arg1233,int arg1234,int arg1235,int arg1236,int arg1237,int arg1238,int arg1239,int arg1240,int arg1241,int arg1242,int arg1243,int arg1244,int arg1245,int arg1246,int arg1247,int arg1248,int arg1249,int arg1250,int arg1251,int arg1252,int arg1253,int arg1254,int arg1255,int arg1256,int arg1257,int arg1258,int arg1259,int arg1260,int arg1261,int arg1262,int arg1263,int arg1264,int arg1265,int arg1266,int arg1267,int arg1268,int arg1269,int arg1270,int arg1271,int arg1272,int arg1273,int arg1274,int arg1275,int arg1276,int arg1277,int arg1278,int arg1279,int arg1280,int arg1281,int arg1282,int arg1283,int arg1284,int arg1285,int arg1286,int arg1287,int arg1288,int arg1289,int arg1290,int arg1291,int arg1292,int arg1293,int arg1294,int arg1295,int arg1296,int arg1297,int arg1298,int arg1299,int arg1300,int arg1301,int arg1302,int arg1303,int arg1304,int arg1305,int arg1306,int arg1307,int arg1308,int arg1309,int arg1310,int arg1311,int arg1312,int arg1313,int arg1314,int arg1315,int arg1316,int arg1317,int arg1318,int arg1319,int arg1320,int arg1321,int arg1322,int arg1323,int arg1324,int arg1325,int arg1326,int arg1327,int arg1328,int arg1329,int arg1330,int arg1331,int arg1332,int arg1333,int arg1334,int arg1335,int arg1336,int arg1337,int arg1338,int arg1339,int arg1340,int arg1341,int arg1342,int arg1343,int arg1344,int arg1345,int arg1346,int arg1347,int arg1348,int arg1349,int arg1350,int arg1351,int arg1352,int arg1353,int arg1354,int arg1355,int arg1356,int arg1357,int arg1358,int arg1359,int arg1360,int arg1361,int arg1362,int arg1363,int arg1364,int arg1365,int arg1366,int arg1367,int arg1368,int arg1369,int arg1370,int arg1371,int arg1372,int arg1373,int arg1374,int arg1375,int arg1376,int arg1377,int arg1378,int arg1379,int arg1380,int arg1381,int arg1382,int arg1383,int arg1384,int arg1385,int arg1386,int arg1387,int arg1388,int arg1389,int arg1390,int arg1391,int arg1392,int arg1393,int arg1394,int arg1395,int arg1396,int arg1397,int arg1398,int arg1399,int arg1400,int arg1401,int arg1402,int arg1403,int arg1404,int arg1405,int arg1406,int arg1407,int arg1408,int arg1409,int arg1410,int arg1411,int arg1412,int arg1413,int arg1414,int arg1415,int arg1416,int arg1417,int arg1418,int arg1419,int arg1420,int arg1421,int arg1422,int arg1423,int arg1424,int arg1425,int arg1426,int arg1427,int arg1428,int arg1429,int arg1430,int arg1431,int arg1432,int arg1433,int arg1434,int arg1435,int arg1436,int arg1437,int arg1438,int arg1439,int arg1440,int arg1441,int arg1442,int arg1443,int arg1444,int arg1445,int arg1446,int arg1447,int arg1448,int arg1449,int arg1450,int arg1451,int arg1452,int arg1453,int arg1454,int arg1455,int arg1456,int arg1457,int arg1458,int arg1459,int arg1460,int arg1461,int arg1462,int arg1463,int arg1464,int arg1465,int arg1466,int arg1467,int arg1468,int arg1469,int arg1470,int arg1471,int arg1472,int arg1473,int arg1474,int arg1475,int arg1476,int arg1477,int arg1478,int arg1479,int arg1480,int arg1481,int arg1482,int arg1483,int arg1484,int arg1485,int arg1486,int arg1487,int arg1488,int arg1489,int arg1490,int arg1491,int arg1492,int arg1493,int arg1494,int arg1495,int arg1496,int arg1497,int arg1498,int arg1499,int arg1500,int arg1501,int arg1502,int arg1503,int arg1504,int arg1505,int arg1506,int arg1507,int arg1508,int arg1509,int arg1510,int arg1511,int arg1512,int arg1513,int arg1514,int arg1515,int arg1516,int arg1517,int arg1518,int arg1519,int arg1520,int arg1521,int arg1522,int arg1523,int arg1524,int arg1525,int arg1526,int arg1527,int arg1528,int arg1529,int arg1530,int arg1531,int arg1532,int arg1533,int arg1534,int arg1535,int arg1536,int arg1537,int arg1538,int arg1539,int arg1540,int arg1541,int arg1542,int arg1543,int arg1544,int arg1545,int arg1546,int arg1547,int arg1548,int arg1549,int arg1550,int arg1551,int arg1552,int arg1553,int arg1554,int arg1555,int arg1556,int arg1557,int arg1558,int arg1559,int arg1560,int arg1561,int arg1562,int arg1563,int arg1564,int arg1565,int arg1566,int arg1567,int arg1568,int arg1569,int arg1570,int arg1571,int arg1572,int arg1573,int arg1574,int arg1575,int arg1576,int arg1577,int arg1578,int arg1579,int arg1580,int arg1581,int arg1582,int arg1583,int arg1584,int arg1585,int arg1586,int arg1587,int arg1588,int arg1589,int arg1590,int arg1591,int arg1592,int arg1593,int arg1594,int arg1595,int arg1596,int arg1597,int arg1598,int arg1599,int arg1600,int arg1601,int arg1602,int arg1603,int arg1604,int arg1605,int arg1606,int arg1607,int arg1608,int arg1609,int arg1610,int arg1611,int arg1612,int arg1613,int arg1614,int arg1615,int arg1616,int arg1617,int arg1618,int arg1619,int arg1620,int arg1621,int arg1622,int arg1623,int arg1624,int arg1625,int arg1626,int arg1627,int arg1628,int arg1629,int arg1630,int arg1631,int arg1632,int arg1633,int arg1634,int arg1635,int arg1636,int arg1637,int arg1638,int arg1639,int arg1640,int arg1641,int arg1642,int arg1643,int arg1644,int arg1645,int arg1646,int arg1647,int arg1648,int arg1649,int arg1650,int arg1651,int arg1652,int arg1653,int arg1654,int arg1655,int arg1656,int arg1657,int arg1658,int arg1659,int arg1660,int arg1661,int arg1662,int arg1663,int arg1664,int arg1665,int arg1666,int arg1667,int arg1668,int arg1669,int arg1670,int arg1671,int arg1672,int arg1673,int arg1674,int arg1675,int arg1676,int arg1677,int arg1678,int arg1679,int arg1680,int arg1681,int arg1682,int arg1683,int arg1684,int arg1685,int arg1686,int arg1687,int arg1688,int arg1689,int arg1690,int arg1691,int arg1692,int arg1693,int arg1694,int arg1695,int arg1696,int arg1697,int arg1698,int arg1699,int arg1700,int arg1701,int arg1702,int arg1703,int arg1704,int arg1705,int arg1706,int arg1707,int arg1708,int arg1709,int arg1710,int arg1711,int arg1712,int arg1713,int arg1714,int arg1715,int arg1716,int arg1717,int arg1718,int arg1719,int arg1720,int arg1721,int arg1722,int arg1723,int arg1724,int arg1725,int arg1726,int arg1727,int arg1728,int arg1729,int arg1730,int arg1731,int arg1732,int arg1733,int arg1734,int arg1735,int arg1736,int arg1737,int arg1738,int arg1739,int arg1740,int arg1741,int arg1742,int arg1743,int arg1744,int arg1745,int arg1746,int arg1747,int arg1748,int arg1749,int arg1750,int arg1751,int arg1752,int arg1753,int arg1754,int arg1755,int arg1756,int arg1757,int arg1758,int arg1759,int arg1760,int arg1761,int arg1762,int arg1763,int arg1764,int arg1765,int arg1766,int arg1767,int arg1768,int arg1769,int arg1770,int arg1771,int arg1772,int arg1773,int arg1774,int arg1775,int arg1776,int arg1777,int arg1778,int arg1779,int arg1780,int arg1781,int arg1782,int arg1783,int arg1784,int arg1785,int arg1786,int arg1787,int arg1788,int arg1789,int arg1790,int arg1791,int arg1792,int arg1793,int arg1794,int arg1795,int arg1796,int arg1797,int arg1798,int arg1799,int arg1800,int arg1801,int arg1802,int arg1803,int arg1804,int arg1805,int arg1806,int arg1807,int arg1808,int arg1809,int arg1810,int arg1811,int arg1812,int arg1813,int arg1814,int arg1815,int arg1816,int arg1817,int arg1818,int arg1819,int arg1820,int arg1821,int arg1822,int arg1823,int arg1824,int arg1825,int arg1826,int arg1827,int arg1828,int arg1829,int arg1830,int arg1831,int arg1832,int arg1833,int arg1834,int arg1835,int arg1836,int arg1837,int arg1838,int arg1839,int arg1840,int arg1841,int arg1842,int arg1843,int arg1844,int arg1845,int arg1846,int arg1847,int arg1848,int arg1849,int arg1850,int arg1851,int arg1852,int arg1853,int arg1854,int arg1855,int arg1856,int arg1857,int arg1858,int arg1859,int arg1860,int arg1861,int arg1862,int arg1863,int arg1864,int arg1865,int arg1866,int arg1867,int arg1868,int arg1869,int arg1870,int arg1871,int arg1872,int arg1873,int arg1874,int arg1875,int arg1876,int arg1877,int arg1878,int arg1879,int arg1880,int arg1881,int arg1882,int arg1883,int arg1884,int arg1885,int arg1886,int arg1887,int arg1888,int arg1889,int arg1890,int arg1891,int arg1892,int arg1893,int arg1894,int arg1895,int arg1896,int arg1897,int arg1898,int arg1899,int arg1900,int arg1901,int arg1902,int arg1903,int arg1904,int arg1905,int arg1906,int arg1907,int arg1908,int arg1909,int arg1910,int arg1911,int arg1912,int arg1913,int arg1914,int arg1915,int arg1916,int arg1917,int arg1918,int arg1919,int arg1920,int arg1921,int arg1922,int arg1923,int arg1924,int arg1925,int arg1926,int arg1927,int arg1928,int arg1929,int arg1930,int arg1931,int arg1932,int arg1933,int arg1934,int arg1935,int arg1936,int arg1937,int arg1938,int arg1939,int arg1940,int arg1941,int arg1942,int arg1943,int arg1944,int arg1945,int arg1946,int arg1947,int arg1948,int arg1949,int arg1950,int arg1951,int arg1952,int arg1953,int arg1954,int arg1955,int arg1956,int arg1957,int arg1958,int arg1959,int arg1960,int arg1961,int arg1962,int arg1963,int arg1964,int arg1965,int arg1966,int arg1967,int arg1968,int arg1969,int arg1970,int arg1971,int arg1972,int arg1973,int arg1974,int arg1975,int arg1976,int arg1977,int arg1978,int arg1979,int arg1980,int arg1981,int arg1982,int arg1983,int arg1984,int arg1985,int arg1986,int arg1987,int arg1988,int arg1989,int arg1990,int arg1991,int arg1992,int arg1993,int arg1994,int arg1995,int arg1996,int arg1997,int arg1998,int arg1999,int arg2000,int arg2001,int arg2002,int arg2003,int arg2004,int arg2005,int arg2006,int arg2007,int arg2008,int arg2009,int arg2010,int arg2011,int arg2012,int arg2013,int arg2014,int arg2015,int arg2016,int arg2017,int arg2018,int arg2019,int arg2020,int arg2021,int arg2022,int arg2023,int arg2024,int arg2025,int arg2026,int arg2027,int arg2028,int arg2029,int arg2030,int arg2031,int arg2032,int arg2033,int arg2034,int arg2035,int arg2036,int arg2037,int arg2038,int arg2039,int arg2040,int arg2041,int arg2042,int arg2043,int arg2044,int arg2045,int arg2046,int arg2047,int arg2048,int arg2049,int arg2050,int arg2051,int arg2052,int arg2053,int arg2054,int arg2055,int arg2056,int arg2057,int arg2058,int arg2059,int arg2060,int arg2061,int arg2062,int arg2063,int arg2064,int arg2065,int arg2066,int arg2067,int arg2068,int arg2069,int arg2070,int arg2071,int arg2072,int arg2073,int arg2074,int arg2075,int arg2076,int arg2077,int arg2078,int arg2079,int arg2080,int arg2081,int arg2082,int arg2083,int arg2084,int arg2085,int arg2086,int arg2087,int arg2088,int arg2089,int arg2090,int arg2091,int arg2092,int arg2093,int arg2094,int arg2095,int arg2096,int arg2097,int arg2098,int arg2099,int arg2100,int arg2101,int arg2102,int arg2103,int arg2104,int arg2105,int arg2106,int arg2107,int arg2108,int arg2109,int arg2110,int arg2111,int arg2112,int arg2113,int arg2114,int arg2115,int arg2116,int arg2117,int arg2118,int arg2119,int arg2120,int arg2121,int arg2122,int arg2123,int arg2124,int arg2125,int arg2126,int arg2127,int arg2128,int arg2129,int arg2130,int arg2131,int arg2132,int arg2133,int arg2134,int arg2135,int arg2136,int arg2137,int arg2138,int arg2139,int arg2140,int arg2141,int arg2142,int arg2143,int arg2144,int arg2145,int arg2146,int arg2147,int arg2148,int arg2149,int arg2150,int arg2151,int arg2152,int arg2153,int arg2154,int arg2155,int arg2156,int arg2157,int arg2158,int arg2159,int arg2160,int arg2161,int arg2162,int arg2163,int arg2164,int arg2165,int arg2166,int arg2167,int arg2168,int arg2169,int arg2170,int arg2171,int arg2172,int arg2173,int arg2174,int arg2175,int arg2176,int arg2177,int arg2178,int arg2179,int arg2180,int arg2181,int arg2182,int arg2183,int arg2184,int arg2185,int arg2186,int arg2187,int arg2188,int arg2189,int arg2190,int arg2191,int arg2192,int arg2193,int arg2194,int arg2195,int arg2196,int arg2197,int arg2198,int arg2199,int arg2200,int arg2201,int arg2202,int arg2203,int arg2204,int arg2205,int arg2206,int arg2207,int arg2208,int arg2209,int arg2210,int arg2211,int arg2212,int arg2213,int arg2214,int arg2215,int arg2216,int arg2217,int arg2218,int arg2219,int arg2220,int arg2221,int arg2222,int arg2223,int arg2224,int arg2225,int arg2226,int arg2227,int arg2228,int arg2229,int arg2230,int arg2231,int arg2232,int arg2233,int arg2234,int arg2235,int arg2236,int arg2237,int arg2238,int arg2239,int arg2240,int arg2241,int arg2242,int arg2243,int arg2244,int arg2245,int arg2246,int arg2247,int arg2248,int arg2249,int arg2250,int arg2251,int arg2252,int arg2253,int arg2254,int arg2255,int arg2256,int arg2257,int arg2258,int arg2259,int arg2260,int arg2261,int arg2262,int arg2263,int arg2264,int arg2265,int arg2266,int arg2267,int arg2268,int arg2269,int arg2270,int arg2271,int arg2272,int arg2273,int arg2274,int arg2275,int arg2276,int arg2277,int arg2278,int arg2279,int arg2280,int arg2281,int arg2282,int arg2283,int arg2284,int arg2285,int arg2286,int arg2287,int arg2288,int arg2289,int arg2290,int arg2291,int arg2292,int arg2293,int arg2294,int arg2295,int arg2296,int arg2297,int arg2298,int arg2299,int arg2300,int arg2301,int arg2302,int arg2303,int arg2304,int arg2305,int arg2306,int arg2307,int arg2308,int arg2309,int arg2310,int arg2311,int arg2312,int arg2313,int arg2314,int arg2315,int arg2316,int arg2317,int arg2318,int arg2319,int arg2320,int arg2321,int arg2322,int arg2323,int arg2324,int arg2325,int arg2326,int arg2327,int arg2328,int arg2329,int arg2330,int arg2331,int arg2332,int arg2333,int arg2334,int arg2335,int arg2336,int arg2337,int arg2338,int arg2339,int arg2340,int arg2341,int arg2342,int arg2343,int arg2344,int arg2345,int arg2346,int arg2347,int arg2348,int arg2349,int arg2350,int arg2351,int arg2352,int arg2353,int arg2354,int arg2355,int arg2356,int arg2357,int arg2358,int arg2359,int arg2360,int arg2361,int arg2362,int arg2363,int arg2364,int arg2365,int arg2366,int arg2367,int arg2368,int arg2369,int arg2370,int arg2371,int arg2372,int arg2373,int arg2374,int arg2375,int arg2376,int arg2377,int arg2378,int arg2379,int arg2380,int arg2381,int arg2382,int arg2383,int arg2384,int arg2385,int arg2386,int arg2387,int arg2388,int arg2389,int arg2390,int arg2391,int arg2392,int arg2393,int arg2394,int arg2395,int arg2396,int arg2397,int arg2398,int arg2399,int arg2400,int arg2401,int arg2402,int arg2403,int arg2404,int arg2405,int arg2406,int arg2407,int arg2408,int arg2409,int arg2410,int arg2411,int arg2412,int arg2413,int arg2414,int arg2415,int arg2416,int arg2417,int arg2418,int arg2419,int arg2420,int arg2421,int arg2422,int arg2423,int arg2424,int arg2425,int arg2426,int arg2427,int arg2428,int arg2429,int arg2430,int arg2431,int arg2432,int arg2433,int arg2434,int arg2435,int arg2436,int arg2437,int arg2438,int arg2439,int arg2440,int arg2441,int arg2442,int arg2443,int arg2444,int arg2445,int arg2446,int arg2447,int arg2448,int arg2449,int arg2450,int arg2451,int arg2452,int arg2453,int arg2454,int arg2455,int arg2456,int arg2457,int arg2458,int arg2459,int arg2460,int arg2461,int arg2462,int arg2463,int arg2464,int arg2465,int arg2466,int arg2467,int arg2468,int arg2469,int arg2470,int arg2471,int arg2472,int arg2473,int arg2474,int arg2475,int arg2476,int arg2477,int arg2478,int arg2479,int arg2480,int arg2481,int arg2482,int arg2483,int arg2484,int arg2485,int arg2486,int arg2487,int arg2488,int arg2489,int arg2490,int arg2491,int arg2492,int arg2493,int arg2494,int arg2495,int arg2496,int arg2497,int arg2498,int arg2499,int arg2500,int arg2501,int arg2502,int arg2503,int arg2504,int arg2505,int arg2506,int arg2507,int arg2508,int arg2509,int arg2510,int arg2511,int arg2512,int arg2513,int arg2514,int arg2515,int arg2516,int arg2517,int arg2518,int arg2519,int arg2520,int arg2521,int arg2522,int arg2523,int arg2524,int arg2525,int arg2526,int arg2527,int arg2528,int arg2529,int arg2530,int arg2531,int arg2532,int arg2533,int arg2534,int arg2535,int arg2536,int arg2537,int arg2538,int arg2539,int arg2540,int arg2541,int arg2542,int arg2543,int arg2544,int arg2545,int arg2546,int arg2547,int arg2548,int arg2549,int arg2550,int arg2551,int arg2552,int arg2553,int arg2554,int arg2555,int arg2556,int arg2557,int arg2558,int arg2559,int arg2560,int arg2561,int arg2562,int arg2563,int arg2564,int arg2565,int arg2566,int arg2567,int arg2568,int arg2569,int arg2570,int arg2571,int arg2572,int arg2573,int arg2574,int arg2575,int arg2576,int arg2577,int arg2578,int arg2579,int arg2580,int arg2581,int arg2582,int arg2583,int arg2584,int arg2585,int arg2586,int arg2587,int arg2588,int arg2589,int arg2590,int arg2591,int arg2592,int arg2593,int arg2594,int arg2595,int arg2596,int arg2597,int arg2598,int arg2599,int arg2600,int arg2601,int arg2602,int arg2603,int arg2604,int arg2605,int arg2606,int arg2607,int arg2608,int arg2609,int arg2610,int arg2611,int arg2612,int arg2613,int arg2614,int arg2615,int arg2616,int arg2617,int arg2618,int arg2619,int arg2620,int arg2621,int arg2622,int arg2623,int arg2624,int arg2625,int arg2626,int arg2627,int arg2628,int arg2629,int arg2630,int arg2631,int arg2632,int arg2633,int arg2634,int arg2635,int arg2636,int arg2637,int arg2638,int arg2639,int arg2640,int arg2641,int arg2642,int arg2643,int arg2644,int arg2645,int arg2646,int arg2647,int arg2648,int arg2649,int arg2650,int arg2651,int arg2652,int arg2653,int arg2654,int arg2655,int arg2656,int arg2657,int arg2658,int arg2659,int arg2660,int arg2661,int arg2662,int arg2663,int arg2664,int arg2665,int arg2666,int arg2667,int arg2668,int arg2669,int arg2670,int arg2671,int arg2672,int arg2673,int arg2674,int arg2675,int arg2676,int arg2677,int arg2678,int arg2679,int arg2680,int arg2681,int arg2682,int arg2683,int arg2684,int arg2685,int arg2686,int arg2687,int arg2688,int arg2689,int arg2690,int arg2691,int arg2692,int arg2693,int arg2694,int arg2695,int arg2696,int arg2697,int arg2698,int arg2699,int arg2700,int arg2701,int arg2702,int arg2703,int arg2704,int arg2705,int arg2706,int arg2707,int arg2708,int arg2709,int arg2710,int arg2711,int arg2712,int arg2713,int arg2714,int arg2715,int arg2716,int arg2717,int arg2718,int arg2719,int arg2720,int arg2721,int arg2722,int arg2723,int arg2724,int arg2725,int arg2726,int arg2727,int arg2728,int arg2729,int arg2730,int arg2731,int arg2732,int arg2733,int arg2734,int arg2735,int arg2736,int arg2737,int arg2738,int arg2739,int arg2740,int arg2741,int arg2742,int arg2743,int arg2744,int arg2745,int arg2746,int arg2747,int arg2748,int arg2749,int arg2750,int arg2751,int arg2752,int arg2753,int arg2754,int arg2755,int arg2756,int arg2757,int arg2758,int arg2759,int arg2760,int arg2761,int arg2762,int arg2763,int arg2764,int arg2765,int arg2766,int arg2767,int arg2768,int arg2769,int arg2770,int arg2771,int arg2772,int arg2773,int arg2774,int arg2775,int arg2776,int arg2777,int arg2778,int arg2779,int arg2780,int arg2781,int arg2782,int arg2783,int arg2784,int arg2785,int arg2786,int arg2787,int arg2788,int arg2789,int arg2790,int arg2791,int arg2792,int arg2793,int arg2794,int arg2795,int arg2796,int arg2797,int arg2798,int arg2799,int arg2800,int arg2801,int arg2802,int arg2803,int arg2804,int arg2805,int arg2806,int arg2807,int arg2808,int arg2809,int arg2810,int arg2811,int arg2812,int arg2813,int arg2814,int arg2815,int arg2816,int arg2817,int arg2818,int arg2819,int arg2820,int arg2821,int arg2822,int arg2823,int arg2824,int arg2825,int arg2826,int arg2827,int arg2828,int arg2829,int arg2830,int arg2831,int arg2832,int arg2833,int arg2834,int arg2835,int arg2836,int arg2837,int arg2838,int arg2839,int arg2840,int arg2841,int arg2842,int arg2843,int arg2844,int arg2845,int arg2846,int arg2847,int arg2848,int arg2849,int arg2850,int arg2851,int arg2852,int arg2853,int arg2854,int arg2855,int arg2856,int arg2857,int arg2858,int arg2859,int arg2860,int arg2861,int arg2862,int arg2863,int arg2864,int arg2865,int arg2866,int arg2867,int arg2868,int arg2869,int arg2870,int arg2871,int arg2872,int arg2873,int arg2874,int arg2875,int arg2876,int arg2877,int arg2878,int arg2879,int arg2880,int arg2881,int arg2882,int arg2883,int arg2884,int arg2885,int arg2886,int arg2887,int arg2888,int arg2889,int arg2890,int arg2891,int arg2892,int arg2893,int arg2894,int arg2895,int arg2896,int arg2897,int arg2898,int arg2899,int arg2900,int arg2901,int arg2902,int arg2903,int arg2904,int arg2905,int arg2906,int arg2907,int arg2908,int arg2909,int arg2910,int arg2911,int arg2912,int arg2913,int arg2914,int arg2915,int arg2916,int arg2917,int arg2918,int arg2919,int arg2920,int arg2921,int arg2922,int arg2923,int arg2924,int arg2925,int arg2926,int arg2927,int arg2928,int arg2929,int arg2930,int arg2931,int arg2932,int arg2933,int arg2934,int arg2935,int arg2936,int arg2937,int arg2938,int arg2939,int arg2940,int arg2941,int arg2942,int arg2943,int arg2944,int arg2945,int arg2946,int arg2947,int arg2948,int arg2949,int arg2950,int arg2951,int arg2952,int arg2953,int arg2954,int arg2955,int arg2956,int arg2957,int arg2958,int arg2959,int arg2960,int arg2961,int arg2962,int arg2963,int arg2964,int arg2965,int arg2966,int arg2967,int arg2968,int arg2969,int arg2970,int arg2971,int arg2972,int arg2973,int arg2974,int arg2975,int arg2976,int arg2977,int arg2978,int arg2979,int arg2980,int arg2981,int arg2982,int arg2983,int arg2984,int arg2985,int arg2986,int arg2987,int arg2988,int arg2989,int arg2990,int arg2991,int arg2992,int arg2993,int arg2994,int arg2995,int arg2996,int arg2997,int arg2998,int arg2999,int arg3000,int arg3001,int arg3002,int arg3003,int arg3004,int arg3005,int arg3006,int arg3007,int arg3008,int arg3009,int arg3010,int arg3011,int arg3012,int arg3013,int arg3014,int arg3015,int arg3016,int arg3017,int arg3018,int arg3019,int arg3020,int arg3021,int arg3022,int arg3023,int arg3024,int arg3025,int arg3026,int arg3027,int arg3028,int arg3029,int arg3030,int arg3031,int arg3032,int arg3033,int arg3034,int arg3035,int arg3036,int arg3037,int arg3038,int arg3039,int arg3040,int arg3041,int arg3042,int arg3043,int arg3044,int arg3045,int arg3046,int arg3047,int arg3048,int arg3049,int arg3050,int arg3051,int arg3052,int arg3053,int arg3054,int arg3055,int arg3056,int arg3057,int arg3058,int arg3059,int arg3060,int arg3061,int arg3062,int arg3063,int arg3064,int arg3065,int arg3066,int arg3067,int arg3068,int arg3069,int arg3070,int arg3071,int arg3072,int arg3073,int arg3074,int arg3075,int arg3076,int arg3077,int arg3078,int arg3079,int arg3080,int arg3081,int arg3082,int arg3083,int arg3084,int arg3085,int arg3086,int arg3087,int arg3088,int arg3089,int arg3090,int arg3091,int arg3092,int arg3093,int arg3094,int arg3095,int arg3096,int arg3097,int arg3098,int arg3099,int arg3100,int arg3101,int arg3102,int arg3103,int arg3104,int arg3105,int arg3106,int arg3107,int arg3108,int arg3109,int arg3110,int arg3111,int arg3112,int arg3113,int arg3114,int arg3115,int arg3116,int arg3117,int arg3118,int arg3119,int arg3120,int arg3121,int arg3122,int arg3123,int arg3124,int arg3125,int arg3126,int arg3127,int arg3128,int arg3129,int arg3130,int arg3131,int arg3132,int arg3133,int arg3134,int arg3135,int arg3136,int arg3137,int arg3138,int arg3139,int arg3140,int arg3141,int arg3142,int arg3143,int arg3144,int arg3145,int arg3146,int arg3147,int arg3148,int arg3149,int arg3150,int arg3151,int arg3152,int arg3153,int arg3154,int arg3155,int arg3156,int arg3157,int arg3158,int arg3159,int arg3160,int arg3161,int arg3162,int arg3163,int arg3164,int arg3165,int arg3166,int arg3167,int arg3168,int arg3169,int arg3170,int arg3171,int arg3172,int arg3173,int arg3174,int arg3175,int arg3176,int arg3177,int arg3178,int arg3179,int arg3180,int arg3181,int arg3182,int arg3183,int arg3184,int arg3185,int arg3186,int arg3187,int arg3188,int arg3189,int arg3190,int arg3191,int arg3192,int arg3193,int arg3194,int arg3195,int arg3196,int arg3197,int arg3198,int arg3199,int arg3200,int arg3201,int arg3202,int arg3203,int arg3204,int arg3205,int arg3206,int arg3207,int arg3208,int arg3209,int arg3210,int arg3211,int arg3212,int arg3213,int arg3214,int arg3215,int arg3216,int arg3217,int arg3218,int arg3219,int arg3220,int arg3221,int arg3222,int arg3223,int arg3224,int arg3225,int arg3226,int arg3227,int arg3228,int arg3229,int arg3230,int arg3231,int arg3232,int arg3233,int arg3234,int arg3235,int arg3236,int arg3237,int arg3238,int arg3239,int arg3240,int arg3241,int arg3242,int arg3243,int arg3244,int arg3245,int arg3246,int arg3247,int arg3248,int arg3249,int arg3250,int arg3251,int arg3252,int arg3253,int arg3254,int arg3255,int arg3256,int arg3257,int arg3258,int arg3259,int arg3260,int arg3261,int arg3262,int arg3263,int arg3264,int arg3265,int arg3266,int arg3267,int arg3268,int arg3269,int arg3270,int arg3271,int arg3272,int arg3273,int arg3274,int arg3275,int arg3276,int arg3277,int arg3278,int arg3279,int arg3280,int arg3281,int arg3282,int arg3283,int arg3284,int arg3285,int arg3286,int arg3287,int arg3288,int arg3289,int arg3290,int arg3291,int arg3292,int arg3293,int arg3294,int arg3295,int arg3296,int arg3297,int arg3298,int arg3299,int arg3300,int arg3301,int arg3302,int arg3303,int arg3304,int arg3305,int arg3306,int arg3307,int arg3308,int arg3309,int arg3310,int arg3311,int arg3312,int arg3313,int arg3314,int arg3315,int arg3316,int arg3317,int arg3318,int arg3319,int arg3320,int arg3321,int arg3322,int arg3323,int arg3324,int arg3325,int arg3326,int arg3327,int arg3328,int arg3329,int arg3330,int arg3331,int arg3332,int arg3333,int arg3334,int arg3335,int arg3336,int arg3337,int arg3338,int arg3339,int arg3340,int arg3341,int arg3342,int arg3343,int arg3344,int arg3345,int arg3346,int arg3347,int arg3348,int arg3349,int arg3350,int arg3351,int arg3352,int arg3353,int arg3354,int arg3355,int arg3356,int arg3357,int arg3358,int arg3359,int arg3360,int arg3361,int arg3362,int arg3363,int arg3364,int arg3365,int arg3366,int arg3367,int arg3368,int arg3369,int arg3370,int arg3371,int arg3372,int arg3373,int arg3374,int arg3375,int arg3376,int arg3377,int arg3378,int arg3379,int arg3380,int arg3381,int arg3382,int arg3383,int arg3384,int arg3385,int arg3386,int arg3387,int arg3388,int arg3389,int arg3390,int arg3391,int arg3392,int arg3393,int arg3394,int arg3395,int arg3396,int arg3397,int arg3398,int arg3399,int arg3400,int arg3401,int arg3402,int arg3403,int arg3404,int arg3405,int arg3406,int arg3407,int arg3408,int arg3409,int arg3410,int arg3411,int arg3412,int arg3413,int arg3414,int arg3415,int arg3416,int arg3417,int arg3418,int arg3419,int arg3420,int arg3421,int arg3422,int arg3423,int arg3424,int arg3425,int arg3426,int arg3427,int arg3428,int arg3429,int arg3430,int arg3431,int arg3432,int arg3433,int arg3434,int arg3435,int arg3436,int arg3437,int arg3438,int arg3439,int arg3440,int arg3441,int arg3442,int arg3443,int arg3444,int arg3445,int arg3446,int arg3447,int arg3448,int arg3449,int arg3450,int arg3451,int arg3452,int arg3453,int arg3454,int arg3455,int arg3456,int arg3457,int arg3458,int arg3459,int arg3460,int arg3461,int arg3462,int arg3463,int arg3464,int arg3465,int arg3466,int arg3467,int arg3468,int arg3469,int arg3470,int arg3471,int arg3472,int arg3473,int arg3474,int arg3475,int arg3476,int arg3477,int arg3478,int arg3479,int arg3480,int arg3481,int arg3482,int arg3483,int arg3484,int arg3485,int arg3486,int arg3487,int arg3488,int arg3489,int arg3490,int arg3491,int arg3492,int arg3493,int arg3494,int arg3495,int arg3496,int arg3497,int arg3498,int arg3499,int arg3500,int arg3501,int arg3502,int arg3503,int arg3504,int arg3505,int arg3506,int arg3507,int arg3508,int arg3509,int arg3510,int arg3511,int arg3512,int arg3513,int arg3514,int arg3515,int arg3516,int arg3517,int arg3518,int arg3519,int arg3520,int arg3521,int arg3522,int arg3523,int arg3524,int arg3525,int arg3526,int arg3527,int arg3528,int arg3529,int arg3530,int arg3531,int arg3532,int arg3533,int arg3534,int arg3535,int arg3536,int arg3537,int arg3538,int arg3539,int arg3540,int arg3541,int arg3542,int arg3543,int arg3544,int arg3545,int arg3546,int arg3547,int arg3548,int arg3549,int arg3550,int arg3551,int arg3552,int arg3553,int arg3554,int arg3555,int arg3556,int arg3557,int arg3558,int arg3559,int arg3560,int arg3561,int arg3562,int arg3563,int arg3564,int arg3565,int arg3566,int arg3567,int arg3568,int arg3569,int arg3570,int arg3571,int arg3572,int arg3573,int arg3574,int arg3575,int arg3576,int arg3577,int arg3578,int arg3579,int arg3580,int arg3581,int arg3582,int arg3583,int arg3584,int arg3585,int arg3586,int arg3587,int arg3588,int arg3589,int arg3590,int arg3591,int arg3592,int arg3593,int arg3594,int arg3595,int arg3596,int arg3597,int arg3598,int arg3599,int arg3600,int arg3601,int arg3602,int arg3603,int arg3604,int arg3605,int arg3606,int arg3607,int arg3608,int arg3609,int arg3610,int arg3611,int arg3612,int arg3613,int arg3614,int arg3615,int arg3616,int arg3617,int arg3618,int arg3619,int arg3620,int arg3621,int arg3622,int arg3623,int arg3624,int arg3625,int arg3626,int arg3627,int arg3628,int arg3629,int arg3630,int arg3631,int arg3632,int arg3633,int arg3634,int arg3635,int arg3636,int arg3637,int arg3638,int arg3639,int arg3640,int arg3641,int arg3642,int arg3643,int arg3644,int arg3645,int arg3646,int arg3647,int arg3648,int arg3649,int arg3650,int arg3651,int arg3652,int arg3653,int arg3654,int arg3655,int arg3656,int arg3657,int arg3658,int arg3659,int arg3660,int arg3661,int arg3662,int arg3663,int arg3664,int arg3665,int arg3666,int arg3667,int arg3668,int arg3669,int arg3670,int arg3671,int arg3672,int arg3673,int arg3674,int arg3675,int arg3676,int arg3677,int arg3678,int arg3679,int arg3680,int arg3681,int arg3682,int arg3683,int arg3684,int arg3685,int arg3686,int arg3687,int arg3688,int arg3689,int arg3690,int arg3691,int arg3692,int arg3693,int arg3694,int arg3695,int arg3696,int arg3697,int arg3698,int arg3699,int arg3700,int arg3701,int arg3702,int arg3703,int arg3704,int arg3705,int arg3706,int arg3707,int arg3708,int arg3709,int arg3710,int arg3711,int arg3712,int arg3713,int arg3714,int arg3715,int arg3716,int arg3717,int arg3718,int arg3719,int arg3720,int arg3721,int arg3722,int arg3723,int arg3724,int arg3725,int arg3726,int arg3727,int arg3728,int arg3729,int arg3730,int arg3731,int arg3732,int arg3733,int arg3734,int arg3735,int arg3736,int arg3737,int arg3738,int arg3739,int arg3740,int arg3741,int arg3742,int arg3743,int arg3744,int arg3745,int arg3746,int arg3747,int arg3748,int arg3749,int arg3750,int arg3751,int arg3752,int arg3753,int arg3754,int arg3755,int arg3756,int arg3757,int arg3758,int arg3759,int arg3760,int arg3761,int arg3762,int arg3763,int arg3764,int arg3765,int arg3766,int arg3767,int arg3768,int arg3769,int arg3770,int arg3771,int arg3772,int arg3773,int arg3774,int arg3775,int arg3776,int arg3777,int arg3778,int arg3779,int arg3780,int arg3781,int arg3782,int arg3783,int arg3784,int arg3785,int arg3786,int arg3787,int arg3788,int arg3789,int arg3790,int arg3791,int arg3792,int arg3793,int arg3794,int arg3795,int arg3796,int arg3797,int arg3798,int arg3799,int arg3800,int arg3801,int arg3802,int arg3803,int arg3804,int arg3805,int arg3806,int arg3807,int arg3808,int arg3809,int arg3810,int arg3811,int arg3812,int arg3813,int arg3814,int arg3815,int arg3816,int arg3817,int arg3818,int arg3819,int arg3820,int arg3821,int arg3822,int arg3823,int arg3824,int arg3825,int arg3826,int arg3827,int arg3828,int arg3829,int arg3830,int arg3831,int arg3832,int arg3833,int arg3834,int arg3835,int arg3836,int arg3837,int arg3838,int arg3839,int arg3840,int arg3841,int arg3842,int arg3843,int arg3844,int arg3845,int arg3846,int arg3847,int arg3848,int arg3849,int arg3850,int arg3851,int arg3852,int arg3853,int arg3854,int arg3855,int arg3856,int arg3857,int arg3858,int arg3859,int arg3860,int arg3861,int arg3862,int arg3863,int arg3864,int arg3865,int arg3866,int arg3867,int arg3868,int arg3869,int arg3870,int arg3871,int arg3872,int arg3873,int arg3874,int arg3875,int arg3876,int arg3877,int arg3878,int arg3879,int arg3880,int arg3881,int arg3882,int arg3883,int arg3884,int arg3885,int arg3886,int arg3887,int arg3888,int arg3889,int arg3890,int arg3891,int arg3892,int arg3893,int arg3894,int arg3895,int arg3896,int arg3897,int arg3898,int arg3899,int arg3900,int arg3901,int arg3902,int arg3903,int arg3904,int arg3905,int arg3906,int arg3907,int arg3908,int arg3909,int arg3910,int arg3911,int arg3912,int arg3913,int arg3914,int arg3915,int arg3916,int arg3917,int arg3918,int arg3919,int arg3920,int arg3921,int arg3922,int arg3923,int arg3924,int arg3925,int arg3926,int arg3927,int arg3928,int arg3929,int arg3930,int arg3931,int arg3932,int arg3933,int arg3934,int arg3935,int arg3936,int arg3937,int arg3938,int arg3939,int arg3940,int arg3941,int arg3942,int arg3943,int arg3944,int arg3945,int arg3946,int arg3947,int arg3948,int arg3949,int arg3950,int arg3951,int arg3952,int arg3953,int arg3954,int arg3955,int arg3956,int arg3957,int arg3958,int arg3959,int arg3960,int arg3961,int arg3962,int arg3963,int arg3964,int arg3965,int arg3966,int arg3967,int arg3968,int arg3969,int arg3970,int arg3971,int arg3972,int arg3973,int arg3974,int arg3975,int arg3976,int arg3977,int arg3978,int arg3979,int arg3980,int arg3981,int arg3982,int arg3983,int arg3984,int arg3985,int arg3986,int arg3987,int arg3988,int arg3989,int arg3990,int arg3991,int arg3992,int arg3993,int arg3994,int arg3995,int arg3996,int arg3997,int arg3998,int arg3999,int arg4000,int arg4001,int arg4002,int arg4003,int arg4004,int arg4005,int arg4006,int arg4007,int arg4008,int arg4009,int arg4010,int arg4011,int arg4012,int arg4013,int arg4014,int arg4015,int arg4016,int arg4017,int arg4018,int arg4019,int arg4020,int arg4021,int arg4022,int arg4023,int arg4024,int arg4025,int arg4026,int arg4027,int arg4028,int arg4029,int arg4030,int arg4031,int arg4032,int arg4033,int arg4034,int arg4035,int arg4036,int arg4037,int arg4038,int arg4039,int arg4040,int arg4041,int arg4042,int arg4043,int arg4044,int arg4045,int arg4046,int arg4047,int arg4048,int arg4049,int arg4050,int arg4051,int arg4052,int arg4053,int arg4054,int arg4055,int arg4056,int arg4057,int arg4058,int arg4059,int arg4060,int arg4061,int arg4062,int arg4063,int arg4064,int arg4065,int arg4066,int arg4067,int arg4068,int arg4069,int arg4070,int arg4071,int arg4072,int arg4073,int arg4074,int arg4075,int arg4076,int arg4077,int arg4078,int arg4079,int arg4080,int arg4081,int arg4082,int arg4083,int arg4084,int arg4085,int arg4086,int arg4087,int arg4088,int arg4089,int arg4090,int arg4091,int arg4092,int arg4093,int arg4094,int arg4095,int arg4096,int arg4097,int arg4098,int arg4099,int arg4100,int arg4101,int arg4102,int arg4103,int arg4104,int arg4105,int arg4106,int arg4107,int arg4108,int arg4109,int arg4110,int arg4111,int arg4112,int arg4113,int arg4114,int arg4115,int arg4116,int arg4117,int arg4118,int arg4119,int arg4120,int arg4121,int arg4122,int arg4123,int arg4124,int arg4125,int arg4126,int arg4127,int arg4128,int arg4129,int arg4130,int arg4131,int arg4132,int arg4133,int arg4134,int arg4135,int arg4136,int arg4137,int arg4138,int arg4139,int arg4140,int arg4141,int arg4142,int arg4143,int arg4144,int arg4145,int arg4146,int arg4147,int arg4148,int arg4149,int arg4150,int arg4151,int arg4152,int arg4153,int arg4154,int arg4155,int arg4156,int arg4157,int arg4158,int arg4159,int arg4160,int arg4161,int arg4162,int arg4163,int arg4164,int arg4165,int arg4166,int arg4167,int arg4168,int arg4169,int arg4170,int arg4171,int arg4172,int arg4173,int arg4174,int arg4175,int arg4176,int arg4177,int arg4178,int arg4179,int arg4180,int arg4181,int arg4182,int arg4183,int arg4184,int arg4185,int arg4186,int arg4187,int arg4188,int arg4189,int arg4190,int arg4191,int arg4192,int arg4193,int arg4194,int arg4195,int arg4196,int arg4197,int arg4198,int arg4199,int arg4200,int arg4201,int arg4202,int arg4203,int arg4204,int arg4205,int arg4206,int arg4207,int arg4208,int arg4209,int arg4210,int arg4211,int arg4212,int arg4213,int arg4214,int arg4215,int arg4216,int arg4217,int arg4218,int arg4219,int arg4220,int arg4221,int arg4222,int arg4223,int arg4224,int arg4225,int arg4226,int arg4227,int arg4228,int arg4229,int arg4230,int arg4231,int arg4232,int arg4233,int arg4234,int arg4235,int arg4236,int arg4237,int arg4238,int arg4239,int arg4240,int arg4241,int arg4242,int arg4243,int arg4244,int arg4245,int arg4246,int arg4247,int arg4248,int arg4249,int arg4250,int arg4251,int arg4252,int arg4253,int arg4254,int arg4255,int arg4256,int arg4257,int arg4258,int arg4259,int arg4260,int arg4261,int arg4262,int arg4263,int arg4264,int arg4265,int arg4266,int arg4267,int arg4268,int arg4269,int arg4270,int arg4271,int arg4272,int arg4273,int arg4274,int arg4275,int arg4276,int arg4277,int arg4278,int arg4279,int arg4280,int arg4281,int arg4282,int arg4283,int arg4284,int arg4285,int arg4286,int arg4287,int arg4288,int arg4289,int arg4290,int arg4291,int arg4292,int arg4293,int arg4294,int arg4295,int arg4296,int arg4297,int arg4298,int arg4299,int arg4300,int arg4301,int arg4302,int arg4303,int arg4304,int arg4305,int arg4306,int arg4307,int arg4308,int arg4309,int arg4310,int arg4311,int arg4312,int arg4313,int arg4314,int arg4315,int arg4316,int arg4317,int arg4318,int arg4319,int arg4320,int arg4321,int arg4322,int arg4323,int arg4324,int arg4325,int arg4326,int arg4327,int arg4328,int arg4329,int arg4330,int arg4331,int arg4332,int arg4333,int arg4334,int arg4335,int arg4336,int arg4337,int arg4338,int arg4339,int arg4340,int arg4341,int arg4342,int arg4343,int arg4344,int arg4345,int arg4346,int arg4347,int arg4348,int arg4349,int arg4350,int arg4351,int arg4352,int arg4353,int arg4354,int arg4355,int arg4356,int arg4357,int arg4358,int arg4359,int arg4360,int arg4361,int arg4362,int arg4363,int arg4364,int arg4365,int arg4366,int arg4367,int arg4368,int arg4369,int arg4370,int arg4371,int arg4372,int arg4373,int arg4374,int arg4375,int arg4376,int arg4377,int arg4378,int arg4379,int arg4380,int arg4381,int arg4382,int arg4383,int arg4384,int arg4385,int arg4386,int arg4387,int arg4388,int arg4389,int arg4390,int arg4391,int arg4392,int arg4393,int arg4394,int arg4395,int arg4396,int arg4397,int arg4398,int arg4399,int arg4400,int arg4401,int arg4402,int arg4403,int arg4404,int arg4405,int arg4406,int arg4407,int arg4408,int arg4409,int arg4410,int arg4411,int arg4412,int arg4413,int arg4414,int arg4415,int arg4416,int arg4417,int arg4418,int arg4419,int arg4420,int arg4421,int arg4422,int arg4423,int arg4424,int arg4425,int arg4426,int arg4427,int arg4428,int arg4429,int arg4430,int arg4431,int arg4432,int arg4433,int arg4434,int arg4435,int arg4436,int arg4437,int arg4438,int arg4439,int arg4440,int arg4441,int arg4442,int arg4443,int arg4444,int arg4445,int arg4446,int arg4447,int arg4448,int arg4449,int arg4450,int arg4451,int arg4452,int arg4453,int arg4454,int arg4455,int arg4456,int arg4457,int arg4458,int arg4459,int arg4460,int arg4461,int arg4462,int arg4463,int arg4464,int arg4465,int arg4466,int arg4467,int arg4468,int arg4469,int arg4470,int arg4471,int arg4472,int arg4473,int arg4474,int arg4475,int arg4476,int arg4477,int arg4478,int arg4479,int arg4480,int arg4481,int arg4482,int arg4483,int arg4484,int arg4485,int arg4486,int arg4487,int arg4488,int arg4489,int arg4490,int arg4491,int arg4492,int arg4493,int arg4494,int arg4495,int arg4496,int arg4497,int arg4498,int arg4499,int arg4500,int arg4501,int arg4502,int arg4503,int arg4504,int arg4505,int arg4506,int arg4507,int arg4508,int arg4509,int arg4510,int arg4511,int arg4512,int arg4513,int arg4514,int arg4515,int arg4516,int arg4517,int arg4518,int arg4519,int arg4520,int arg4521,int arg4522,int arg4523,int arg4524,int arg4525,int arg4526,int arg4527,int arg4528,int arg4529,int arg4530,int arg4531,int arg4532,int arg4533,int arg4534,int arg4535,int arg4536,int arg4537,int arg4538,int arg4539,int arg4540,int arg4541,int arg4542,int arg4543,int arg4544,int arg4545,int arg4546,int arg4547,int arg4548,int arg4549,int arg4550,int arg4551,int arg4552,int arg4553,int arg4554,int arg4555,int arg4556,int arg4557,int arg4558,int arg4559,int arg4560,int arg4561,int arg4562,int arg4563,int arg4564,int arg4565,int arg4566,int arg4567,int arg4568,int arg4569,int arg4570,int arg4571,int arg4572,int arg4573,int arg4574,int arg4575,int arg4576,int arg4577,int arg4578,int arg4579,int arg4580,int arg4581,int arg4582,int arg4583,int arg4584,int arg4585,int arg4586,int arg4587,int arg4588,int arg4589,int arg4590,int arg4591,int arg4592,int arg4593,int arg4594,int arg4595,int arg4596,int arg4597,int arg4598,int arg4599,int arg4600,int arg4601,int arg4602,int arg4603,int arg4604,int arg4605,int arg4606,int arg4607,int arg4608,int arg4609,int arg4610,int arg4611,int arg4612,int arg4613,int arg4614,int arg4615,int arg4616,int arg4617,int arg4618,int arg4619,int arg4620,int arg4621,int arg4622,int arg4623,int arg4624,int arg4625,int arg4626,int arg4627,int arg4628,int arg4629,int arg4630,int arg4631,int arg4632,int arg4633,int arg4634,int arg4635,int arg4636,int arg4637,int arg4638,int arg4639,int arg4640,int arg4641,int arg4642,int arg4643,int arg4644,int arg4645,int arg4646,int arg4647,int arg4648,int arg4649,int arg4650,int arg4651,int arg4652,int arg4653,int arg4654,int arg4655,int arg4656,int arg4657,int arg4658,int arg4659,int arg4660,int arg4661,int arg4662,int arg4663,int arg4664,int arg4665,int arg4666,int arg4667,int arg4668,int arg4669,int arg4670,int arg4671,int arg4672,int arg4673,int arg4674,int arg4675,int arg4676,int arg4677,int arg4678,int arg4679,int arg4680,int arg4681,int arg4682,int arg4683,int arg4684,int arg4685,int arg4686,int arg4687,int arg4688,int arg4689,int arg4690,int arg4691,int arg4692,int arg4693,int arg4694,int arg4695,int arg4696,int arg4697,int arg4698,int arg4699,int arg4700,int arg4701,int arg4702,int arg4703,int arg4704,int arg4705,int arg4706,int arg4707,int arg4708,int arg4709,int arg4710,int arg4711,int arg4712,int arg4713,int arg4714,int arg4715,int arg4716,int arg4717,int arg4718,int arg4719,int arg4720,int arg4721,int arg4722,int arg4723,int arg4724,int arg4725,int arg4726,int arg4727,int arg4728,int arg4729,int arg4730,int arg4731,int arg4732,int arg4733,int arg4734,int arg4735,int arg4736,int arg4737,int arg4738,int arg4739,int arg4740,int arg4741,int arg4742,int arg4743,int arg4744,int arg4745,int arg4746,int arg4747,int arg4748,int arg4749,int arg4750,int arg4751,int arg4752,int arg4753,int arg4754,int arg4755,int arg4756,int arg4757,int arg4758,int arg4759,int arg4760,int arg4761,int arg4762,int arg4763,int arg4764,int arg4765,int arg4766,int arg4767,int arg4768,int arg4769,int arg4770,int arg4771,int arg4772,int arg4773,int arg4774,int arg4775,int arg4776,int arg4777,int arg4778,int arg4779,int arg4780,int arg4781,int arg4782,int arg4783,int arg4784,int arg4785,int arg4786,int arg4787,int arg4788,int arg4789,int arg4790,int arg4791,int arg4792,int arg4793,int arg4794,int arg4795,int arg4796,int arg4797,int arg4798,int arg4799,int arg4800,int arg4801,int arg4802,int arg4803,int arg4804,int arg4805,int arg4806,int arg4807,int arg4808,int arg4809,int arg4810,int arg4811,int arg4812,int arg4813,int arg4814,int arg4815,int arg4816,int arg4817,int arg4818,int arg4819,int arg4820,int arg4821,int arg4822,int arg4823,int arg4824,int arg4825,int arg4826,int arg4827,int arg4828,int arg4829,int arg4830,int arg4831,int arg4832,int arg4833,int arg4834,int arg4835,int arg4836,int arg4837,int arg4838,int arg4839,int arg4840,int arg4841,int arg4842,int arg4843,int arg4844,int arg4845,int arg4846,int arg4847,int arg4848,int arg4849,int arg4850,int arg4851,int arg4852,int arg4853,int arg4854,int arg4855,int arg4856,int arg4857,int arg4858,int arg4859,int arg4860,int arg4861,int arg4862,int arg4863,int arg4864,int arg4865,int arg4866,int arg4867,int arg4868,int arg4869,int arg4870,int arg4871,int arg4872,int arg4873,int arg4874,int arg4875,int arg4876,int arg4877,int arg4878,int arg4879,int arg4880,int arg4881,int arg4882,int arg4883,int arg4884,int arg4885,int arg4886,int arg4887,int arg4888,int arg4889,int arg4890,int arg4891,int arg4892,int arg4893,int arg4894,int arg4895,int arg4896,int arg4897,int arg4898,int arg4899,int arg4900,int arg4901,int arg4902,int arg4903,int arg4904,int arg4905,int arg4906,int arg4907,int arg4908,int arg4909,int arg4910,int arg4911,int arg4912,int arg4913,int arg4914,int arg4915,int arg4916,int arg4917,int arg4918,int arg4919,int arg4920,int arg4921,int arg4922,int arg4923,int arg4924,int arg4925,int arg4926,int arg4927,int arg4928,int arg4929,int arg4930,int arg4931,int arg4932,int arg4933,int arg4934,int arg4935,int arg4936,int arg4937,int arg4938,int arg4939,int arg4940,int arg4941,int arg4942,int arg4943,int arg4944,int arg4945,int arg4946,int arg4947,int arg4948,int arg4949,int arg4950,int arg4951,int arg4952,int arg4953,int arg4954,int arg4955,int arg4956,int arg4957,int arg4958,int arg4959,int arg4960,int arg4961,int arg4962,int arg4963,int arg4964,int arg4965,int arg4966,int arg4967,int arg4968,int arg4969,int arg4970,int arg4971,int arg4972,int arg4973,int arg4974,int arg4975,int arg4976,int arg4977,int arg4978,int arg4979,int arg4980,int arg4981,int arg4982,int arg4983,int arg4984,int arg4985,int arg4986,int arg4987,int arg4988,int arg4989,int arg4990,int arg4991,int arg4992,int arg4993,int arg4994,int arg4995,int arg4996,int arg4997,int arg4998,int arg4999) { return arg0+arg1+arg2+arg3+arg4+arg5+arg6+arg7+arg8+arg9+arg10+arg11+arg12+arg13+arg14+arg15+arg16+arg17+arg18+arg19+arg20+arg21+arg22+arg23+arg24+arg25+arg26+arg27+arg28+arg29+arg30+arg31+arg32+arg33+arg34+arg35+arg36+arg37+arg38+arg39+arg40+arg41+arg42+arg43+arg44+arg45+arg46+arg47+arg48+arg49+arg50+arg51+arg52+arg53+arg54+arg55+arg56+arg57+arg58+arg59+arg60+arg61+arg62+arg63+arg64+arg65+arg66+arg67+arg68+arg69+arg70+arg71+arg72+arg73+arg74+arg75+arg76+arg77+arg78+arg79+arg80+arg81+arg82+arg83+arg84+arg85+arg86+arg87+arg88+arg89+arg90+arg91+arg92+arg93+arg94+arg95+arg96+arg97+arg98+arg99+arg100+arg101+arg102+arg103+arg104+arg105+arg106+arg107+arg108+arg109+arg110+arg111+arg112+arg113+arg114+arg115+arg116+arg117+arg118+arg119+arg120+arg121+arg122+arg123+arg124+arg125+arg126+arg127+arg128+arg129+arg130+arg131+arg132+arg133+arg134+arg135+arg136+arg137+arg138+arg139+arg140+arg141+arg142+arg143+arg144+arg145+arg146+arg147+arg148+arg149+arg150+arg151+arg152+arg153+arg154+arg155+arg156+arg157+arg158+arg159+arg160+arg161+arg162+arg163+arg164+arg165+arg166+arg167+arg168+arg169+arg170+arg171+arg172+arg173+arg174+arg175+arg176+arg177+arg178+arg179+arg180+arg181+arg182+arg183+arg184+arg185+arg186+arg187+arg188+arg189+arg190+arg191+arg192+arg193+arg194+arg195+arg196+arg197+arg198+arg199+arg200+arg201+arg202+arg203+arg204+arg205+arg206+arg207+arg208+arg209+arg210+arg211+arg212+arg213+arg214+arg215+arg216+arg217+arg218+arg219+arg220+arg221+arg222+arg223+arg224+arg225+arg226+arg227+arg228+arg229+arg230+arg231+arg232+arg233+arg234+arg235+arg236+arg237+arg238+arg239+arg240+arg241+arg242+arg243+arg244+arg245+arg246+arg247+arg248+arg249+arg250+arg251+arg252+arg253+arg254+arg255+arg256+arg257+arg258+arg259+arg260+arg261+arg262+arg263+arg264+arg265+arg266+arg267+arg268+arg269+arg270+arg271+arg272+arg273+arg274+arg275+arg276+arg277+arg278+arg279+arg280+arg281+arg282+arg283+arg284+arg285+arg286+arg287+arg288+arg289+arg290+arg291+arg292+arg293+arg294+arg295+arg296+arg297+arg298+arg299+arg300+arg301+arg302+arg303+arg304+arg305+arg306+arg307+arg308+arg309+arg310+arg311+arg312+arg313+arg314+arg315+arg316+arg317+arg318+arg319+arg320+arg321+arg322+arg323+arg324+arg325+arg326+arg327+arg328+arg329+arg330+arg331+arg332+arg333+arg334+arg335+arg336+arg337+arg338+arg339+arg340+arg341+arg342+arg343+arg344+arg345+arg346+arg347+arg348+arg349+arg350+arg351+arg352+arg353+arg354+arg355+arg356+arg357+arg358+arg359+arg360+arg361+arg362+arg363+arg364+arg365+arg366+arg367+arg368+arg369+arg370+arg371+arg372+arg373+arg374+arg375+arg376+arg377+arg378+arg379+arg380+arg381+arg382+arg383+arg384+arg385+arg386+arg387+arg388+arg389+arg390+arg391+arg392+arg393+arg394+arg395+arg396+arg397+arg398+arg399+arg400+arg401+arg402+arg403+arg404+arg405+arg406+arg407+arg408+arg409+arg410+arg411+arg412+arg413+arg414+arg415+arg416+arg417+arg418+arg419+arg420+arg421+arg422+arg423+arg424+arg425+arg426+arg427+arg428+arg429+arg430+arg431+arg432+arg433+arg434+arg435+arg436+arg437+arg438+arg439+arg440+arg441+arg442+arg443+arg444+arg445+arg446+arg447+arg448+arg449+arg450+arg451+arg452+arg453+arg454+arg455+arg456+arg457+arg458+arg459+arg460+arg461+arg462+arg463+arg464+arg465+arg466+arg467+arg468+arg469+arg470+arg471+arg472+arg473+arg474+arg475+arg476+arg477+arg478+arg479+arg480+arg481+arg482+arg483+arg484+arg485+arg486+arg487+arg488+arg489+arg490+arg491+arg492+arg493+arg494+arg495+arg496+arg497+arg498+arg499+arg500+arg501+arg502+arg503+arg504+arg505+arg506+arg507+arg508+arg509+arg510+arg511+arg512+arg513+arg514+arg515+arg516+arg517+arg518+arg519+arg520+arg521+arg522+arg523+arg524+arg525+arg526+arg527+arg528+arg529+arg530+arg531+arg532+arg533+arg534+arg535+arg536+arg537+arg538+arg539+arg540+arg541+arg542+arg543+arg544+arg545+arg546+arg547+arg548+arg549+arg550+arg551+arg552+arg553+arg554+arg555+arg556+arg557+arg558+arg559+arg560+arg561+arg562+arg563+arg564+arg565+arg566+arg567+arg568+arg569+arg570+arg571+arg572+arg573+arg574+arg575+arg576+arg577+arg578+arg579+arg580+arg581+arg582+arg583+arg584+arg585+arg586+arg587+arg588+arg589+arg590+arg591+arg592+arg593+arg594+arg595+arg596+arg597+arg598+arg599+arg600+arg601+arg602+arg603+arg604+arg605+arg606+arg607+arg608+arg609+arg610+arg611+arg612+arg613+arg614+arg615+arg616+arg617+arg618+arg619+arg620+arg621+arg622+arg623+arg624+arg625+arg626+arg627+arg628+arg629+arg630+arg631+arg632+arg633+arg634+arg635+arg636+arg637+arg638+arg639+arg640+arg641+arg642+arg643+arg644+arg645+arg646+arg647+arg648+arg649+arg650+arg651+arg652+arg653+arg654+arg655+arg656+arg657+arg658+arg659+arg660+arg661+arg662+arg663+arg664+arg665+arg666+arg667+arg668+arg669+arg670+arg671+arg672+arg673+arg674+arg675+arg676+arg677+arg678+arg679+arg680+arg681+arg682+arg683+arg684+arg685+arg686+arg687+arg688+arg689+arg690+arg691+arg692+arg693+arg694+arg695+arg696+arg697+arg698+arg699+arg700+arg701+arg702+arg703+arg704+arg705+arg706+arg707+arg708+arg709+arg710+arg711+arg712+arg713+arg714+arg715+arg716+arg717+arg718+arg719+arg720+arg721+arg722+arg723+arg724+arg725+arg726+arg727+arg728+arg729+arg730+arg731+arg732+arg733+arg734+arg735+arg736+arg737+arg738+arg739+arg740+arg741+arg742+arg743+arg744+arg745+arg746+arg747+arg748+arg749+arg750+arg751+arg752+arg753+arg754+arg755+arg756+arg757+arg758+arg759+arg760+arg761+arg762+arg763+arg764+arg765+arg766+arg767+arg768+arg769+arg770+arg771+arg772+arg773+arg774+arg775+arg776+arg777+arg778+arg779+arg780+arg781+arg782+arg783+arg784+arg785+arg786+arg787+arg788+arg789+arg790+arg791+arg792+arg793+arg794+arg795+arg796+arg797+arg798+arg799+arg800+arg801+arg802+arg803+arg804+arg805+arg806+arg807+arg808+arg809+arg810+arg811+arg812+arg813+arg814+arg815+arg816+arg817+arg818+arg819+arg820+arg821+arg822+arg823+arg824+arg825+arg826+arg827+arg828+arg829+arg830+arg831+arg832+arg833+arg834+arg835+arg836+arg837+arg838+arg839+arg840+arg841+arg842+arg843+arg844+arg845+arg846+arg847+arg848+arg849+arg850+arg851+arg852+arg853+arg854+arg855+arg856+arg857+arg858+arg859+arg860+arg861+arg862+arg863+arg864+arg865+arg866+arg867+arg868+arg869+arg870+arg871+arg872+arg873+arg874+arg875+arg876+arg877+arg878+arg879+arg880+arg881+arg882+arg883+arg884+arg885+arg886+arg887+arg888+arg889+arg890+arg891+arg892+arg893+arg894+arg895+arg896+arg897+arg898+arg899+arg900+arg901+arg902+arg903+arg904+arg905+arg906+arg907+arg908+arg909+arg910+arg911+arg912+arg913+arg914+arg915+arg916+arg917+arg918+arg919+arg920+arg921+arg922+arg923+arg924+arg925+arg926+arg927+arg928+arg929+arg930+arg931+arg932+arg933+arg934+arg935+arg936+arg937+arg938+arg939+arg940+arg941+arg942+arg943+arg944+arg945+arg946+arg947+arg948+arg949+arg950+arg951+arg952+arg953+arg954+arg955+arg956+arg957+arg958+arg959+arg960+arg961+arg962+arg963+arg964+arg965+arg966+arg967+arg968+arg969+arg970+arg971+arg972+arg973+arg974+arg975+arg976+arg977+arg978+arg979+arg980+arg981+arg982+arg983+arg984+arg985+arg986+arg987+arg988+arg989+arg990+arg991+arg992+arg993+arg994+arg995+arg996+arg997+arg998+arg999+arg1000+arg1001+arg1002+arg1003+arg1004+arg1005+arg1006+arg1007+arg1008+arg1009+arg1010+arg1011+arg1012+arg1013+arg1014+arg1015+arg1016+arg1017+arg1018+arg1019+arg1020+arg1021+arg1022+arg1023+arg1024+arg1025+arg1026+arg1027+arg1028+arg1029+arg1030+arg1031+arg1032+arg1033+arg1034+arg1035+arg1036+arg1037+arg1038+arg1039+arg1040+arg1041+arg1042+arg1043+arg1044+arg1045+arg1046+arg1047+arg1048+arg1049+arg1050+arg1051+arg1052+arg1053+arg1054+arg1055+arg1056+arg1057+arg1058+arg1059+arg1060+arg1061+arg1062+arg1063+arg1064+arg1065+arg1066+arg1067+arg1068+arg1069+arg1070+arg1071+arg1072+arg1073+arg1074+arg1075+arg1076+arg1077+arg1078+arg1079+arg1080+arg1081+arg1082+arg1083+arg1084+arg1085+arg1086+arg1087+arg1088+arg1089+arg1090+arg1091+arg1092+arg1093+arg1094+arg1095+arg1096+arg1097+arg1098+arg1099+arg1100+arg1101+arg1102+arg1103+arg1104+arg1105+arg1106+arg1107+arg1108+arg1109+arg1110+arg1111+arg1112+arg1113+arg1114+arg1115+arg1116+arg1117+arg1118+arg1119+arg1120+arg1121+arg1122+arg1123+arg1124+arg1125+arg1126+arg1127+arg1128+arg1129+arg1130+arg1131+arg1132+arg1133+arg1134+arg1135+arg1136+arg1137+arg1138+arg1139+arg1140+arg1141+arg1142+arg1143+arg1144+arg1145+arg1146+arg1147+arg1148+arg1149+arg1150+arg1151+arg1152+arg1153+arg1154+arg1155+arg1156+arg1157+arg1158+arg1159+arg1160+arg1161+arg1162+arg1163+arg1164+arg1165+arg1166+arg1167+arg1168+arg1169+arg1170+arg1171+arg1172+arg1173+arg1174+arg1175+arg1176+arg1177+arg1178+arg1179+arg1180+arg1181+arg1182+arg1183+arg1184+arg1185+arg1186+arg1187+arg1188+arg1189+arg1190+arg1191+arg1192+arg1193+arg1194+arg1195+arg1196+arg1197+arg1198+arg1199+arg1200+arg1201+arg1202+arg1203+arg1204+arg1205+arg1206+arg1207+arg1208+arg1209+arg1210+arg1211+arg1212+arg1213+arg1214+arg1215+arg1216+arg1217+arg1218+arg1219+arg1220+arg1221+arg1222+arg1223+arg1224+arg1225+arg1226+arg1227+arg1228+arg1229+arg1230+arg1231+arg1232+arg1233+arg1234+arg1235+arg1236+arg1237+arg1238+arg1239+arg1240+arg1241+arg1242+arg1243+arg1244+arg1245+arg1246+arg1247+arg1248+arg1249+arg1250+arg1251+arg1252+arg1253+arg1254+arg1255+arg1256+arg1257+arg1258+arg1259+arg1260+arg1261+arg1262+arg1263+arg1264+arg1265+arg1266+arg1267+arg1268+arg1269+arg1270+arg1271+arg1272+arg1273+arg1274+arg1275+arg1276+arg1277+arg1278+arg1279+arg1280+arg1281+arg1282+arg1283+arg1284+arg1285+arg1286+arg1287+arg1288+arg1289+arg1290+arg1291+arg1292+arg1293+arg1294+arg1295+arg1296+arg1297+arg1298+arg1299+arg1300+arg1301+arg1302+arg1303+arg1304+arg1305+arg1306+arg1307+arg1308+arg1309+arg1310+arg1311+arg1312+arg1313+arg1314+arg1315+arg1316+arg1317+arg1318+arg1319+arg1320+arg1321+arg1322+arg1323+arg1324+arg1325+arg1326+arg1327+arg1328+arg1329+arg1330+arg1331+arg1332+arg1333+arg1334+arg1335+arg1336+arg1337+arg1338+arg1339+arg1340+arg1341+arg1342+arg1343+arg1344+arg1345+arg1346+arg1347+arg1348+arg1349+arg1350+arg1351+arg1352+arg1353+arg1354+arg1355+arg1356+arg1357+arg1358+arg1359+arg1360+arg1361+arg1362+arg1363+arg1364+arg1365+arg1366+arg1367+arg1368+arg1369+arg1370+arg1371+arg1372+arg1373+arg1374+arg1375+arg1376+arg1377+arg1378+arg1379+arg1380+arg1381+arg1382+arg1383+arg1384+arg1385+arg1386+arg1387+arg1388+arg1389+arg1390+arg1391+arg1392+arg1393+arg1394+arg1395+arg1396+arg1397+arg1398+arg1399+arg1400+arg1401+arg1402+arg1403+arg1404+arg1405+arg1406+arg1407+arg1408+arg1409+arg1410+arg1411+arg1412+arg1413+arg1414+arg1415+arg1416+arg1417+arg1418+arg1419+arg1420+arg1421+arg1422+arg1423+arg1424+arg1425+arg1426+arg1427+arg1428+arg1429+arg1430+arg1431+arg1432+arg1433+arg1434+arg1435+arg1436+arg1437+arg1438+arg1439+arg1440+arg1441+arg1442+arg1443+arg1444+arg1445+arg1446+arg1447+arg1448+arg1449+arg1450+arg1451+arg1452+arg1453+arg1454+arg1455+arg1456+arg1457+arg1458+arg1459+arg1460+arg1461+arg1462+arg1463+arg1464+arg1465+arg1466+arg1467+arg1468+arg1469+arg1470+arg1471+arg1472+arg1473+arg1474+arg1475+arg1476+arg1477+arg1478+arg1479+arg1480+arg1481+arg1482+arg1483+arg1484+arg1485+arg1486+arg1487+arg1488+arg1489+arg1490+arg1491+arg1492+arg1493+arg1494+arg1495+arg1496+arg1497+arg1498+arg1499+arg1500+arg1501+arg1502+arg1503+arg1504+arg1505+arg1506+arg1507+arg1508+arg1509+arg1510+arg1511+arg1512+arg1513+arg1514+arg1515+arg1516+arg1517+arg1518+arg1519+arg1520+arg1521+arg1522+arg1523+arg1524+arg1525+arg1526+arg1527+arg1528+arg1529+arg1530+arg1531+arg1532+arg1533+arg1534+arg1535+arg1536+arg1537+arg1538+arg1539+arg1540+arg1541+arg1542+arg1543+arg1544+arg1545+arg1546+arg1547+arg1548+arg1549+arg1550+arg1551+arg1552+arg1553+arg1554+arg1555+arg1556+arg1557+arg1558+arg1559+arg1560+arg1561+arg1562+arg1563+arg1564+arg1565+arg1566+arg1567+arg1568+arg1569+arg1570+arg1571+arg1572+arg1573+arg1574+arg1575+arg1576+arg1577+arg1578+arg1579+arg1580+arg1581+arg1582+arg1583+arg1584+arg1585+arg1586+arg1587+arg1588+arg1589+arg1590+arg1591+arg1592+arg1593+arg1594+arg1595+arg1596+arg1597+arg1598+arg1599+arg1600+arg1601+arg1602+arg1603+arg1604+arg1605+arg1606+arg1607+arg1608+arg1609+arg1610+arg1611+arg1612+arg1613+arg1614+arg1615+arg1616+arg1617+arg1618+arg1619+arg1620+arg1621+arg1622+arg1623+arg1624+arg1625+arg1626+arg1627+arg1628+arg1629+arg1630+arg1631+arg1632+arg1633+arg1634+arg1635+arg1636+arg1637+arg1638+arg1639+arg1640+arg1641+arg1642+arg1643+arg1644+arg1645+arg1646+arg1647+arg1648+arg1649+arg1650+arg1651+arg1652+arg1653+arg1654+arg1655+arg1656+arg1657+arg1658+arg1659+arg1660+arg1661+arg1662+arg1663+arg1664+arg1665+arg1666+arg1667+arg1668+arg1669+arg1670+arg1671+arg1672+arg1673+arg1674+arg1675+arg1676+arg1677+arg1678+arg1679+arg1680+arg1681+arg1682+arg1683+arg1684+arg1685+arg1686+arg1687+arg1688+arg1689+arg1690+arg1691+arg1692+arg1693+arg1694+arg1695+arg1696+arg1697+arg1698+arg1699+arg1700+arg1701+arg1702+arg1703+arg1704+arg1705+arg1706+arg1707+arg1708+arg1709+arg1710+arg1711+arg1712+arg1713+arg1714+arg1715+arg1716+arg1717+arg1718+arg1719+arg1720+arg1721+arg1722+arg1723+arg1724+arg1725+arg1726+arg1727+arg1728+arg1729+arg1730+arg1731+arg1732+arg1733+arg1734+arg1735+arg1736+arg1737+arg1738+arg1739+arg1740+arg1741+arg1742+arg1743+arg1744+arg1745+arg1746+arg1747+arg1748+arg1749+arg1750+arg1751+arg1752+arg1753+arg1754+arg1755+arg1756+arg1757+arg1758+arg1759+arg1760+arg1761+arg1762+arg1763+arg1764+arg1765+arg1766+arg1767+arg1768+arg1769+arg1770+arg1771+arg1772+arg1773+arg1774+arg1775+arg1776+arg1777+arg1778+arg1779+arg1780+arg1781+arg1782+arg1783+arg1784+arg1785+arg1786+arg1787+arg1788+arg1789+arg1790+arg1791+arg1792+arg1793+arg1794+arg1795+arg1796+arg1797+arg1798+arg1799+arg1800+arg1801+arg1802+arg1803+arg1804+arg1805+arg1806+arg1807+arg1808+arg1809+arg1810+arg1811+arg1812+arg1813+arg1814+arg1815+arg1816+arg1817+arg1818+arg1819+arg1820+arg1821+arg1822+arg1823+arg1824+arg1825+arg1826+arg1827+arg1828+arg1829+arg1830+arg1831+arg1832+arg1833+arg1834+arg1835+arg1836+arg1837+arg1838+arg1839+arg1840+arg1841+arg1842+arg1843+arg1844+arg1845+arg1846+arg1847+arg1848+arg1849+arg1850+arg1851+arg1852+arg1853+arg1854+arg1855+arg1856+arg1857+arg1858+arg1859+arg1860+arg1861+arg1862+arg1863+arg1864+arg1865+arg1866+arg1867+arg1868+arg1869+arg1870+arg1871+arg1872+arg1873+arg1874+arg1875+arg1876+arg1877+arg1878+arg1879+arg1880+arg1881+arg1882+arg1883+arg1884+arg1885+arg1886+arg1887+arg1888+arg1889+arg1890+arg1891+arg1892+arg1893+arg1894+arg1895+arg1896+arg1897+arg1898+arg1899+arg1900+arg1901+arg1902+arg1903+arg1904+arg1905+arg1906+arg1907+arg1908+arg1909+arg1910+arg1911+arg1912+arg1913+arg1914+arg1915+arg1916+arg1917+arg1918+arg1919+arg1920+arg1921+arg1922+arg1923+arg1924+arg1925+arg1926+arg1927+arg1928+arg1929+arg1930+arg1931+arg1932+arg1933+arg1934+arg1935+arg1936+arg1937+arg1938+arg1939+arg1940+arg1941+arg1942+arg1943+arg1944+arg1945+arg1946+arg1947+arg1948+arg1949+arg1950+arg1951+arg1952+arg1953+arg1954+arg1955+arg1956+arg1957+arg1958+arg1959+arg1960+arg1961+arg1962+arg1963+arg1964+arg1965+arg1966+arg1967+arg1968+arg1969+arg1970+arg1971+arg1972+arg1973+arg1974+arg1975+arg1976+arg1977+arg1978+arg1979+arg1980+arg1981+arg1982+arg1983+arg1984+arg1985+arg1986+arg1987+arg1988+arg1989+arg1990+arg1991+arg1992+arg1993+arg1994+arg1995+arg1996+arg1997+arg1998+arg1999+arg2000+arg2001+arg2002+arg2003+arg2004+arg2005+arg2006+arg2007+arg2008+arg2009+arg2010+arg2011+arg2012+arg2013+arg2014+arg2015+arg2016+arg2017+arg2018+arg2019+arg2020+arg2021+arg2022+arg2023+arg2024+arg2025+arg2026+arg2027+arg2028+arg2029+arg2030+arg2031+arg2032+arg2033+arg2034+arg2035+arg2036+arg2037+arg2038+arg2039+arg2040+arg2041+arg2042+arg2043+arg2044+arg2045+arg2046+arg2047+arg2048+arg2049+arg2050+arg2051+arg2052+arg2053+arg2054+arg2055+arg2056+arg2057+arg2058+arg2059+arg2060+arg2061+arg2062+arg2063+arg2064+arg2065+arg2066+arg2067+arg2068+arg2069+arg2070+arg2071+arg2072+arg2073+arg2074+arg2075+arg2076+arg2077+arg2078+arg2079+arg2080+arg2081+arg2082+arg2083+arg2084+arg2085+arg2086+arg2087+arg2088+arg2089+arg2090+arg2091+arg2092+arg2093+arg2094+arg2095+arg2096+arg2097+arg2098+arg2099+arg2100+arg2101+arg2102+arg2103+arg2104+arg2105+arg2106+arg2107+arg2108+arg2109+arg2110+arg2111+arg2112+arg2113+arg2114+arg2115+arg2116+arg2117+arg2118+arg2119+arg2120+arg2121+arg2122+arg2123+arg2124+arg2125+arg2126+arg2127+arg2128+arg2129+arg2130+arg2131+arg2132+arg2133+arg2134+arg2135+arg2136+arg2137+arg2138+arg2139+arg2140+arg2141+arg2142+arg2143+arg2144+arg2145+arg2146+arg2147+arg2148+arg2149+arg2150+arg2151+arg2152+arg2153+arg2154+arg2155+arg2156+arg2157+arg2158+arg2159+arg2160+arg2161+arg2162+arg2163+arg2164+arg2165+arg2166+arg2167+arg2168+arg2169+arg2170+arg2171+arg2172+arg2173+arg2174+arg2175+arg2176+arg2177+arg2178+arg2179+arg2180+arg2181+arg2182+arg2183+arg2184+arg2185+arg2186+arg2187+arg2188+arg2189+arg2190+arg2191+arg2192+arg2193+arg2194+arg2195+arg2196+arg2197+arg2198+arg2199+arg2200+arg2201+arg2202+arg2203+arg2204+arg2205+arg2206+arg2207+arg2208+arg2209+arg2210+arg2211+arg2212+arg2213+arg2214+arg2215+arg2216+arg2217+arg2218+arg2219+arg2220+arg2221+arg2222+arg2223+arg2224+arg2225+arg2226+arg2227+arg2228+arg2229+arg2230+arg2231+arg2232+arg2233+arg2234+arg2235+arg2236+arg2237+arg2238+arg2239+arg2240+arg2241+arg2242+arg2243+arg2244+arg2245+arg2246+arg2247+arg2248+arg2249+arg2250+arg2251+arg2252+arg2253+arg2254+arg2255+arg2256+arg2257+arg2258+arg2259+arg2260+arg2261+arg2262+arg2263+arg2264+arg2265+arg2266+arg2267+arg2268+arg2269+arg2270+arg2271+arg2272+arg2273+arg2274+arg2275+arg2276+arg2277+arg2278+arg2279+arg2280+arg2281+arg2282+arg2283+arg2284+arg2285+arg2286+arg2287+arg2288+arg2289+arg2290+arg2291+arg2292+arg2293+arg2294+arg2295+arg2296+arg2297+arg2298+arg2299+arg2300+arg2301+arg2302+arg2303+arg2304+arg2305+arg2306+arg2307+arg2308+arg2309+arg2310+arg2311+arg2312+arg2313+arg2314+arg2315+arg2316+arg2317+arg2318+arg2319+arg2320+arg2321+arg2322+arg2323+arg2324+arg2325+arg2326+arg2327+arg2328+arg2329+arg2330+arg2331+arg2332+arg2333+arg2334+arg2335+arg2336+arg2337+arg2338+arg2339+arg2340+arg2341+arg2342+arg2343+arg2344+arg2345+arg2346+arg2347+arg2348+arg2349+arg2350+arg2351+arg2352+arg2353+arg2354+arg2355+arg2356+arg2357+arg2358+arg2359+arg2360+arg2361+arg2362+arg2363+arg2364+arg2365+arg2366+arg2367+arg2368+arg2369+arg2370+arg2371+arg2372+arg2373+arg2374+arg2375+arg2376+arg2377+arg2378+arg2379+arg2380+arg2381+arg2382+arg2383+arg2384+arg2385+arg2386+arg2387+arg2388+arg2389+arg2390+arg2391+arg2392+arg2393+arg2394+arg2395+arg2396+arg2397+arg2398+arg2399+arg2400+arg2401+arg2402+arg2403+arg2404+arg2405+arg2406+arg2407+arg2408+arg2409+arg2410+arg2411+arg2412+arg2413+arg2414+arg2415+arg2416+arg2417+arg2418+arg2419+arg2420+arg2421+arg2422+arg2423+arg2424+arg2425+arg2426+arg2427+arg2428+arg2429+arg2430+arg2431+arg2432+arg2433+arg2434+arg2435+arg2436+arg2437+arg2438+arg2439+arg2440+arg2441+arg2442+arg2443+arg2444+arg2445+arg2446+arg2447+arg2448+arg2449+arg2450+arg2451+arg2452+arg2453+arg2454+arg2455+arg2456+arg2457+arg2458+arg2459+arg2460+arg2461+arg2462+arg2463+arg2464+arg2465+arg2466+arg2467+arg2468+arg2469+arg2470+arg2471+arg2472+arg2473+arg2474+arg2475+arg2476+arg2477+arg2478+arg2479+arg2480+arg2481+arg2482+arg2483+arg2484+arg2485+arg2486+arg2487+arg2488+arg2489+arg2490+arg2491+arg2492+arg2493+arg2494+arg2495+arg2496+arg2497+arg2498+arg2499+arg2500+arg2501+arg2502+arg2503+arg2504+arg2505+arg2506+arg2507+arg2508+arg2509+arg2510+arg2511+arg2512+arg2513+arg2514+arg2515+arg2516+arg2517+arg2518+arg2519+arg2520+arg2521+arg2522+arg2523+arg2524+arg2525+arg2526+arg2527+arg2528+arg2529+arg2530+arg2531+arg2532+arg2533+arg2534+arg2535+arg2536+arg2537+arg2538+arg2539+arg2540+arg2541+arg2542+arg2543+arg2544+arg2545+arg2546+arg2547+arg2548+arg2549+arg2550+arg2551+arg2552+arg2553+arg2554+arg2555+arg2556+arg2557+arg2558+arg2559+arg2560+arg2561+arg2562+arg2563+arg2564+arg2565+arg2566+arg2567+arg2568+arg2569+arg2570+arg2571+arg2572+arg2573+arg2574+arg2575+arg2576+arg2577+arg2578+arg2579+arg2580+arg2581+arg2582+arg2583+arg2584+arg2585+arg2586+arg2587+arg2588+arg2589+arg2590+arg2591+arg2592+arg2593+arg2594+arg2595+arg2596+arg2597+arg2598+arg2599+arg2600+arg2601+arg2602+arg2603+arg2604+arg2605+arg2606+arg2607+arg2608+arg2609+arg2610+arg2611+arg2612+arg2613+arg2614+arg2615+arg2616+arg2617+arg2618+arg2619+arg2620+arg2621+arg2622+arg2623+arg2624+arg2625+arg2626+arg2627+arg2628+arg2629+arg2630+arg2631+arg2632+arg2633+arg2634+arg2635+arg2636+arg2637+arg2638+arg2639+arg2640+arg2641+arg2642+arg2643+arg2644+arg2645+arg2646+arg2647+arg2648+arg2649+arg2650+arg2651+arg2652+arg2653+arg2654+arg2655+arg2656+arg2657+arg2658+arg2659+arg2660+arg2661+arg2662+arg2663+arg2664+arg2665+arg2666+arg2667+arg2668+arg2669+arg2670+arg2671+arg2672+arg2673+arg2674+arg2675+arg2676+arg2677+arg2678+arg2679+arg2680+arg2681+arg2682+arg2683+arg2684+arg2685+arg2686+arg2687+arg2688+arg2689+arg2690+arg2691+arg2692+arg2693+arg2694+arg2695+arg2696+arg2697+arg2698+arg2699+arg2700+arg2701+arg2702+arg2703+arg2704+arg2705+arg2706+arg2707+arg2708+arg2709+arg2710+arg2711+arg2712+arg2713+arg2714+arg2715+arg2716+arg2717+arg2718+arg2719+arg2720+arg2721+arg2722+arg2723+arg2724+arg2725+arg2726+arg2727+arg2728+arg2729+arg2730+arg2731+arg2732+arg2733+arg2734+arg2735+arg2736+arg2737+arg2738+arg2739+arg2740+arg2741+arg2742+arg2743+arg2744+arg2745+arg2746+arg2747+arg2748+arg2749+arg2750+arg2751+arg2752+arg2753+arg2754+arg2755+arg2756+arg2757+arg2758+arg2759+arg2760+arg2761+arg2762+arg2763+arg2764+arg2765+arg2766+arg2767+arg2768+arg2769+arg2770+arg2771+arg2772+arg2773+arg2774+arg2775+arg2776+arg2777+arg2778+arg2779+arg2780+arg2781+arg2782+arg2783+arg2784+arg2785+arg2786+arg2787+arg2788+arg2789+arg2790+arg2791+arg2792+arg2793+arg2794+arg2795+arg2796+arg2797+arg2798+arg2799+arg2800+arg2801+arg2802+arg2803+arg2804+arg2805+arg2806+arg2807+arg2808+arg2809+arg2810+arg2811+arg2812+arg2813+arg2814+arg2815+arg2816+arg2817+arg2818+arg2819+arg2820+arg2821+arg2822+arg2823+arg2824+arg2825+arg2826+arg2827+arg2828+arg2829+arg2830+arg2831+arg2832+arg2833+arg2834+arg2835+arg2836+arg2837+arg2838+arg2839+arg2840+arg2841+arg2842+arg2843+arg2844+arg2845+arg2846+arg2847+arg2848+arg2849+arg2850+arg2851+arg2852+arg2853+arg2854+arg2855+arg2856+arg2857+arg2858+arg2859+arg2860+arg2861+arg2862+arg2863+arg2864+arg2865+arg2866+arg2867+arg2868+arg2869+arg2870+arg2871+arg2872+arg2873+arg2874+arg2875+arg2876+arg2877+arg2878+arg2879+arg2880+arg2881+arg2882+arg2883+arg2884+arg2885+arg2886+arg2887+arg2888+arg2889+arg2890+arg2891+arg2892+arg2893+arg2894+arg2895+arg2896+arg2897+arg2898+arg2899+arg2900+arg2901+arg2902+arg2903+arg2904+arg2905+arg2906+arg2907+arg2908+arg2909+arg2910+arg2911+arg2912+arg2913+arg2914+arg2915+arg2916+arg2917+arg2918+arg2919+arg2920+arg2921+arg2922+arg2923+arg2924+arg2925+arg2926+arg2927+arg2928+arg2929+arg2930+arg2931+arg2932+arg2933+arg2934+arg2935+arg2936+arg2937+arg2938+arg2939+arg2940+arg2941+arg2942+arg2943+arg2944+arg2945+arg2946+arg2947+arg2948+arg2949+arg2950+arg2951+arg2952+arg2953+arg2954+arg2955+arg2956+arg2957+arg2958+arg2959+arg2960+arg2961+arg2962+arg2963+arg2964+arg2965+arg2966+arg2967+arg2968+arg2969+arg2970+arg2971+arg2972+arg2973+arg2974+arg2975+arg2976+arg2977+arg2978+arg2979+arg2980+arg2981+arg2982+arg2983+arg2984+arg2985+arg2986+arg2987+arg2988+arg2989+arg2990+arg2991+arg2992+arg2993+arg2994+arg2995+arg2996+arg2997+arg2998+arg2999+arg3000+arg3001+arg3002+arg3003+arg3004+arg3005+arg3006+arg3007+arg3008+arg3009+arg3010+arg3011+arg3012+arg3013+arg3014+arg3015+arg3016+arg3017+arg3018+arg3019+arg3020+arg3021+arg3022+arg3023+arg3024+arg3025+arg3026+arg3027+arg3028+arg3029+arg3030+arg3031+arg3032+arg3033+arg3034+arg3035+arg3036+arg3037+arg3038+arg3039+arg3040+arg3041+arg3042+arg3043+arg3044+arg3045+arg3046+arg3047+arg3048+arg3049+arg3050+arg3051+arg3052+arg3053+arg3054+arg3055+arg3056+arg3057+arg3058+arg3059+arg3060+arg3061+arg3062+arg3063+arg3064+arg3065+arg3066+arg3067+arg3068+arg3069+arg3070+arg3071+arg3072+arg3073+arg3074+arg3075+arg3076+arg3077+arg3078+arg3079+arg3080+arg3081+arg3082+arg3083+arg3084+arg3085+arg3086+arg3087+arg3088+arg3089+arg3090+arg3091+arg3092+arg3093+arg3094+arg3095+arg3096+arg3097+arg3098+arg3099+arg3100+arg3101+arg3102+arg3103+arg3104+arg3105+arg3106+arg3107+arg3108+arg3109+arg3110+arg3111+arg3112+arg3113+arg3114+arg3115+arg3116+arg3117+arg3118+arg3119+arg3120+arg3121+arg3122+arg3123+arg3124+arg3125+arg3126+arg3127+arg3128+arg3129+arg3130+arg3131+arg3132+arg3133+arg3134+arg3135+arg3136+arg3137+arg3138+arg3139+arg3140+arg3141+arg3142+arg3143+arg3144+arg3145+arg3146+arg3147+arg3148+arg3149+arg3150+arg3151+arg3152+arg3153+arg3154+arg3155+arg3156+arg3157+arg3158+arg3159+arg3160+arg3161+arg3162+arg3163+arg3164+arg3165+arg3166+arg3167+arg3168+arg3169+arg3170+arg3171+arg3172+arg3173+arg3174+arg3175+arg3176+arg3177+arg3178+arg3179+arg3180+arg3181+arg3182+arg3183+arg3184+arg3185+arg3186+arg3187+arg3188+arg3189+arg3190+arg3191+arg3192+arg3193+arg3194+arg3195+arg3196+arg3197+arg3198+arg3199+arg3200+arg3201+arg3202+arg3203+arg3204+arg3205+arg3206+arg3207+arg3208+arg3209+arg3210+arg3211+arg3212+arg3213+arg3214+arg3215+arg3216+arg3217+arg3218+arg3219+arg3220+arg3221+arg3222+arg3223+arg3224+arg3225+arg3226+arg3227+arg3228+arg3229+arg3230+arg3231+arg3232+arg3233+arg3234+arg3235+arg3236+arg3237+arg3238+arg3239+arg3240+arg3241+arg3242+arg3243+arg3244+arg3245+arg3246+arg3247+arg3248+arg3249+arg3250+arg3251+arg3252+arg3253+arg3254+arg3255+arg3256+arg3257+arg3258+arg3259+arg3260+arg3261+arg3262+arg3263+arg3264+arg3265+arg3266+arg3267+arg3268+arg3269+arg3270+arg3271+arg3272+arg3273+arg3274+arg3275+arg3276+arg3277+arg3278+arg3279+arg3280+arg3281+arg3282+arg3283+arg3284+arg3285+arg3286+arg3287+arg3288+arg3289+arg3290+arg3291+arg3292+arg3293+arg3294+arg3295+arg3296+arg3297+arg3298+arg3299+arg3300+arg3301+arg3302+arg3303+arg3304+arg3305+arg3306+arg3307+arg3308+arg3309+arg3310+arg3311+arg3312+arg3313+arg3314+arg3315+arg3316+arg3317+arg3318+arg3319+arg3320+arg3321+arg3322+arg3323+arg3324+arg3325+arg3326+arg3327+arg3328+arg3329+arg3330+arg3331+arg3332+arg3333+arg3334+arg3335+arg3336+arg3337+arg3338+arg3339+arg3340+arg3341+arg3342+arg3343+arg3344+arg3345+arg3346+arg3347+arg3348+arg3349+arg3350+arg3351+arg3352+arg3353+arg3354+arg3355+arg3356+arg3357+arg3358+arg3359+arg3360+arg3361+arg3362+arg3363+arg3364+arg3365+arg3366+arg3367+arg3368+arg3369+arg3370+arg3371+arg3372+arg3373+arg3374+arg3375+arg3376+arg3377+arg3378+arg3379+arg3380+arg3381+arg3382+arg3383+arg3384+arg3385+arg3386+arg3387+arg3388+arg3389+arg3390+arg3391+arg3392+arg3393+arg3394+arg3395+arg3396+arg3397+arg3398+arg3399+arg3400+arg3401+arg3402+arg3403+arg3404+arg3405+arg3406+arg3407+arg3408+arg3409+arg3410+arg3411+arg3412+arg3413+arg3414+arg3415+arg3416+arg3417+arg3418+arg3419+arg3420+arg3421+arg3422+arg3423+arg3424+arg3425+arg3426+arg3427+arg3428+arg3429+arg3430+arg3431+arg3432+arg3433+arg3434+arg3435+arg3436+arg3437+arg3438+arg3439+arg3440+arg3441+arg3442+arg3443+arg3444+arg3445+arg3446+arg3447+arg3448+arg3449+arg3450+arg3451+arg3452+arg3453+arg3454+arg3455+arg3456+arg3457+arg3458+arg3459+arg3460+arg3461+arg3462+arg3463+arg3464+arg3465+arg3466+arg3467+arg3468+arg3469+arg3470+arg3471+arg3472+arg3473+arg3474+arg3475+arg3476+arg3477+arg3478+arg3479+arg3480+arg3481+arg3482+arg3483+arg3484+arg3485+arg3486+arg3487+arg3488+arg3489+arg3490+arg3491+arg3492+arg3493+arg3494+arg3495+arg3496+arg3497+arg3498+arg3499+arg3500+arg3501+arg3502+arg3503+arg3504+arg3505+arg3506+arg3507+arg3508+arg3509+arg3510+arg3511+arg3512+arg3513+arg3514+arg3515+arg3516+arg3517+arg3518+arg3519+arg3520+arg3521+arg3522+arg3523+arg3524+arg3525+arg3526+arg3527+arg3528+arg3529+arg3530+arg3531+arg3532+arg3533+arg3534+arg3535+arg3536+arg3537+arg3538+arg3539+arg3540+arg3541+arg3542+arg3543+arg3544+arg3545+arg3546+arg3547+arg3548+arg3549+arg3550+arg3551+arg3552+arg3553+arg3554+arg3555+arg3556+arg3557+arg3558+arg3559+arg3560+arg3561+arg3562+arg3563+arg3564+arg3565+arg3566+arg3567+arg3568+arg3569+arg3570+arg3571+arg3572+arg3573+arg3574+arg3575+arg3576+arg3577+arg3578+arg3579+arg3580+arg3581+arg3582+arg3583+arg3584+arg3585+arg3586+arg3587+arg3588+arg3589+arg3590+arg3591+arg3592+arg3593+arg3594+arg3595+arg3596+arg3597+arg3598+arg3599+arg3600+arg3601+arg3602+arg3603+arg3604+arg3605+arg3606+arg3607+arg3608+arg3609+arg3610+arg3611+arg3612+arg3613+arg3614+arg3615+arg3616+arg3617+arg3618+arg3619+arg3620+arg3621+arg3622+arg3623+arg3624+arg3625+arg3626+arg3627+arg3628+arg3629+arg3630+arg3631+arg3632+arg3633+arg3634+arg3635+arg3636+arg3637+arg3638+arg3639+arg3640+arg3641+arg3642+arg3643+arg3644+arg3645+arg3646+arg3647+arg3648+arg3649+arg3650+arg3651+arg3652+arg3653+arg3654+arg3655+arg3656+arg3657+arg3658+arg3659+arg3660+arg3661+arg3662+arg3663+arg3664+arg3665+arg3666+arg3667+arg3668+arg3669+arg3670+arg3671+arg3672+arg3673+arg3674+arg3675+arg3676+arg3677+arg3678+arg3679+arg3680+arg3681+arg3682+arg3683+arg3684+arg3685+arg3686+arg3687+arg3688+arg3689+arg3690+arg3691+arg3692+arg3693+arg3694+arg3695+arg3696+arg3697+arg3698+arg3699+arg3700+arg3701+arg3702+arg3703+arg3704+arg3705+arg3706+arg3707+arg3708+arg3709+arg3710+arg3711+arg3712+arg3713+arg3714+arg3715+arg3716+arg3717+arg3718+arg3719+arg3720+arg3721+arg3722+arg3723+arg3724+arg3725+arg3726+arg3727+arg3728+arg3729+arg3730+arg3731+arg3732+arg3733+arg3734+arg3735+arg3736+arg3737+arg3738+arg3739+arg3740+arg3741+arg3742+arg3743+arg3744+arg3745+arg3746+arg3747+arg3748+arg3749+arg3750+arg3751+arg3752+arg3753+arg3754+arg3755+arg3756+arg3757+arg3758+arg3759+arg3760+arg3761+arg3762+arg3763+arg3764+arg3765+arg3766+arg3767+arg3768+arg3769+arg3770+arg3771+arg3772+arg3773+arg3774+arg3775+arg3776+arg3777+arg3778+arg3779+arg3780+arg3781+arg3782+arg3783+arg3784+arg3785+arg3786+arg3787+arg3788+arg3789+arg3790+arg3791+arg3792+arg3793+arg3794+arg3795+arg3796+arg3797+arg3798+arg3799+arg3800+arg3801+arg3802+arg3803+arg3804+arg3805+arg3806+arg3807+arg3808+arg3809+arg3810+arg3811+arg3812+arg3813+arg3814+arg3815+arg3816+arg3817+arg3818+arg3819+arg3820+arg3821+arg3822+arg3823+arg3824+arg3825+arg3826+arg3827+arg3828+arg3829+arg3830+arg3831+arg3832+arg3833+arg3834+arg3835+arg3836+arg3837+arg3838+arg3839+arg3840+arg3841+arg3842+arg3843+arg3844+arg3845+arg3846+arg3847+arg3848+arg3849+arg3850+arg3851+arg3852+arg3853+arg3854+arg3855+arg3856+arg3857+arg3858+arg3859+arg3860+arg3861+arg3862+arg3863+arg3864+arg3865+arg3866+arg3867+arg3868+arg3869+arg3870+arg3871+arg3872+arg3873+arg3874+arg3875+arg3876+arg3877+arg3878+arg3879+arg3880+arg3881+arg3882+arg3883+arg3884+arg3885+arg3886+arg3887+arg3888+arg3889+arg3890+arg3891+arg3892+arg3893+arg3894+arg3895+arg3896+arg3897+arg3898+arg3899+arg3900+arg3901+arg3902+arg3903+arg3904+arg3905+arg3906+arg3907+arg3908+arg3909+arg3910+arg3911+arg3912+arg3913+arg3914+arg3915+arg3916+arg3917+arg3918+arg3919+arg3920+arg3921+arg3922+arg3923+arg3924+arg3925+arg3926+arg3927+arg3928+arg3929+arg3930+arg3931+arg3932+arg3933+arg3934+arg3935+arg3936+arg3937+arg3938+arg3939+arg3940+arg3941+arg3942+arg3943+arg3944+arg3945+arg3946+arg3947+arg3948+arg3949+arg3950+arg3951+arg3952+arg3953+arg3954+arg3955+arg3956+arg3957+arg3958+arg3959+arg3960+arg3961+arg3962+arg3963+arg3964+arg3965+arg3966+arg3967+arg3968+arg3969+arg3970+arg3971+arg3972+arg3973+arg3974+arg3975+arg3976+arg3977+arg3978+arg3979+arg3980+arg3981+arg3982+arg3983+arg3984+arg3985+arg3986+arg3987+arg3988+arg3989+arg3990+arg3991+arg3992+arg3993+arg3994+arg3995+arg3996+arg3997+arg3998+arg3999+arg4000+arg4001+arg4002+arg4003+arg4004+arg4005+arg4006+arg4007+arg4008+arg4009+arg4010+arg4011+arg4012+arg4013+arg4014+arg4015+arg4016+arg4017+arg4018+arg4019+arg4020+arg4021+arg4022+arg4023+arg4024+arg4025+arg4026+arg4027+arg4028+arg4029+arg4030+arg4031+arg4032+arg4033+arg4034+arg4035+arg4036+arg4037+arg4038+arg4039+arg4040+arg4041+arg4042+arg4043+arg4044+arg4045+arg4046+arg4047+arg4048+arg4049+arg4050+arg4051+arg4052+arg4053+arg4054+arg4055+arg4056+arg4057+arg4058+arg4059+arg4060+arg4061+arg4062+arg4063+arg4064+arg4065+arg4066+arg4067+arg4068+arg4069+arg4070+arg4071+arg4072+arg4073+arg4074+arg4075+arg4076+arg4077+arg4078+arg4079+arg4080+arg4081+arg4082+arg4083+arg4084+arg4085+arg4086+arg4087+arg4088+arg4089+arg4090+arg4091+arg4092+arg4093+arg4094+arg4095+arg4096+arg4097+arg4098+arg4099+arg4100+arg4101+arg4102+arg4103+arg4104+arg4105+arg4106+arg4107+arg4108+arg4109+arg4110+arg4111+arg4112+arg4113+arg4114+arg4115+arg4116+arg4117+arg4118+arg4119+arg4120+arg4121+arg4122+arg4123+arg4124+arg4125+arg4126+arg4127+arg4128+arg4129+arg4130+arg4131+arg4132+arg4133+arg4134+arg4135+arg4136+arg4137+arg4138+arg4139+arg4140+arg4141+arg4142+arg4143+arg4144+arg4145+arg4146+arg4147+arg4148+arg4149+arg4150+arg4151+arg4152+arg4153+arg4154+arg4155+arg4156+arg4157+arg4158+arg4159+arg4160+arg4161+arg4162+arg4163+arg4164+arg4165+arg4166+arg4167+arg4168+arg4169+arg4170+arg4171+arg4172+arg4173+arg4174+arg4175+arg4176+arg4177+arg4178+arg4179+arg4180+arg4181+arg4182+arg4183+arg4184+arg4185+arg4186+arg4187+arg4188+arg4189+arg4190+arg4191+arg4192+arg4193+arg4194+arg4195+arg4196+arg4197+arg4198+arg4199+arg4200+arg4201+arg4202+arg4203+arg4204+arg4205+arg4206+arg4207+arg4208+arg4209+arg4210+arg4211+arg4212+arg4213+arg4214+arg4215+arg4216+arg4217+arg4218+arg4219+arg4220+arg4221+arg4222+arg4223+arg4224+arg4225+arg4226+arg4227+arg4228+arg4229+arg4230+arg4231+arg4232+arg4233+arg4234+arg4235+arg4236+arg4237+arg4238+arg4239+arg4240+arg4241+arg4242+arg4243+arg4244+arg4245+arg4246+arg4247+arg4248+arg4249+arg4250+arg4251+arg4252+arg4253+arg4254+arg4255+arg4256+arg4257+arg4258+arg4259+arg4260+arg4261+arg4262+arg4263+arg4264+arg4265+arg4266+arg4267+arg4268+arg4269+arg4270+arg4271+arg4272+arg4273+arg4274+arg4275+arg4276+arg4277+arg4278+arg4279+arg4280+arg4281+arg4282+arg4283+arg4284+arg4285+arg4286+arg4287+arg4288+arg4289+arg4290+arg4291+arg4292+arg4293+arg4294+arg4295+arg4296+arg4297+arg4298+arg4299+arg4300+arg4301+arg4302+arg4303+arg4304+arg4305+arg4306+arg4307+arg4308+arg4309+arg4310+arg4311+arg4312+arg4313+arg4314+arg4315+arg4316+arg4317+arg4318+arg4319+arg4320+arg4321+arg4322+arg4323+arg4324+arg4325+arg4326+arg4327+arg4328+arg4329+arg4330+arg4331+arg4332+arg4333+arg4334+arg4335+arg4336+arg4337+arg4338+arg4339+arg4340+arg4341+arg4342+arg4343+arg4344+arg4345+arg4346+arg4347+arg4348+arg4349+arg4350+arg4351+arg4352+arg4353+arg4354+arg4355+arg4356+arg4357+arg4358+arg4359+arg4360+arg4361+arg4362+arg4363+arg4364+arg4365+arg4366+arg4367+arg4368+arg4369+arg4370+arg4371+arg4372+arg4373+arg4374+arg4375+arg4376+arg4377+arg4378+arg4379+arg4380+arg4381+arg4382+arg4383+arg4384+arg4385+arg4386+arg4387+arg4388+arg4389+arg4390+arg4391+arg4392+arg4393+arg4394+arg4395+arg4396+arg4397+arg4398+arg4399+arg4400+arg4401+arg4402+arg4403+arg4404+arg4405+arg4406+arg4407+arg4408+arg4409+arg4410+arg4411+arg4412+arg4413+arg4414+arg4415+arg4416+arg4417+arg4418+arg4419+arg4420+arg4421+arg4422+arg4423+arg4424+arg4425+arg4426+arg4427+arg4428+arg4429+arg4430+arg4431+arg4432+arg4433+arg4434+arg4435+arg4436+arg4437+arg4438+arg4439+arg4440+arg4441+arg4442+arg4443+arg4444+arg4445+arg4446+arg4447+arg4448+arg4449+arg4450+arg4451+arg4452+arg4453+arg4454+arg4455+arg4456+arg4457+arg4458+arg4459+arg4460+arg4461+arg4462+arg4463+arg4464+arg4465+arg4466+arg4467+arg4468+arg4469+arg4470+arg4471+arg4472+arg4473+arg4474+arg4475+arg4476+arg4477+arg4478+arg4479+arg4480+arg4481+arg4482+arg4483+arg4484+arg4485+arg4486+arg4487+arg4488+arg4489+arg4490+arg4491+arg4492+arg4493+arg4494+arg4495+arg4496+arg4497+arg4498+arg4499+arg4500+arg4501+arg4502+arg4503+arg4504+arg4505+arg4506+arg4507+arg4508+arg4509+arg4510+arg4511+arg4512+arg4513+arg4514+arg4515+arg4516+arg4517+arg4518+arg4519+arg4520+arg4521+arg4522+arg4523+arg4524+arg4525+arg4526+arg4527+arg4528+arg4529+arg4530+arg4531+arg4532+arg4533+arg4534+arg4535+arg4536+arg4537+arg4538+arg4539+arg4540+arg4541+arg4542+arg4543+arg4544+arg4545+arg4546+arg4547+arg4548+arg4549+arg4550+arg4551+arg4552+arg4553+arg4554+arg4555+arg4556+arg4557+arg4558+arg4559+arg4560+arg4561+arg4562+arg4563+arg4564+arg4565+arg4566+arg4567+arg4568+arg4569+arg4570+arg4571+arg4572+arg4573+arg4574+arg4575+arg4576+arg4577+arg4578+arg4579+arg4580+arg4581+arg4582+arg4583+arg4584+arg4585+arg4586+arg4587+arg4588+arg4589+arg4590+arg4591+arg4592+arg4593+arg4594+arg4595+arg4596+arg4597+arg4598+arg4599+arg4600+arg4601+arg4602+arg4603+arg4604+arg4605+arg4606+arg4607+arg4608+arg4609+arg4610+arg4611+arg4612+arg4613+arg4614+arg4615+arg4616+arg4617+arg4618+arg4619+arg4620+arg4621+arg4622+arg4623+arg4624+arg4625+arg4626+arg4627+arg4628+arg4629+arg4630+arg4631+arg4632+arg4633+arg4634+arg4635+arg4636+arg4637+arg4638+arg4639+arg4640+arg4641+arg4642+arg4643+arg4644+arg4645+arg4646+arg4647+arg4648+arg4649+arg4650+arg4651+arg4652+arg4653+arg4654+arg4655+arg4656+arg4657+arg4658+arg4659+arg4660+arg4661+arg4662+arg4663+arg4664+arg4665+arg4666+arg4667+arg4668+arg4669+arg4670+arg4671+arg4672+arg4673+arg4674+arg4675+arg4676+arg4677+arg4678+arg4679+arg4680+arg4681+arg4682+arg4683+arg4684+arg4685+arg4686+arg4687+arg4688+arg4689+arg4690+arg4691+arg4692+arg4693+arg4694+arg4695+arg4696+arg4697+arg4698+arg4699+arg4700+arg4701+arg4702+arg4703+arg4704+arg4705+arg4706+arg4707+arg4708+arg4709+arg4710+arg4711+arg4712+arg4713+arg4714+arg4715+arg4716+arg4717+arg4718+arg4719+arg4720+arg4721+arg4722+arg4723+arg4724+arg4725+arg4726+arg4727+arg4728+arg4729+arg4730+arg4731+arg4732+arg4733+arg4734+arg4735+arg4736+arg4737+arg4738+arg4739+arg4740+arg4741+arg4742+arg4743+arg4744+arg4745+arg4746+arg4747+arg4748+arg4749+arg4750+arg4751+arg4752+arg4753+arg4754+arg4755+arg4756+arg4757+arg4758+arg4759+arg4760+arg4761+arg4762+arg4763+arg4764+arg4765+arg4766+arg4767+arg4768+arg4769+arg4770+arg4771+arg4772+arg4773+arg4774+arg4775+arg4776+arg4777+arg4778+arg4779+arg4780+arg4781+arg4782+arg4783+arg4784+arg4785+arg4786+arg4787+arg4788+arg4789+arg4790+arg4791+arg4792+arg4793+arg4794+arg4795+arg4796+arg4797+arg4798+arg4799+arg4800+arg4801+arg4802+arg4803+arg4804+arg4805+arg4806+arg4807+arg4808+arg4809+arg4810+arg4811+arg4812+arg4813+arg4814+arg4815+arg4816+arg4817+arg4818+arg4819+arg4820+arg4821+arg4822+arg4823+arg4824+arg4825+arg4826+arg4827+arg4828+arg4829+arg4830+arg4831+arg4832+arg4833+arg4834+arg4835+arg4836+arg4837+arg4838+arg4839+arg4840+arg4841+arg4842+arg4843+arg4844+arg4845+arg4846+arg4847+arg4848+arg4849+arg4850+arg4851+arg4852+arg4853+arg4854+arg4855+arg4856+arg4857+arg4858+arg4859+arg4860+arg4861+arg4862+arg4863+arg4864+arg4865+arg4866+arg4867+arg4868+arg4869+arg4870+arg4871+arg4872+arg4873+arg4874+arg4875+arg4876+arg4877+arg4878+arg4879+arg4880+arg4881+arg4882+arg4883+arg4884+arg4885+arg4886+arg4887+arg4888+arg4889+arg4890+arg4891+arg4892+arg4893+arg4894+arg4895+arg4896+arg4897+arg4898+arg4899+arg4900+arg4901+arg4902+arg4903+arg4904+arg4905+arg4906+arg4907+arg4908+arg4909+arg4910+arg4911+arg4912+arg4913+arg4914+arg4915+arg4916+arg4917+arg4918+arg4919+arg4920+arg4921+arg4922+arg4923+arg4924+arg4925+arg4926+arg4927+arg4928+arg4929+arg4930+arg4931+arg4932+arg4933+arg4934+arg4935+arg4936+arg4937+arg4938+arg4939+arg4940+arg4941+arg4942+arg4943+arg4944+arg4945+arg4946+arg4947+arg4948+arg4949+arg4950+arg4951+arg4952+arg4953+arg4954+arg4955+arg4956+arg4957+arg4958+arg4959+arg4960+arg4961+arg4962+arg4963+arg4964+arg4965+arg4966+arg4967+arg4968+arg4969+arg4970+arg4971+arg4972+arg4973+arg4974+arg4975+arg4976+arg4977+arg4978+arg4979+arg4980+arg4981+arg4982+arg4983+arg4984+arg4985+arg4986+arg4987+arg4988+arg4989+arg4990+arg4991+arg4992+arg4993+arg4994+arg4995+arg4996+arg4997+arg4998+arg4999;}
11000void testCallFunctionWithHellaArguments3()
11001{
11002 Procedure proc;
11003 BasicBlock* root = proc.addBlock();
11004
11005 Vector<Value*> args;
11006 for (unsigned i = 0; i < 5000; ++i)
11007 args.append(root->appendNew<Const32Value>(proc, Origin(), 4095 - 5000 + i - 1));
11008
11009 CCallValue* call = root->appendNew<CCallValue>(
11010 proc, Int32, Origin(),
11011 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaArguments3, B3CCallPtrTag)));
11012 call->appendArgs(args);
11013
11014 root->appendNewControlValue(proc, Return, Origin(), call);
11015
11016 std::unique_ptr<Compilation> compilation = compileProc(proc);
11017 CHECK(invoke<int>(*compilation) == invoke<int>(*compilation));
11018 CHECK(invoke<int>(*compilation) == 7967500);
11019 CHECK(invoke<int>(*compilation) == invoke<int>(*compilation));
11020 CHECK(invoke<int>(*compilation) == 7967500);
11021 CHECK(invoke<int>(*compilation) == invoke<int>(*compilation));
11022 CHECK(invoke<int>(*compilation) == 7967500);
11023 CHECK(invoke<int>(*compilation) == invoke<int>(*compilation));
11024 CHECK(invoke<int>(*compilation) == 7967500);
11025}
11026
11027void testReturnDouble(double value)
11028{
11029 Procedure proc;
11030 BasicBlock* root = proc.addBlock();
11031 root->appendNewControlValue(
11032 proc, Return, Origin(),
11033 root->appendNew<ConstDoubleValue>(proc, Origin(), value));
11034
11035 CHECK(isIdentical(compileAndRun<double>(proc), value));
11036}
11037
11038void testReturnFloat(float value)
11039{
11040 Procedure proc;
11041 BasicBlock* root = proc.addBlock();
11042 root->appendNewControlValue(
11043 proc, Return, Origin(),
11044 root->appendNew<ConstFloatValue>(proc, Origin(), value));
11045
11046 CHECK(isIdentical(compileAndRun<float>(proc), value));
11047}
11048
11049double simpleFunctionDouble(double a, double b)
11050{
11051 return a + b;
11052}
11053
11054void testCallSimpleDouble(double a, double b)
11055{
11056 Procedure proc;
11057 BasicBlock* root = proc.addBlock();
11058 root->appendNewControlValue(
11059 proc, Return, Origin(),
11060 root->appendNew<CCallValue>(
11061 proc, Double, Origin(),
11062 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(simpleFunctionDouble, B3CCallPtrTag)),
11063 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0),
11064 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)));
11065
11066 CHECK(compileAndRun<double>(proc, a, b) == a + b);
11067}
11068
11069float simpleFunctionFloat(float a, float b)
11070{
11071 return a + b;
11072}
11073
11074void testCallSimpleFloat(float a, float b)
11075{
11076 Procedure proc;
11077 BasicBlock* root = proc.addBlock();
11078 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
11079 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
11080 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
11081 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
11082 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
11083 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
11084 root->appendNewControlValue(
11085 proc, Return, Origin(),
11086 root->appendNew<CCallValue>(
11087 proc, Float, Origin(),
11088 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(simpleFunctionFloat, B3CCallPtrTag)),
11089 floatValue1,
11090 floatValue2));
11091
11092 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), a + b));
11093}
11094
11095double functionWithHellaDoubleArguments(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j, double k, double l, double m, double n, double o, double p, double q, double r, double s, double t, double u, double v, double w, double x, double y, double z)
11096{
11097 return a * pow(2, 0) + b * pow(2, 1) + c * pow(2, 2) + d * pow(2, 3) + e * pow(2, 4) + f * pow(2, 5) + g * pow(2, 6) + h * pow(2, 7) + i * pow(2, 8) + j * pow(2, 9) + k * pow(2, 10) + l * pow(2, 11) + m * pow(2, 12) + n * pow(2, 13) + o * pow(2, 14) + p * pow(2, 15) + q * pow(2, 16) + r * pow(2, 17) + s * pow(2, 18) + t * pow(2, 19) + u * pow(2, 20) + v * pow(2, 21) + w * pow(2, 22) + x * pow(2, 23) + y * pow(2, 24) + z * pow(2, 25);
11098}
11099
11100void testCallFunctionWithHellaDoubleArguments()
11101{
11102 Procedure proc;
11103 BasicBlock* root = proc.addBlock();
11104
11105 Vector<Value*> args;
11106 for (unsigned i = 0; i < 26; ++i)
11107 args.append(root->appendNew<ConstDoubleValue>(proc, Origin(), i + 1));
11108
11109 CCallValue* call = root->appendNew<CCallValue>(
11110 proc, Double, Origin(),
11111 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaDoubleArguments, B3CCallPtrTag)));
11112 call->appendArgs(args);
11113
11114 root->appendNewControlValue(proc, Return, Origin(), call);
11115
11116 CHECK(compileAndRun<double>(proc) == functionWithHellaDoubleArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26));
11117}
11118
11119float functionWithHellaFloatArguments(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p, float q, float r, float s, float t, float u, float v, float w, float x, float y, float z)
11120{
11121 return a * pow(2, 0) + b * pow(2, 1) + c * pow(2, 2) + d * pow(2, 3) + e * pow(2, 4) + f * pow(2, 5) + g * pow(2, 6) + h * pow(2, 7) + i * pow(2, 8) + j * pow(2, 9) + k * pow(2, 10) + l * pow(2, 11) + m * pow(2, 12) + n * pow(2, 13) + o * pow(2, 14) + p * pow(2, 15) + q * pow(2, 16) + r * pow(2, 17) + s * pow(2, 18) + t * pow(2, 19) + u * pow(2, 20) + v * pow(2, 21) + w * pow(2, 22) + x * pow(2, 23) + y * pow(2, 24) + z * pow(2, 25);
11122}
11123
11124void testCallFunctionWithHellaFloatArguments()
11125{
11126 Procedure proc;
11127 BasicBlock* root = proc.addBlock();
11128
11129 Vector<Value*> args;
11130 for (unsigned i = 0; i < 26; ++i)
11131 args.append(root->appendNew<ConstFloatValue>(proc, Origin(), i + 1));
11132
11133 CCallValue* call = root->appendNew<CCallValue>(
11134 proc, Float, Origin(),
11135 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaFloatArguments, B3CCallPtrTag)));
11136 call->appendArgs(args);
11137
11138 root->appendNewControlValue(proc, Return, Origin(), call);
11139
11140 CHECK(compileAndRun<float>(proc) == functionWithHellaFloatArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26));
11141}
11142
11143void testLinearScanWithCalleeOnStack()
11144{
11145 // This tests proper CCall generation when compiling with a lower optimization
11146 // level and operating with a callee argument that's spilt on the stack.
11147 // On ARM64, this caused an assert in MacroAssemblerARM64 because of disallowed
11148 // use of the scratch register.
11149 // https://bugs.webkit.org/show_bug.cgi?id=170672
11150
11151 Procedure proc;
11152 BasicBlock* root = proc.addBlock();
11153
11154 root->appendNewControlValue(
11155 proc, Return, Origin(),
11156 root->appendNew<CCallValue>(
11157 proc, Int32, Origin(),
11158 root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(simpleFunction, B3CCallPtrTag)),
11159 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
11160 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
11161
11162 // Force the linear scan algorithm to spill everything.
11163 auto original = Options::airLinearScanSpillsEverything();
11164 Options::airLinearScanSpillsEverything() = true;
11165
11166 // Compiling with 1 as the optimization level enforces the use of linear scan
11167 // for register allocation.
11168 auto code = compileProc(proc);
11169 CHECK_EQ(invoke<int>(*code, 41, 1), 42);
11170
11171 Options::airLinearScanSpillsEverything() = original;
11172}
11173
11174void testChillDiv(int num, int den, int res)
11175{
11176 // Test non-constant.
11177 {
11178 Procedure proc;
11179 BasicBlock* root = proc.addBlock();
11180
11181 root->appendNewControlValue(
11182 proc, Return, Origin(),
11183 root->appendNew<Value>(
11184 proc, chill(Div), Origin(),
11185 root->appendNew<Value>(
11186 proc, Trunc, Origin(),
11187 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
11188 root->appendNew<Value>(
11189 proc, Trunc, Origin(),
11190 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
11191
11192 CHECK(compileAndRun<int>(proc, num, den) == res);
11193 }
11194
11195 // Test constant.
11196 {
11197 Procedure proc;
11198 BasicBlock* root = proc.addBlock();
11199
11200 root->appendNewControlValue(
11201 proc, Return, Origin(),
11202 root->appendNew<Value>(
11203 proc, chill(Div), Origin(),
11204 root->appendNew<Const32Value>(proc, Origin(), num),
11205 root->appendNew<Const32Value>(proc, Origin(), den)));
11206
11207 CHECK(compileAndRun<int>(proc) == res);
11208 }
11209}
11210
11211void testChillDivTwice(int num1, int den1, int num2, int den2, int res)
11212{
11213 Procedure proc;
11214 BasicBlock* root = proc.addBlock();
11215
11216 root->appendNewControlValue(
11217 proc, Return, Origin(),
11218 root->appendNew<Value>(
11219 proc, Add, Origin(),
11220 root->appendNew<Value>(
11221 proc, chill(Div), Origin(),
11222 root->appendNew<Value>(
11223 proc, Trunc, Origin(),
11224 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
11225 root->appendNew<Value>(
11226 proc, Trunc, Origin(),
11227 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))),
11228 root->appendNew<Value>(
11229 proc, chill(Div), Origin(),
11230 root->appendNew<Value>(
11231 proc, Trunc, Origin(),
11232 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)),
11233 root->appendNew<Value>(
11234 proc, Trunc, Origin(),
11235 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)))));
11236
11237 CHECK(compileAndRun<int>(proc, num1, den1, num2, den2) == res);
11238}
11239
11240void testChillDiv64(int64_t num, int64_t den, int64_t res)
11241{
11242 if (!is64Bit())
11243 return;
11244
11245 // Test non-constant.
11246 {
11247 Procedure proc;
11248 BasicBlock* root = proc.addBlock();
11249
11250 root->appendNewControlValue(
11251 proc, Return, Origin(),
11252 root->appendNew<Value>(
11253 proc, chill(Div), Origin(),
11254 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
11255 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
11256
11257 CHECK(compileAndRun<int64_t>(proc, num, den) == res);
11258 }
11259
11260 // Test constant.
11261 {
11262 Procedure proc;
11263 BasicBlock* root = proc.addBlock();
11264
11265 root->appendNewControlValue(
11266 proc, Return, Origin(),
11267 root->appendNew<Value>(
11268 proc, chill(Div), Origin(),
11269 root->appendNew<Const64Value>(proc, Origin(), num),
11270 root->appendNew<Const64Value>(proc, Origin(), den)));
11271
11272 CHECK(compileAndRun<int64_t>(proc) == res);
11273 }
11274}
11275
11276void testModArg(int64_t value)
11277{
11278 if (!value)
11279 return;
11280
11281 Procedure proc;
11282 BasicBlock* root = proc.addBlock();
11283
11284 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
11285 Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument, argument);
11286 root->appendNewControlValue(proc, Return, Origin(), result);
11287
11288 CHECK(!compileAndRun<int64_t>(proc, value));
11289}
11290
11291void testModArgs(int64_t numerator, int64_t denominator)
11292{
11293 if (!denominator)
11294 return;
11295 if (numerator == std::numeric_limits<int64_t>::min() && denominator == -1)
11296 return;
11297
11298 Procedure proc;
11299 BasicBlock* root = proc.addBlock();
11300
11301 Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
11302 Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
11303 Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
11304 root->appendNewControlValue(proc, Return, Origin(), result);
11305
11306 CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == numerator % denominator);
11307}
11308
11309void testModImms(int64_t numerator, int64_t denominator)
11310{
11311 if (!denominator)
11312 return;
11313 if (numerator == std::numeric_limits<int64_t>::min() && denominator == -1)
11314 return;
11315
11316 Procedure proc;
11317 BasicBlock* root = proc.addBlock();
11318
11319 Value* argument1 = root->appendNew<Const64Value>(proc, Origin(), numerator);
11320 Value* argument2 = root->appendNew<Const64Value>(proc, Origin(), denominator);
11321 Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
11322 root->appendNewControlValue(proc, Return, Origin(), result);
11323
11324 CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == numerator % denominator);
11325}
11326
11327void testModArg32(int32_t value)
11328{
11329 if (!value)
11330 return;
11331
11332 Procedure proc;
11333 BasicBlock* root = proc.addBlock();
11334
11335 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
11336 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
11337 Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument, argument);
11338 root->appendNewControlValue(proc, Return, Origin(), result);
11339
11340 CHECK(!compileAndRun<int32_t>(proc, value));
11341}
11342
11343void testModArgs32(int32_t numerator, int32_t denominator)
11344{
11345 if (!denominator)
11346 return;
11347 if (numerator == std::numeric_limits<int32_t>::min() && denominator == -1)
11348 return;
11349
11350 Procedure proc;
11351 BasicBlock* root = proc.addBlock();
11352
11353 Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
11354 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
11355 Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
11356 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
11357 Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
11358 root->appendNewControlValue(proc, Return, Origin(), result);
11359
11360 CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == numerator % denominator);
11361}
11362
11363void testModImms32(int32_t numerator, int32_t denominator)
11364{
11365 if (!denominator)
11366 return;
11367 if (numerator == std::numeric_limits<int32_t>::min() && denominator == -1)
11368 return;
11369
11370 Procedure proc;
11371 BasicBlock* root = proc.addBlock();
11372
11373 Value* argument1 = root->appendNew<Const32Value>(proc, Origin(), numerator);
11374 Value* argument2 = root->appendNew<Const32Value>(proc, Origin(), denominator);
11375 Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
11376 root->appendNewControlValue(proc, Return, Origin(), result);
11377
11378 CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == numerator % denominator);
11379}
11380
11381void testChillModArg(int64_t value)
11382{
11383 Procedure proc;
11384 BasicBlock* root = proc.addBlock();
11385
11386 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
11387 Value* result = root->appendNew<Value>(proc, chill(Mod), Origin(), argument, argument);
11388 root->appendNewControlValue(proc, Return, Origin(), result);
11389
11390 CHECK(!compileAndRun<int64_t>(proc, value));
11391}
11392
11393void testChillModArgs(int64_t numerator, int64_t denominator)
11394{
11395 Procedure proc;
11396 BasicBlock* root = proc.addBlock();
11397
11398 Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
11399 Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
11400 Value* result = root->appendNew<Value>(proc, chill(Mod), Origin(), argument1, argument2);
11401 root->appendNewControlValue(proc, Return, Origin(), result);
11402
11403 CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
11404}
11405
11406void testChillModImms(int64_t numerator, int64_t denominator)
11407{
11408 Procedure proc;
11409 BasicBlock* root = proc.addBlock();
11410
11411 Value* argument1 = root->appendNew<Const64Value>(proc, Origin(), numerator);
11412 Value* argument2 = root->appendNew<Const64Value>(proc, Origin(), denominator);
11413 Value* result = root->appendNew<Value>(proc, chill(Mod), Origin(), argument1, argument2);
11414 root->appendNewControlValue(proc, Return, Origin(), result);
11415
11416 CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
11417}
11418
11419void testChillModArg32(int32_t value)
11420{
11421 Procedure proc;
11422 BasicBlock* root = proc.addBlock();
11423
11424 Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
11425 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
11426 Value* result = root->appendNew<Value>(proc, chill(Mod), Origin(), argument, argument);
11427 root->appendNewControlValue(proc, Return, Origin(), result);
11428
11429 CHECK(!compileAndRun<int32_t>(proc, value));
11430}
11431
11432void testChillModArgs32(int32_t numerator, int32_t denominator)
11433{
11434 Procedure proc;
11435 BasicBlock* root = proc.addBlock();
11436
11437 Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
11438 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
11439 Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
11440 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
11441 Value* result = root->appendNew<Value>(proc, chill(Mod), Origin(), argument1, argument2);
11442 root->appendNewControlValue(proc, Return, Origin(), result);
11443
11444 CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
11445}
11446
11447void testChillModImms32(int32_t numerator, int32_t denominator)
11448{
11449 Procedure proc;
11450 BasicBlock* root = proc.addBlock();
11451
11452 Value* argument1 = root->appendNew<Const32Value>(proc, Origin(), numerator);
11453 Value* argument2 = root->appendNew<Const32Value>(proc, Origin(), denominator);
11454 Value* result = root->appendNew<Value>(proc, chill(Mod), Origin(), argument1, argument2);
11455 root->appendNewControlValue(proc, Return, Origin(), result);
11456
11457 CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
11458}
11459
11460void testLoopWithMultipleHeaderEdges()
11461{
11462 Procedure proc;
11463 BasicBlock* root = proc.addBlock();
11464 BasicBlock* innerHeader = proc.addBlock();
11465 BasicBlock* innerEnd = proc.addBlock();
11466 BasicBlock* outerHeader = proc.addBlock();
11467 BasicBlock* outerEnd = proc.addBlock();
11468 BasicBlock* end = proc.addBlock();
11469
11470 auto* ne42 = outerHeader->appendNew<Value>(
11471 proc, NotEqual, Origin(),
11472 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
11473 root->appendNew<ConstPtrValue>(proc, Origin(), 42));
11474 outerHeader->appendNewControlValue(
11475 proc, Branch, Origin(),
11476 ne42,
11477 FrequentedBlock(innerHeader), FrequentedBlock(outerEnd));
11478 outerEnd->appendNewControlValue(
11479 proc, Branch, Origin(),
11480 root->appendNew<Value>(
11481 proc, Trunc, Origin(),
11482 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
11483 FrequentedBlock(outerHeader), FrequentedBlock(end));
11484
11485 SwitchValue* switchValue = innerHeader->appendNew<SwitchValue>(
11486 proc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
11487 switchValue->setFallThrough(FrequentedBlock(innerEnd));
11488 for (unsigned i = 0; i < 20; ++i) {
11489 switchValue->appendCase(SwitchCase(i, FrequentedBlock(innerHeader)));
11490 }
11491
11492 root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(outerHeader));
11493
11494 innerEnd->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(outerEnd));
11495 end->appendNewControlValue(
11496 proc, Return, Origin(),
11497 end->appendNew<Const32Value>(proc, Origin(), 5678));
11498
11499 auto code = compileProc(proc); // This shouldn't crash in computing NaturalLoops.
11500 CHECK(invoke<int32_t>(*code, 0, 12345) == 5678);
11501}
11502
11503void testSwitch(unsigned degree, unsigned gap = 1)
11504{
11505 Procedure proc;
11506 BasicBlock* root = proc.addBlock();
11507
11508 BasicBlock* terminate = proc.addBlock();
11509 terminate->appendNewControlValue(
11510 proc, Return, Origin(),
11511 terminate->appendNew<Const32Value>(proc, Origin(), 0));
11512
11513 SwitchValue* switchValue = root->appendNew<SwitchValue>(
11514 proc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
11515 switchValue->setFallThrough(FrequentedBlock(terminate));
11516
11517 for (unsigned i = 0; i < degree; ++i) {
11518 BasicBlock* newBlock = proc.addBlock();
11519 newBlock->appendNewControlValue(
11520 proc, Return, Origin(),
11521 newBlock->appendNew<ArgumentRegValue>(
11522 proc, Origin(), (i & 1) ? GPRInfo::argumentGPR2 : GPRInfo::argumentGPR1));
11523 switchValue->appendCase(SwitchCase(gap * i, FrequentedBlock(newBlock)));
11524 }
11525
11526 auto code = compileProc(proc);
11527
11528 for (unsigned i = 0; i < degree; ++i) {
11529 CHECK(invoke<int32_t>(*code, i * gap, 42, 11) == ((i & 1) ? 11 : 42));
11530 if (gap > 1) {
11531 CHECK(!invoke<int32_t>(*code, i * gap + 1, 42, 11));
11532 CHECK(!invoke<int32_t>(*code, i * gap - 1, 42, 11));
11533 }
11534 }
11535
11536 CHECK(!invoke<int32_t>(*code, -1, 42, 11));
11537 CHECK(!invoke<int32_t>(*code, degree * gap, 42, 11));
11538 CHECK(!invoke<int32_t>(*code, degree * gap + 1, 42, 11));
11539}
11540
11541void testSwitchSameCaseAsDefault()
11542{
11543 Procedure proc;
11544 BasicBlock* root = proc.addBlock();
11545
11546 BasicBlock* return10 = proc.addBlock();
11547 return10->appendNewControlValue(
11548 proc, Return, Origin(),
11549 return10->appendNew<Const32Value>(proc, Origin(), 10));
11550
11551 Value* switchOperand = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
11552
11553 BasicBlock* caseAndDefault = proc.addBlock();
11554 caseAndDefault->appendNewControlValue(
11555 proc, Return, Origin(),
11556 caseAndDefault->appendNew<Value>(
11557 proc, Equal, Origin(),
11558 switchOperand, caseAndDefault->appendNew<ConstPtrValue>(proc, Origin(), 0)));
11559
11560 SwitchValue* switchValue = root->appendNew<SwitchValue>(proc, Origin(), switchOperand);
11561
11562 switchValue->appendCase(SwitchCase(100, FrequentedBlock(return10)));
11563
11564 // Because caseAndDefault is reached both as default case, and when it's 0,
11565 // we should not incorrectly optimize and assume that switchOperand==0.
11566 switchValue->appendCase(SwitchCase(0, FrequentedBlock(caseAndDefault)));
11567 switchValue->setFallThrough(FrequentedBlock(caseAndDefault));
11568
11569 auto code = compileProc(proc);
11570
11571 CHECK(invoke<int32_t>(*code, 100) == 10);
11572 CHECK(invoke<int32_t>(*code, 0) == 1);
11573 CHECK(invoke<int32_t>(*code, 1) == 0);
11574 CHECK(invoke<int32_t>(*code, 2) == 0);
11575 CHECK(invoke<int32_t>(*code, 99) == 0);
11576 CHECK(invoke<int32_t>(*code, 0xbaadbeef) == 0);
11577}
11578
11579void testSwitchChillDiv(unsigned degree, unsigned gap = 1)
11580{
11581 Procedure proc;
11582 BasicBlock* root = proc.addBlock();
11583
11584 Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
11585 Value* right = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
11586
11587 BasicBlock* terminate = proc.addBlock();
11588 terminate->appendNewControlValue(
11589 proc, Return, Origin(),
11590 terminate->appendNew<Const32Value>(proc, Origin(), 0));
11591
11592 SwitchValue* switchValue = root->appendNew<SwitchValue>(
11593 proc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
11594 switchValue->setFallThrough(FrequentedBlock(terminate));
11595
11596 for (unsigned i = 0; i < degree; ++i) {
11597 BasicBlock* newBlock = proc.addBlock();
11598
11599 newBlock->appendNewControlValue(
11600 proc, Return, Origin(),
11601 newBlock->appendNew<Value>(
11602 proc, chill(Div), Origin(), (i & 1) ? right : left, (i & 1) ? left : right));
11603
11604 switchValue->appendCase(SwitchCase(gap * i, FrequentedBlock(newBlock)));
11605 }
11606
11607 auto code = compileProc(proc);
11608
11609 for (unsigned i = 0; i < degree; ++i) {
11610 dataLog("i = ", i, "\n");
11611 int32_t result = invoke<int32_t>(*code, i * gap, 42, 11);
11612 dataLog("result = ", result, "\n");
11613 CHECK(result == ((i & 1) ? 11/42 : 42/11));
11614 if (gap > 1) {
11615 CHECK(!invoke<int32_t>(*code, i * gap + 1, 42, 11));
11616 CHECK(!invoke<int32_t>(*code, i * gap - 1, 42, 11));
11617 }
11618 }
11619
11620 CHECK(!invoke<int32_t>(*code, -1, 42, 11));
11621 CHECK(!invoke<int32_t>(*code, degree * gap, 42, 11));
11622 CHECK(!invoke<int32_t>(*code, degree * gap + 1, 42, 11));
11623}
11624
11625void testSwitchTargettingSameBlock()
11626{
11627 Procedure proc;
11628 BasicBlock* root = proc.addBlock();
11629
11630 BasicBlock* terminate = proc.addBlock();
11631 terminate->appendNewControlValue(
11632 proc, Return, Origin(),
11633 terminate->appendNew<Const32Value>(proc, Origin(), 5));
11634
11635 SwitchValue* switchValue = root->appendNew<SwitchValue>(
11636 proc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
11637 switchValue->setFallThrough(FrequentedBlock(terminate));
11638
11639 BasicBlock* otherTarget = proc.addBlock();
11640 otherTarget->appendNewControlValue(
11641 proc, Return, Origin(),
11642 otherTarget->appendNew<Const32Value>(proc, Origin(), 42));
11643 switchValue->appendCase(SwitchCase(3, FrequentedBlock(otherTarget)));
11644 switchValue->appendCase(SwitchCase(13, FrequentedBlock(otherTarget)));
11645
11646 auto code = compileProc(proc);
11647
11648 for (unsigned i = 0; i < 20; ++i) {
11649 int32_t expected = (i == 3 || i == 13) ? 42 : 5;
11650 CHECK(invoke<int32_t>(*code, i) == expected);
11651 }
11652}
11653
11654void testSwitchTargettingSameBlockFoldPathConstant()
11655{
11656 Procedure proc;
11657 BasicBlock* root = proc.addBlock();
11658
11659 BasicBlock* terminate = proc.addBlock();
11660 terminate->appendNewControlValue(
11661 proc, Return, Origin(),
11662 terminate->appendNew<Const32Value>(proc, Origin(), 42));
11663
11664 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
11665 SwitchValue* switchValue = root->appendNew<SwitchValue>(proc, Origin(), argument);
11666 switchValue->setFallThrough(FrequentedBlock(terminate));
11667
11668 BasicBlock* otherTarget = proc.addBlock();
11669 otherTarget->appendNewControlValue(
11670 proc, Return, Origin(), argument);
11671 switchValue->appendCase(SwitchCase(3, FrequentedBlock(otherTarget)));
11672 switchValue->appendCase(SwitchCase(13, FrequentedBlock(otherTarget)));
11673
11674 auto code = compileProc(proc);
11675
11676 for (unsigned i = 0; i < 20; ++i) {
11677 int32_t expected = (i == 3 || i == 13) ? i : 42;
11678 CHECK(invoke<int32_t>(*code, i) == expected);
11679 }
11680}
11681
11682void testTruncFold(int64_t value)
11683{
11684 Procedure proc;
11685 BasicBlock* root = proc.addBlock();
11686 root->appendNewControlValue(
11687 proc, Return, Origin(),
11688 root->appendNew<Value>(
11689 proc, Trunc, Origin(),
11690 root->appendNew<Const64Value>(proc, Origin(), value)));
11691
11692 CHECK(compileAndRun<int>(proc) == static_cast<int>(value));
11693}
11694
11695void testZExt32(int32_t value)
11696{
11697 Procedure proc;
11698 BasicBlock* root = proc.addBlock();
11699 root->appendNewControlValue(
11700 proc, Return, Origin(),
11701 root->appendNew<Value>(
11702 proc, ZExt32, Origin(),
11703 root->appendNew<Value>(
11704 proc, Trunc, Origin(),
11705 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
11706
11707 CHECK(compileAndRun<uint64_t>(proc, value) == static_cast<uint64_t>(static_cast<uint32_t>(value)));
11708}
11709
11710void testZExt32Fold(int32_t value)
11711{
11712 Procedure proc;
11713 BasicBlock* root = proc.addBlock();
11714 root->appendNewControlValue(
11715 proc, Return, Origin(),
11716 root->appendNew<Value>(
11717 proc, ZExt32, Origin(),
11718 root->appendNew<Const32Value>(proc, Origin(), value)));
11719
11720 CHECK(compileAndRun<uint64_t>(proc, value) == static_cast<uint64_t>(static_cast<uint32_t>(value)));
11721}
11722
11723void testSExt32(int32_t value)
11724{
11725 Procedure proc;
11726 BasicBlock* root = proc.addBlock();
11727 root->appendNewControlValue(
11728 proc, Return, Origin(),
11729 root->appendNew<Value>(
11730 proc, SExt32, Origin(),
11731 root->appendNew<Value>(
11732 proc, Trunc, Origin(),
11733 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
11734
11735 CHECK(compileAndRun<int64_t>(proc, value) == static_cast<int64_t>(value));
11736}
11737
11738void testSExt32Fold(int32_t value)
11739{
11740 Procedure proc;
11741 BasicBlock* root = proc.addBlock();
11742 root->appendNewControlValue(
11743 proc, Return, Origin(),
11744 root->appendNew<Value>(
11745 proc, SExt32, Origin(),
11746 root->appendNew<Const32Value>(proc, Origin(), value)));
11747
11748 CHECK(compileAndRun<int64_t>(proc, value) == static_cast<int64_t>(value));
11749}
11750
11751void testTruncZExt32(int32_t value)
11752{
11753 Procedure proc;
11754 BasicBlock* root = proc.addBlock();
11755 root->appendNewControlValue(
11756 proc, Return, Origin(),
11757 root->appendNew<Value>(
11758 proc, Trunc, Origin(),
11759 root->appendNew<Value>(
11760 proc, ZExt32, Origin(),
11761 root->appendNew<Value>(
11762 proc, Trunc, Origin(),
11763 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))));
11764
11765 CHECK(compileAndRun<int32_t>(proc, value) == value);
11766}
11767
11768void testTruncSExt32(int32_t value)
11769{
11770 Procedure proc;
11771 BasicBlock* root = proc.addBlock();
11772 root->appendNewControlValue(
11773 proc, Return, Origin(),
11774 root->appendNew<Value>(
11775 proc, Trunc, Origin(),
11776 root->appendNew<Value>(
11777 proc, SExt32, Origin(),
11778 root->appendNew<Value>(
11779 proc, Trunc, Origin(),
11780 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))));
11781
11782 CHECK(compileAndRun<int32_t>(proc, value) == value);
11783}
11784
11785void testSExt8(int32_t value)
11786{
11787 Procedure proc;
11788 BasicBlock* root = proc.addBlock();
11789 root->appendNewControlValue(
11790 proc, Return, Origin(),
11791 root->appendNew<Value>(
11792 proc, SExt8, Origin(),
11793 root->appendNew<Value>(
11794 proc, Trunc, Origin(),
11795 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
11796
11797 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value)));
11798}
11799
11800void testSExt8Fold(int32_t value)
11801{
11802 Procedure proc;
11803 BasicBlock* root = proc.addBlock();
11804 root->appendNewControlValue(
11805 proc, Return, Origin(),
11806 root->appendNew<Value>(
11807 proc, SExt8, Origin(),
11808 root->appendNew<Const32Value>(proc, Origin(), value)));
11809
11810 CHECK(compileAndRun<int32_t>(proc) == static_cast<int32_t>(static_cast<int8_t>(value)));
11811}
11812
11813void testSExt8SExt8(int32_t value)
11814{
11815 Procedure proc;
11816 BasicBlock* root = proc.addBlock();
11817 root->appendNewControlValue(
11818 proc, Return, Origin(),
11819 root->appendNew<Value>(
11820 proc, SExt8, Origin(),
11821 root->appendNew<Value>(
11822 proc, SExt8, Origin(),
11823 root->appendNew<Value>(
11824 proc, Trunc, Origin(),
11825 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))));
11826
11827 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value)));
11828}
11829
11830void testSExt8SExt16(int32_t value)
11831{
11832 Procedure proc;
11833 BasicBlock* root = proc.addBlock();
11834 root->appendNewControlValue(
11835 proc, Return, Origin(),
11836 root->appendNew<Value>(
11837 proc, SExt8, Origin(),
11838 root->appendNew<Value>(
11839 proc, SExt16, Origin(),
11840 root->appendNew<Value>(
11841 proc, Trunc, Origin(),
11842 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))));
11843
11844 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value)));
11845}
11846
11847void testSExt8BitAnd(int32_t value, int32_t mask)
11848{
11849 Procedure proc;
11850 BasicBlock* root = proc.addBlock();
11851 root->appendNewControlValue(
11852 proc, Return, Origin(),
11853 root->appendNew<Value>(
11854 proc, SExt8, Origin(),
11855 root->appendNew<Value>(
11856 proc, BitAnd, Origin(),
11857 root->appendNew<Value>(
11858 proc, Trunc, Origin(),
11859 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
11860 root->appendNew<Const32Value>(proc, Origin(), mask))));
11861
11862 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value & mask)));
11863}
11864
11865void testBitAndSExt8(int32_t value, int32_t mask)
11866{
11867 Procedure proc;
11868 BasicBlock* root = proc.addBlock();
11869 root->appendNewControlValue(
11870 proc, Return, Origin(),
11871 root->appendNew<Value>(
11872 proc, BitAnd, Origin(),
11873 root->appendNew<Value>(
11874 proc, SExt8, Origin(),
11875 root->appendNew<Value>(
11876 proc, Trunc, Origin(),
11877 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
11878 root->appendNew<Const32Value>(proc, Origin(), mask)));
11879
11880 CHECK(compileAndRun<int32_t>(proc, value) == (static_cast<int32_t>(static_cast<int8_t>(value)) & mask));
11881}
11882
11883void testSExt16(int32_t value)
11884{
11885 Procedure proc;
11886 BasicBlock* root = proc.addBlock();
11887 root->appendNewControlValue(
11888 proc, Return, Origin(),
11889 root->appendNew<Value>(
11890 proc, SExt16, Origin(),
11891 root->appendNew<Value>(
11892 proc, Trunc, Origin(),
11893 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
11894
11895 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int16_t>(value)));
11896}
11897
11898void testSExt16Fold(int32_t value)
11899{
11900 Procedure proc;
11901 BasicBlock* root = proc.addBlock();
11902 root->appendNewControlValue(
11903 proc, Return, Origin(),
11904 root->appendNew<Value>(
11905 proc, SExt16, Origin(),
11906 root->appendNew<Const32Value>(proc, Origin(), value)));
11907
11908 CHECK(compileAndRun<int32_t>(proc) == static_cast<int32_t>(static_cast<int16_t>(value)));
11909}
11910
11911void testSExt16SExt16(int32_t value)
11912{
11913 Procedure proc;
11914 BasicBlock* root = proc.addBlock();
11915 root->appendNewControlValue(
11916 proc, Return, Origin(),
11917 root->appendNew<Value>(
11918 proc, SExt16, Origin(),
11919 root->appendNew<Value>(
11920 proc, SExt16, Origin(),
11921 root->appendNew<Value>(
11922 proc, Trunc, Origin(),
11923 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))));
11924
11925 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int16_t>(value)));
11926}
11927
11928void testSExt16SExt8(int32_t value)
11929{
11930 Procedure proc;
11931 BasicBlock* root = proc.addBlock();
11932 root->appendNewControlValue(
11933 proc, Return, Origin(),
11934 root->appendNew<Value>(
11935 proc, SExt16, Origin(),
11936 root->appendNew<Value>(
11937 proc, SExt8, Origin(),
11938 root->appendNew<Value>(
11939 proc, Trunc, Origin(),
11940 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))));
11941
11942 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value)));
11943}
11944
11945void testSExt16BitAnd(int32_t value, int32_t mask)
11946{
11947 Procedure proc;
11948 BasicBlock* root = proc.addBlock();
11949 root->appendNewControlValue(
11950 proc, Return, Origin(),
11951 root->appendNew<Value>(
11952 proc, SExt16, Origin(),
11953 root->appendNew<Value>(
11954 proc, BitAnd, Origin(),
11955 root->appendNew<Value>(
11956 proc, Trunc, Origin(),
11957 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
11958 root->appendNew<Const32Value>(proc, Origin(), mask))));
11959
11960 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int16_t>(value & mask)));
11961}
11962
11963void testBitAndSExt16(int32_t value, int32_t mask)
11964{
11965 Procedure proc;
11966 BasicBlock* root = proc.addBlock();
11967 root->appendNewControlValue(
11968 proc, Return, Origin(),
11969 root->appendNew<Value>(
11970 proc, BitAnd, Origin(),
11971 root->appendNew<Value>(
11972 proc, SExt16, Origin(),
11973 root->appendNew<Value>(
11974 proc, Trunc, Origin(),
11975 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
11976 root->appendNew<Const32Value>(proc, Origin(), mask)));
11977
11978 CHECK(compileAndRun<int32_t>(proc, value) == (static_cast<int32_t>(static_cast<int16_t>(value)) & mask));
11979}
11980
11981void testSExt32BitAnd(int32_t value, int32_t mask)
11982{
11983 Procedure proc;
11984 BasicBlock* root = proc.addBlock();
11985 root->appendNewControlValue(
11986 proc, Return, Origin(),
11987 root->appendNew<Value>(
11988 proc, SExt32, Origin(),
11989 root->appendNew<Value>(
11990 proc, BitAnd, Origin(),
11991 root->appendNew<Value>(
11992 proc, Trunc, Origin(),
11993 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
11994 root->appendNew<Const32Value>(proc, Origin(), mask))));
11995
11996 CHECK(compileAndRun<int64_t>(proc, value) == static_cast<int64_t>(value & mask));
11997}
11998
11999void testBitAndSExt32(int32_t value, int64_t mask)
12000{
12001 Procedure proc;
12002 BasicBlock* root = proc.addBlock();
12003 root->appendNewControlValue(
12004 proc, Return, Origin(),
12005 root->appendNew<Value>(
12006 proc, BitAnd, Origin(),
12007 root->appendNew<Value>(
12008 proc, SExt32, Origin(),
12009 root->appendNew<Value>(
12010 proc, Trunc, Origin(),
12011 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
12012 root->appendNew<Const64Value>(proc, Origin(), mask)));
12013
12014 CHECK(compileAndRun<int64_t>(proc, value) == (static_cast<int64_t>(value) & mask));
12015}
12016
12017void testBasicSelect()
12018{
12019 Procedure proc;
12020 BasicBlock* root = proc.addBlock();
12021 root->appendNewControlValue(
12022 proc, Return, Origin(),
12023 root->appendNew<Value>(
12024 proc, Select, Origin(),
12025 root->appendNew<Value>(
12026 proc, Equal, Origin(),
12027 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12028 root->appendNew<ConstPtrValue>(proc, Origin(), 42)),
12029 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
12030 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12031
12032 auto code = compileProc(proc);
12033 CHECK(invoke<intptr_t>(*code, 42, 1, 2) == 1);
12034 CHECK(invoke<intptr_t>(*code, 42, 642462, 32533) == 642462);
12035 CHECK(invoke<intptr_t>(*code, 43, 1, 2) == 2);
12036 CHECK(invoke<intptr_t>(*code, 43, 642462, 32533) == 32533);
12037}
12038
12039void testSelectTest()
12040{
12041 Procedure proc;
12042 BasicBlock* root = proc.addBlock();
12043 root->appendNewControlValue(
12044 proc, Return, Origin(),
12045 root->appendNew<Value>(
12046 proc, Select, Origin(),
12047 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12048 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
12049 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12050
12051 auto code = compileProc(proc);
12052 CHECK(invoke<intptr_t>(*code, 42, 1, 2) == 1);
12053 CHECK(invoke<intptr_t>(*code, 42, 642462, 32533) == 642462);
12054 CHECK(invoke<intptr_t>(*code, 0, 1, 2) == 2);
12055 CHECK(invoke<intptr_t>(*code, 0, 642462, 32533) == 32533);
12056}
12057
12058void testSelectCompareDouble()
12059{
12060 Procedure proc;
12061 BasicBlock* root = proc.addBlock();
12062 root->appendNewControlValue(
12063 proc, Return, Origin(),
12064 root->appendNew<Value>(
12065 proc, Select, Origin(),
12066 root->appendNew<Value>(
12067 proc, LessThan, Origin(),
12068 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0),
12069 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)),
12070 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12071 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
12072
12073 auto code = compileProc(proc);
12074 CHECK(invoke<intptr_t>(*code, -1.0, 1.0, 1, 2) == 1);
12075 CHECK(invoke<intptr_t>(*code, 42.5, 42.51, 642462, 32533) == 642462);
12076 CHECK(invoke<intptr_t>(*code, PNaN, 0.0, 1, 2) == 2);
12077 CHECK(invoke<intptr_t>(*code, 42.51, 42.5, 642462, 32533) == 32533);
12078 CHECK(invoke<intptr_t>(*code, 42.52, 42.52, 524978245, 352) == 352);
12079}
12080
12081template<B3::Opcode opcode>
12082void testSelectCompareFloat(float a, float b, bool (*operation)(float, float))
12083{
12084 Procedure proc;
12085 BasicBlock* root = proc.addBlock();
12086 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12087 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
12088 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12089 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
12090 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
12091 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
12092
12093 root->appendNewControlValue(
12094 proc, Return, Origin(),
12095 root->appendNew<Value>(
12096 proc, Select, Origin(),
12097 root->appendNew<Value>(
12098 proc, opcode, Origin(),
12099 floatValue1,
12100 floatValue2),
12101 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2),
12102 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)));
12103 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), 42, -5), operation(a, b) ? 42 : -5));
12104}
12105
12106void testSelectCompareFloat(float a, float b)
12107{
12108 testSelectCompareFloat<Equal>(a, b, [](float a, float b) -> bool { return a == b; });
12109 testSelectCompareFloat<NotEqual>(a, b, [](float a, float b) -> bool { return a != b; });
12110 testSelectCompareFloat<LessThan>(a, b, [](float a, float b) -> bool { return a < b; });
12111 testSelectCompareFloat<GreaterThan>(a, b, [](float a, float b) -> bool { return a > b; });
12112 testSelectCompareFloat<LessEqual>(a, b, [](float a, float b) -> bool { return a <= b; });
12113 testSelectCompareFloat<GreaterEqual>(a, b, [](float a, float b) -> bool { return a >= b; });
12114 testSelectCompareFloat<EqualOrUnordered>(a, b, [](float a, float b) -> bool { return a != a || b != b || a == b; });
12115}
12116
12117template<B3::Opcode opcode>
12118void testSelectCompareFloatToDouble(float a, float b, bool (*operation)(float, float))
12119{
12120 Procedure proc;
12121 BasicBlock* root = proc.addBlock();
12122 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12123 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
12124 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12125 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
12126 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
12127 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
12128 Value* doubleValue1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
12129 Value* doubleValue2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
12130
12131 root->appendNewControlValue(
12132 proc, Return, Origin(),
12133 root->appendNew<Value>(
12134 proc, Select, Origin(),
12135 root->appendNew<Value>(
12136 proc, opcode, Origin(),
12137 doubleValue1,
12138 doubleValue2),
12139 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2),
12140 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)));
12141 CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), 42, -5), operation(a, b) ? 42 : -5));
12142}
12143
12144void testSelectCompareFloatToDouble(float a, float b)
12145{
12146 testSelectCompareFloatToDouble<Equal>(a, b, [](float a, float b) -> bool { return a == b; });
12147 testSelectCompareFloatToDouble<NotEqual>(a, b, [](float a, float b) -> bool { return a != b; });
12148 testSelectCompareFloatToDouble<LessThan>(a, b, [](float a, float b) -> bool { return a < b; });
12149 testSelectCompareFloatToDouble<GreaterThan>(a, b, [](float a, float b) -> bool { return a > b; });
12150 testSelectCompareFloatToDouble<LessEqual>(a, b, [](float a, float b) -> bool { return a <= b; });
12151 testSelectCompareFloatToDouble<GreaterEqual>(a, b, [](float a, float b) -> bool { return a >= b; });
12152 testSelectCompareFloatToDouble<EqualOrUnordered>(a, b, [](float a, float b) -> bool { return a != a || b != b || a == b; });
12153}
12154
12155void testSelectDouble()
12156{
12157 Procedure proc;
12158 BasicBlock* root = proc.addBlock();
12159 root->appendNewControlValue(
12160 proc, Return, Origin(),
12161 root->appendNew<Value>(
12162 proc, Select, Origin(),
12163 root->appendNew<Value>(
12164 proc, Equal, Origin(),
12165 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12166 root->appendNew<ConstPtrValue>(proc, Origin(), 42)),
12167 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0),
12168 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)));
12169
12170 auto code = compileProc(proc);
12171 CHECK(invoke<double>(*code, 42, 1.5, 2.6) == 1.5);
12172 CHECK(invoke<double>(*code, 42, 642462.7, 32533.8) == 642462.7);
12173 CHECK(invoke<double>(*code, 43, 1.9, 2.0) == 2.0);
12174 CHECK(invoke<double>(*code, 43, 642462.1, 32533.2) == 32533.2);
12175}
12176
12177void testSelectDoubleTest()
12178{
12179 Procedure proc;
12180 BasicBlock* root = proc.addBlock();
12181 root->appendNewControlValue(
12182 proc, Return, Origin(),
12183 root->appendNew<Value>(
12184 proc, Select, Origin(),
12185 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12186 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0),
12187 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)));
12188
12189 auto code = compileProc(proc);
12190 CHECK(invoke<double>(*code, 42, 1.5, 2.6) == 1.5);
12191 CHECK(invoke<double>(*code, 42, 642462.7, 32533.8) == 642462.7);
12192 CHECK(invoke<double>(*code, 0, 1.9, 2.0) == 2.0);
12193 CHECK(invoke<double>(*code, 0, 642462.1, 32533.2) == 32533.2);
12194}
12195
12196void testSelectDoubleCompareDouble()
12197{
12198 Procedure proc;
12199 BasicBlock* root = proc.addBlock();
12200 root->appendNewControlValue(
12201 proc, Return, Origin(),
12202 root->appendNew<Value>(
12203 proc, Select, Origin(),
12204 root->appendNew<Value>(
12205 proc, LessThan, Origin(),
12206 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0),
12207 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)),
12208 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2),
12209 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3)));
12210
12211 auto code = compileProc(proc);
12212 CHECK(invoke<double>(*code, -1.0, 1.0, 1.1, 2.2) == 1.1);
12213 CHECK(invoke<double>(*code, 42.5, 42.51, 642462.3, 32533.4) == 642462.3);
12214 CHECK(invoke<double>(*code, PNaN, 0.0, 1.5, 2.6) == 2.6);
12215 CHECK(invoke<double>(*code, 42.51, 42.5, 642462.7, 32533.8) == 32533.8);
12216 CHECK(invoke<double>(*code, 42.52, 42.52, 524978245.9, 352.0) == 352.0);
12217}
12218
12219void testSelectDoubleCompareFloat(float a, float b)
12220{
12221 Procedure proc;
12222 BasicBlock* root = proc.addBlock();
12223 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12224 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
12225 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12226 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
12227 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
12228 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
12229
12230 root->appendNewControlValue(
12231 proc, Return, Origin(),
12232 root->appendNew<Value>(
12233 proc, Select, Origin(),
12234 root->appendNew<Value>(
12235 proc, LessThan, Origin(),
12236 floatValue1,
12237 floatValue2),
12238 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0),
12239 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)));
12240
12241 CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), 42.1, -M_PI), a < b ? 42.1 : -M_PI));
12242}
12243
12244void testSelectFloatCompareFloat(float a, float b)
12245{
12246 Procedure proc;
12247 BasicBlock* root = proc.addBlock();
12248 Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12249 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
12250 Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12251 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
12252 Value* argument3int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12253 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
12254 Value* argument4int32 = root->appendNew<Value>(proc, Trunc, Origin(),
12255 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3));
12256 Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
12257 Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
12258 Value* floatValue3 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument3int32);
12259 Value* floatValue4 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument4int32);
12260
12261 root->appendNewControlValue(
12262 proc, Return, Origin(),
12263 root->appendNew<Value>(
12264 proc, Select, Origin(),
12265 root->appendNew<Value>(
12266 proc, LessThan, Origin(),
12267 floatValue1,
12268 floatValue2),
12269 floatValue3,
12270 floatValue4));
12271
12272 CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), bitwise_cast<int32_t>(1.1f), bitwise_cast<int32_t>(-42.f)), a < b ? 1.1f : -42.f));
12273}
12274
12275
12276template<B3::Opcode opcode>
12277void testSelectDoubleCompareDouble(bool (*operation)(double, double))
12278{
12279 { // Compare arguments and selected arguments are all different.
12280 Procedure proc;
12281 BasicBlock* root = proc.addBlock();
12282 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
12283 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
12284 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2);
12285 Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3);
12286
12287 root->appendNewControlValue(
12288 proc, Return, Origin(),
12289 root->appendNew<Value>(
12290 proc, Select, Origin(),
12291 root->appendNew<Value>(
12292 proc, opcode, Origin(),
12293 arg0,
12294 arg1),
12295 arg2,
12296 arg3));
12297 auto code = compileProc(proc);
12298
12299 for (auto& left : floatingPointOperands<double>()) {
12300 for (auto& right : floatingPointOperands<double>()) {
12301 double expected = operation(left.value, right.value) ? 42.5 : -66.5;
12302 CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, -66.5), expected));
12303 }
12304 }
12305 }
12306 { // Compare arguments and selected arguments are all different. "thenCase" is live after operation.
12307 Procedure proc;
12308 BasicBlock* root = proc.addBlock();
12309 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
12310 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
12311 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2);
12312 Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3);
12313
12314 Value* result = root->appendNew<Value>(proc, Select, Origin(),
12315 root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1),
12316 arg2,
12317 arg3);
12318
12319 PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin());
12320 keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
12321 keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
12322
12323 root->appendNewControlValue(proc, Return, Origin(), result);
12324 auto code = compileProc(proc);
12325
12326 for (auto& left : floatingPointOperands<double>()) {
12327 for (auto& right : floatingPointOperands<double>()) {
12328 double expected = operation(left.value, right.value) ? 42.5 : -66.5;
12329 CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, -66.5), expected));
12330 }
12331 }
12332 }
12333 { // Compare arguments and selected arguments are all different. "elseCase" is live after operation.
12334 Procedure proc;
12335 BasicBlock* root = proc.addBlock();
12336 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
12337 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
12338 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2);
12339 Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3);
12340
12341 Value* result = root->appendNew<Value>(proc, Select, Origin(),
12342 root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1),
12343 arg2,
12344 arg3);
12345
12346 PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin());
12347 keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister));
12348 keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
12349
12350 root->appendNewControlValue(proc, Return, Origin(), result);
12351 auto code = compileProc(proc);
12352
12353 for (auto& left : floatingPointOperands<double>()) {
12354 for (auto& right : floatingPointOperands<double>()) {
12355 double expected = operation(left.value, right.value) ? 42.5 : -66.5;
12356 CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, -66.5), expected));
12357 }
12358 }
12359 }
12360 { // Compare arguments and selected arguments are all different. Both cases are live after operation.
12361 Procedure proc;
12362 BasicBlock* root = proc.addBlock();
12363 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
12364 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
12365 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2);
12366 Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3);
12367
12368 Value* result = root->appendNew<Value>(proc, Select, Origin(),
12369 root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1),
12370 arg2,
12371 arg3);
12372
12373 PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin());
12374 keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
12375 keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister));
12376 keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
12377
12378 root->appendNewControlValue(proc, Return, Origin(), result);
12379 auto code = compileProc(proc);
12380
12381 for (auto& left : floatingPointOperands<double>()) {
12382 for (auto& right : floatingPointOperands<double>()) {
12383 double expected = operation(left.value, right.value) ? 42.5 : -66.5;
12384 CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, -66.5), expected));
12385 }
12386 }
12387 }
12388 { // The left argument is the same as the "elseCase" argument.
12389 Procedure proc;
12390 BasicBlock* root = proc.addBlock();
12391 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
12392 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
12393 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2);
12394
12395 root->appendNewControlValue(
12396 proc, Return, Origin(),
12397 root->appendNew<Value>(
12398 proc, Select, Origin(),
12399 root->appendNew<Value>(
12400 proc, opcode, Origin(),
12401 arg0,
12402 arg1),
12403 arg2,
12404 arg0));
12405 auto code = compileProc(proc);
12406
12407 for (auto& left : floatingPointOperands<double>()) {
12408 for (auto& right : floatingPointOperands<double>()) {
12409 double expected = operation(left.value, right.value) ? 42.5 : left.value;
12410 CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, left.value), expected));
12411 }
12412 }
12413 }
12414 { // The left argument is the same as the "elseCase" argument. "thenCase" is live after operation.
12415 Procedure proc;
12416 BasicBlock* root = proc.addBlock();
12417 Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
12418 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
12419 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2);
12420
12421 Value* result = root->appendNew<Value>(proc, Select, Origin(),
12422 root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1),
12423 arg2,
12424 arg0);
12425
12426 PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin());
12427 keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
12428 keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
12429
12430 root->appendNewControlValue(proc, Return, Origin(), result);
12431 auto code = compileProc(proc);
12432
12433 for (auto& left : floatingPointOperands<double>()) {
12434 for (auto& right : floatingPointOperands<double>()) {
12435 double expected = operation(left.value, right.value) ? 42.5 : left.value;
12436 CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, left.value), expected));
12437 }
12438 }
12439 }
12440}
12441
12442void testSelectDoubleCompareDoubleWithAliasing()
12443{
12444 testSelectDoubleCompareDouble<Equal>([](double a, double b) -> bool { return a == b; });
12445 testSelectDoubleCompareDouble<NotEqual>([](double a, double b) -> bool { return a != b; });
12446 testSelectDoubleCompareDouble<LessThan>([](double a, double b) -> bool { return a < b; });
12447 testSelectDoubleCompareDouble<GreaterThan>([](double a, double b) -> bool { return a > b; });
12448 testSelectDoubleCompareDouble<LessEqual>([](double a, double b) -> bool { return a <= b; });
12449 testSelectDoubleCompareDouble<GreaterEqual>([](double a, double b) -> bool { return a >= b; });
12450 testSelectDoubleCompareDouble<EqualOrUnordered>([](double a, double b) -> bool { return a != a || b != b || a == b; });
12451}
12452
12453template<B3::Opcode opcode>
12454void testSelectFloatCompareFloat(bool (*operation)(float, float))
12455{
12456 { // Compare arguments and selected arguments are all different.
12457 Procedure proc;
12458 BasicBlock* root = proc.addBlock();
12459
12460 Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12461 root->appendNew<Value>(proc, Trunc, Origin(),
12462 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
12463 Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12464 root->appendNew<Value>(proc, Trunc, Origin(),
12465 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
12466 Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12467 root->appendNew<Value>(proc, Trunc, Origin(),
12468 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12469 Value* arg3 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12470 root->appendNew<Value>(proc, Trunc, Origin(),
12471 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)));
12472
12473 root->appendNewControlValue(
12474 proc, Return, Origin(),
12475 root->appendNew<Value>(
12476 proc, Select, Origin(),
12477 root->appendNew<Value>(
12478 proc, opcode, Origin(),
12479 arg0,
12480 arg1),
12481 arg2,
12482 arg3));
12483 auto code = compileProc(proc);
12484
12485 for (auto& left : floatingPointOperands<float>()) {
12486 for (auto& right : floatingPointOperands<float>()) {
12487 float expected = operation(left.value, right.value) ? 42.5 : -66.5;
12488 CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(-66.5f)), expected));
12489 }
12490 }
12491 }
12492 { // Compare arguments and selected arguments are all different. "thenCase" is live after operation.
12493 Procedure proc;
12494 BasicBlock* root = proc.addBlock();
12495 Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12496 root->appendNew<Value>(proc, Trunc, Origin(),
12497 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
12498 Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12499 root->appendNew<Value>(proc, Trunc, Origin(),
12500 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
12501 Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12502 root->appendNew<Value>(proc, Trunc, Origin(),
12503 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12504 Value* arg3 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12505 root->appendNew<Value>(proc, Trunc, Origin(),
12506 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)));
12507
12508 Value* result = root->appendNew<Value>(proc, Select, Origin(),
12509 root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1),
12510 arg2,
12511 arg3);
12512
12513 PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin());
12514 keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
12515 keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
12516
12517 root->appendNewControlValue(proc, Return, Origin(), result);
12518 auto code = compileProc(proc);
12519
12520 for (auto& left : floatingPointOperands<float>()) {
12521 for (auto& right : floatingPointOperands<float>()) {
12522 float expected = operation(left.value, right.value) ? 42.5 : -66.5;
12523 CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(-66.5f)), expected));
12524 }
12525 }
12526 }
12527 { // Compare arguments and selected arguments are all different. "elseCase" is live after operation.
12528 Procedure proc;
12529 BasicBlock* root = proc.addBlock();
12530 Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12531 root->appendNew<Value>(proc, Trunc, Origin(),
12532 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
12533 Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12534 root->appendNew<Value>(proc, Trunc, Origin(),
12535 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
12536 Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12537 root->appendNew<Value>(proc, Trunc, Origin(),
12538 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12539 Value* arg3 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12540 root->appendNew<Value>(proc, Trunc, Origin(),
12541 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)));
12542
12543 Value* result = root->appendNew<Value>(proc, Select, Origin(),
12544 root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1),
12545 arg2,
12546 arg3);
12547
12548 PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin());
12549 keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister));
12550 keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
12551
12552 root->appendNewControlValue(proc, Return, Origin(), result);
12553 auto code = compileProc(proc);
12554
12555 for (auto& left : floatingPointOperands<float>()) {
12556 for (auto& right : floatingPointOperands<float>()) {
12557 float expected = operation(left.value, right.value) ? 42.5 : -66.5;
12558 CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(-66.5f)), expected));
12559 }
12560 }
12561 }
12562 { // Compare arguments and selected arguments are all different. Both cases are live after operation.
12563 Procedure proc;
12564 BasicBlock* root = proc.addBlock();
12565 Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12566 root->appendNew<Value>(proc, Trunc, Origin(),
12567 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
12568 Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12569 root->appendNew<Value>(proc, Trunc, Origin(),
12570 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
12571 Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12572 root->appendNew<Value>(proc, Trunc, Origin(),
12573 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12574 Value* arg3 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12575 root->appendNew<Value>(proc, Trunc, Origin(),
12576 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)));
12577
12578 Value* result = root->appendNew<Value>(proc, Select, Origin(),
12579 root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1),
12580 arg2,
12581 arg3);
12582
12583 PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin());
12584 keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
12585 keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister));
12586 keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
12587
12588 root->appendNewControlValue(proc, Return, Origin(), result);
12589 auto code = compileProc(proc);
12590
12591 for (auto& left : floatingPointOperands<float>()) {
12592 for (auto& right : floatingPointOperands<float>()) {
12593 float expected = operation(left.value, right.value) ? 42.5 : -66.5;
12594 CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(-66.5f)), expected));
12595 }
12596 }
12597 }
12598 { // The left argument is the same as the "elseCase" argument.
12599 Procedure proc;
12600 BasicBlock* root = proc.addBlock();
12601 Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12602 root->appendNew<Value>(proc, Trunc, Origin(),
12603 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
12604 Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12605 root->appendNew<Value>(proc, Trunc, Origin(),
12606 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
12607 Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12608 root->appendNew<Value>(proc, Trunc, Origin(),
12609 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12610
12611 root->appendNewControlValue(
12612 proc, Return, Origin(),
12613 root->appendNew<Value>(
12614 proc, Select, Origin(),
12615 root->appendNew<Value>(
12616 proc, opcode, Origin(),
12617 arg0,
12618 arg1),
12619 arg2,
12620 arg0));
12621 auto code = compileProc(proc);
12622
12623 for (auto& left : floatingPointOperands<float>()) {
12624 for (auto& right : floatingPointOperands<float>()) {
12625 float expected = operation(left.value, right.value) ? 42.5 : left.value;
12626 CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(left.value)), expected));
12627 }
12628 }
12629 }
12630 { // The left argument is the same as the "elseCase" argument. "thenCase" is live after operation.
12631 Procedure proc;
12632 BasicBlock* root = proc.addBlock();
12633 Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12634 root->appendNew<Value>(proc, Trunc, Origin(),
12635 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
12636 Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12637 root->appendNew<Value>(proc, Trunc, Origin(),
12638 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
12639 Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(),
12640 root->appendNew<Value>(proc, Trunc, Origin(),
12641 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12642
12643 Value* result = root->appendNew<Value>(proc, Select, Origin(),
12644 root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1),
12645 arg2,
12646 arg0);
12647
12648 PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin());
12649 keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister));
12650 keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
12651
12652 root->appendNewControlValue(proc, Return, Origin(), result);
12653 auto code = compileProc(proc);
12654
12655 for (auto& left : floatingPointOperands<float>()) {
12656 for (auto& right : floatingPointOperands<float>()) {
12657 float expected = operation(left.value, right.value) ? 42.5 : left.value;
12658 CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(left.value)), expected));
12659 }
12660 }
12661 }
12662}
12663
12664void testSelectFloatCompareFloatWithAliasing()
12665{
12666 testSelectFloatCompareFloat<Equal>([](float a, float b) -> bool { return a == b; });
12667 testSelectFloatCompareFloat<NotEqual>([](float a, float b) -> bool { return a != b; });
12668 testSelectFloatCompareFloat<LessThan>([](float a, float b) -> bool { return a < b; });
12669 testSelectFloatCompareFloat<GreaterThan>([](float a, float b) -> bool { return a > b; });
12670 testSelectFloatCompareFloat<LessEqual>([](float a, float b) -> bool { return a <= b; });
12671 testSelectFloatCompareFloat<GreaterEqual>([](float a, float b) -> bool { return a >= b; });
12672 testSelectFloatCompareFloat<EqualOrUnordered>([](float a, float b) -> bool { return a != a || b != b || a == b; });
12673}
12674
12675void testSelectFold(intptr_t value)
12676{
12677 Procedure proc;
12678 BasicBlock* root = proc.addBlock();
12679 root->appendNewControlValue(
12680 proc, Return, Origin(),
12681 root->appendNew<Value>(
12682 proc, Select, Origin(),
12683 root->appendNew<Value>(
12684 proc, Equal, Origin(),
12685 root->appendNew<ConstPtrValue>(proc, Origin(), value),
12686 root->appendNew<ConstPtrValue>(proc, Origin(), 42)),
12687 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12688 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
12689
12690 auto code = compileProc(proc);
12691 CHECK(invoke<intptr_t>(*code, 1, 2) == (value == 42 ? 1 : 2));
12692 CHECK(invoke<intptr_t>(*code, 642462, 32533) == (value == 42 ? 642462 : 32533));
12693}
12694
12695void testSelectInvert()
12696{
12697 Procedure proc;
12698 BasicBlock* root = proc.addBlock();
12699 root->appendNewControlValue(
12700 proc, Return, Origin(),
12701 root->appendNew<Value>(
12702 proc, Select, Origin(),
12703 root->appendNew<Value>(
12704 proc, Equal, Origin(),
12705 root->appendNew<Value>(
12706 proc, NotEqual, Origin(),
12707 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12708 root->appendNew<ConstPtrValue>(proc, Origin(), 42)),
12709 root->appendNew<Const32Value>(proc, Origin(), 0)),
12710 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
12711 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
12712
12713 auto code = compileProc(proc);
12714 CHECK(invoke<intptr_t>(*code, 42, 1, 2) == 1);
12715 CHECK(invoke<intptr_t>(*code, 42, 642462, 32533) == 642462);
12716 CHECK(invoke<intptr_t>(*code, 43, 1, 2) == 2);
12717 CHECK(invoke<intptr_t>(*code, 43, 642462, 32533) == 32533);
12718}
12719
12720void testCheckSelect()
12721{
12722 Procedure proc;
12723 if (proc.optLevel() < 1)
12724 return;
12725 BasicBlock* root = proc.addBlock();
12726
12727 CheckValue* check = root->appendNew<CheckValue>(
12728 proc, Check, Origin(),
12729 root->appendNew<Value>(
12730 proc, Add, Origin(),
12731 root->appendNew<Value>(
12732 proc, Select, Origin(),
12733 root->appendNew<Value>(
12734 proc, BitAnd, Origin(),
12735 root->appendNew<Value>(
12736 proc, Trunc, Origin(),
12737 root->appendNew<ArgumentRegValue>(
12738 proc, Origin(), GPRInfo::argumentGPR0)),
12739 root->appendNew<Const32Value>(proc, Origin(), 0xff)),
12740 root->appendNew<ConstPtrValue>(proc, Origin(), -42),
12741 root->appendNew<ConstPtrValue>(proc, Origin(), 35)),
12742 root->appendNew<ConstPtrValue>(proc, Origin(), 42)));
12743 unsigned generationCount = 0;
12744 check->setGenerator(
12745 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
12746 AllowMacroScratchRegisterUsage allowScratch(jit);
12747
12748 generationCount++;
12749 jit.move(CCallHelpers::TrustedImm32(666), GPRInfo::returnValueGPR);
12750 jit.emitFunctionEpilogue();
12751 jit.ret();
12752 });
12753
12754 root->appendNewControlValue(
12755 proc, Return, Origin(),
12756 root->appendNew<Const32Value>(proc, Origin(), 0));
12757
12758 auto code = compileProc(proc);
12759 CHECK(generationCount == 1);
12760 CHECK(invoke<int>(*code, true) == 0);
12761 CHECK(invoke<int>(*code, false) == 666);
12762}
12763
12764void testCheckSelectCheckSelect()
12765{
12766 Procedure proc;
12767 if (proc.optLevel() < 1)
12768 return;
12769 BasicBlock* root = proc.addBlock();
12770
12771 CheckValue* check = root->appendNew<CheckValue>(
12772 proc, Check, Origin(),
12773 root->appendNew<Value>(
12774 proc, Add, Origin(),
12775 root->appendNew<Value>(
12776 proc, Select, Origin(),
12777 root->appendNew<Value>(
12778 proc, BitAnd, Origin(),
12779 root->appendNew<Value>(
12780 proc, Trunc, Origin(),
12781 root->appendNew<ArgumentRegValue>(
12782 proc, Origin(), GPRInfo::argumentGPR0)),
12783 root->appendNew<Const32Value>(proc, Origin(), 0xff)),
12784 root->appendNew<ConstPtrValue>(proc, Origin(), -42),
12785 root->appendNew<ConstPtrValue>(proc, Origin(), 35)),
12786 root->appendNew<ConstPtrValue>(proc, Origin(), 42)));
12787
12788 unsigned generationCount = 0;
12789 check->setGenerator(
12790 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
12791 AllowMacroScratchRegisterUsage allowScratch(jit);
12792
12793 generationCount++;
12794 jit.move(CCallHelpers::TrustedImm32(666), GPRInfo::returnValueGPR);
12795 jit.emitFunctionEpilogue();
12796 jit.ret();
12797 });
12798
12799 CheckValue* check2 = root->appendNew<CheckValue>(
12800 proc, Check, Origin(),
12801 root->appendNew<Value>(
12802 proc, Add, Origin(),
12803 root->appendNew<Value>(
12804 proc, Select, Origin(),
12805 root->appendNew<Value>(
12806 proc, BitAnd, Origin(),
12807 root->appendNew<Value>(
12808 proc, Trunc, Origin(),
12809 root->appendNew<ArgumentRegValue>(
12810 proc, Origin(), GPRInfo::argumentGPR1)),
12811 root->appendNew<Const32Value>(proc, Origin(), 0xff)),
12812 root->appendNew<ConstPtrValue>(proc, Origin(), -43),
12813 root->appendNew<ConstPtrValue>(proc, Origin(), 36)),
12814 root->appendNew<ConstPtrValue>(proc, Origin(), 43)));
12815
12816 unsigned generationCount2 = 0;
12817 check2->setGenerator(
12818 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
12819 AllowMacroScratchRegisterUsage allowScratch(jit);
12820
12821 generationCount2++;
12822 jit.move(CCallHelpers::TrustedImm32(667), GPRInfo::returnValueGPR);
12823 jit.emitFunctionEpilogue();
12824 jit.ret();
12825 });
12826
12827 root->appendNewControlValue(
12828 proc, Return, Origin(),
12829 root->appendNew<Const32Value>(proc, Origin(), 0));
12830
12831 auto code = compileProc(proc);
12832 CHECK(generationCount == 1);
12833 CHECK(generationCount2 == 1);
12834 CHECK(invoke<int>(*code, true, true) == 0);
12835 CHECK(invoke<int>(*code, false, true) == 666);
12836 CHECK(invoke<int>(*code, true, false) == 667);
12837}
12838
12839void testCheckSelectAndCSE()
12840{
12841 Procedure proc;
12842 if (proc.optLevel() < 1)
12843 return;
12844 BasicBlock* root = proc.addBlock();
12845
12846 auto* selectValue = root->appendNew<Value>(
12847 proc, Select, Origin(),
12848 root->appendNew<Value>(
12849 proc, BitAnd, Origin(),
12850 root->appendNew<Value>(
12851 proc, Trunc, Origin(),
12852 root->appendNew<ArgumentRegValue>(
12853 proc, Origin(), GPRInfo::argumentGPR0)),
12854 root->appendNew<Const32Value>(proc, Origin(), 0xff)),
12855 root->appendNew<ConstPtrValue>(proc, Origin(), -42),
12856 root->appendNew<ConstPtrValue>(proc, Origin(), 35));
12857
12858 auto* constant = root->appendNew<ConstPtrValue>(proc, Origin(), 42);
12859 auto* addValue = root->appendNew<Value>(proc, Add, Origin(), selectValue, constant);
12860
12861 CheckValue* check = root->appendNew<CheckValue>(proc, Check, Origin(), addValue);
12862 unsigned generationCount = 0;
12863 check->setGenerator(
12864 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
12865 AllowMacroScratchRegisterUsage allowScratch(jit);
12866
12867 generationCount++;
12868 jit.move(CCallHelpers::TrustedImm32(666), GPRInfo::returnValueGPR);
12869 jit.emitFunctionEpilogue();
12870 jit.ret();
12871 });
12872
12873 auto* addValue2 = root->appendNew<Value>(proc, Add, Origin(), selectValue, constant);
12874
12875 root->appendNewControlValue(
12876 proc, Return, Origin(),
12877 root->appendNew<Value>(proc, Add, Origin(), addValue, addValue2));
12878
12879 auto code = compileProc(proc);
12880 CHECK(generationCount == 1);
12881 CHECK(invoke<int>(*code, true) == 0);
12882 CHECK(invoke<int>(*code, false) == 666);
12883}
12884
12885double b3Pow(double x, int y)
12886{
12887 if (y < 0 || y > 1000)
12888 return pow(x, y);
12889 double result = 1;
12890 while (y) {
12891 if (y & 1)
12892 result *= x;
12893 x *= x;
12894 y >>= 1;
12895 }
12896 return result;
12897}
12898
12899void testPowDoubleByIntegerLoop(double xOperand, int32_t yOperand)
12900{
12901 Procedure proc;
12902 BasicBlock* root = proc.addBlock();
12903
12904 Value* x = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
12905 Value* y = root->appendNew<Value>(proc, Trunc, Origin(),
12906 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
12907 auto result = powDoubleInt32(proc, root, Origin(), x, y);
12908 BasicBlock* continuation = result.first;
12909 continuation->appendNewControlValue(proc, Return, Origin(), result.second);
12910
12911 CHECK(isIdentical(compileAndRun<double>(proc, xOperand, yOperand), b3Pow(xOperand, yOperand)));
12912}
12913
12914void testTruncOrHigh()
12915{
12916 Procedure proc;
12917 BasicBlock* root = proc.addBlock();
12918
12919 root->appendNewControlValue(
12920 proc, Return, Origin(),
12921 root->appendNew<Value>(
12922 proc, Trunc, Origin(),
12923 root->appendNew<Value>(
12924 proc, BitOr, Origin(),
12925 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12926 root->appendNew<Const64Value>(proc, Origin(), 0x100000000))));
12927
12928 int64_t value = 0x123456781234;
12929 CHECK(compileAndRun<int>(proc, value) == 0x56781234);
12930}
12931
12932void testTruncOrLow()
12933{
12934 Procedure proc;
12935 BasicBlock* root = proc.addBlock();
12936
12937 root->appendNewControlValue(
12938 proc, Return, Origin(),
12939 root->appendNew<Value>(
12940 proc, Trunc, Origin(),
12941 root->appendNew<Value>(
12942 proc, BitOr, Origin(),
12943 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12944 root->appendNew<Const64Value>(proc, Origin(), 0x1000000))));
12945
12946 int64_t value = 0x123456781234;
12947 CHECK(compileAndRun<int>(proc, value) == 0x57781234);
12948}
12949
12950void testBitAndOrHigh()
12951{
12952 Procedure proc;
12953 BasicBlock* root = proc.addBlock();
12954
12955 root->appendNewControlValue(
12956 proc, Return, Origin(),
12957 root->appendNew<Value>(
12958 proc, BitAnd, Origin(),
12959 root->appendNew<Value>(
12960 proc, BitOr, Origin(),
12961 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12962 root->appendNew<Const64Value>(proc, Origin(), 0x8)),
12963 root->appendNew<Const64Value>(proc, Origin(), 0x777777777777)));
12964
12965 int64_t value = 0x123456781234;
12966 CHECK(compileAndRun<int64_t>(proc, value) == 0x123456701234ll);
12967}
12968
12969void testBitAndOrLow()
12970{
12971 Procedure proc;
12972 BasicBlock* root = proc.addBlock();
12973
12974 root->appendNewControlValue(
12975 proc, Return, Origin(),
12976 root->appendNew<Value>(
12977 proc, BitAnd, Origin(),
12978 root->appendNew<Value>(
12979 proc, BitOr, Origin(),
12980 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
12981 root->appendNew<Const64Value>(proc, Origin(), 0x1)),
12982 root->appendNew<Const64Value>(proc, Origin(), 0x777777777777)));
12983
12984 int64_t value = 0x123456781234;
12985 CHECK(compileAndRun<int64_t>(proc, value) == 0x123456701235ll);
12986}
12987
12988void testBranch64Equal(int64_t left, int64_t right)
12989{
12990 Procedure proc;
12991 BasicBlock* root = proc.addBlock();
12992 BasicBlock* thenCase = proc.addBlock();
12993 BasicBlock* elseCase = proc.addBlock();
12994
12995 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
12996 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
12997 root->appendNewControlValue(
12998 proc, Branch, Origin(),
12999 root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2),
13000 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
13001
13002 bool trueResult = true;
13003 thenCase->appendNewControlValue(
13004 proc, Return, Origin(),
13005 thenCase->appendNew<MemoryValue>(
13006 proc, Load8Z, Origin(),
13007 thenCase->appendNew<ConstPtrValue>(proc, Origin(), &trueResult)));
13008
13009 bool elseResult = false;
13010 elseCase->appendNewControlValue(
13011 proc, Return, Origin(),
13012 elseCase->appendNew<MemoryValue>(
13013 proc, Load8Z, Origin(),
13014 elseCase->appendNew<ConstPtrValue>(proc, Origin(), &elseResult)));
13015
13016 CHECK(compileAndRun<bool>(proc, left, right) == (left == right));
13017}
13018
13019void testBranch64EqualImm(int64_t left, int64_t right)
13020{
13021 Procedure proc;
13022 BasicBlock* root = proc.addBlock();
13023 BasicBlock* thenCase = proc.addBlock();
13024 BasicBlock* elseCase = proc.addBlock();
13025
13026 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13027 Value* arg2 = root->appendNew<ConstPtrValue>(proc, Origin(), right);
13028 root->appendNewControlValue(
13029 proc, Branch, Origin(),
13030 root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2),
13031 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
13032
13033 bool trueResult = true;
13034 thenCase->appendNewControlValue(
13035 proc, Return, Origin(),
13036 thenCase->appendNew<MemoryValue>(
13037 proc, Load8Z, Origin(),
13038 thenCase->appendNew<ConstPtrValue>(proc, Origin(), &trueResult)));
13039
13040 bool elseResult = false;
13041 elseCase->appendNewControlValue(
13042 proc, Return, Origin(),
13043 elseCase->appendNew<MemoryValue>(
13044 proc, Load8Z, Origin(),
13045 elseCase->appendNew<ConstPtrValue>(proc, Origin(), &elseResult)));
13046
13047 CHECK(compileAndRun<bool>(proc, left) == (left == right));
13048}
13049
13050void testBranch64EqualMem(int64_t left, int64_t right)
13051{
13052 Procedure proc;
13053 BasicBlock* root = proc.addBlock();
13054 BasicBlock* thenCase = proc.addBlock();
13055 BasicBlock* elseCase = proc.addBlock();
13056
13057 Value* arg1 = root->appendNew<MemoryValue>(
13058 proc, Load, pointerType(), Origin(),
13059 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
13060 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
13061 root->appendNewControlValue(
13062 proc, Branch, Origin(),
13063 root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2),
13064 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
13065
13066 bool trueResult = true;
13067 thenCase->appendNewControlValue(
13068 proc, Return, Origin(),
13069 thenCase->appendNew<MemoryValue>(
13070 proc, Load8Z, Origin(),
13071 thenCase->appendNew<ConstPtrValue>(proc, Origin(), &trueResult)));
13072
13073 bool elseResult = false;
13074 elseCase->appendNewControlValue(
13075 proc, Return, Origin(),
13076 elseCase->appendNew<MemoryValue>(
13077 proc, Load8Z, Origin(),
13078 elseCase->appendNew<ConstPtrValue>(proc, Origin(), &elseResult)));
13079
13080 CHECK(compileAndRun<bool>(proc, &left, right) == (left == right));
13081}
13082
13083void testBranch64EqualMemImm(int64_t left, int64_t right)
13084{
13085 Procedure proc;
13086 BasicBlock* root = proc.addBlock();
13087 BasicBlock* thenCase = proc.addBlock();
13088 BasicBlock* elseCase = proc.addBlock();
13089
13090 Value* arg1 = root->appendNew<MemoryValue>(
13091 proc, Load, pointerType(), Origin(),
13092 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
13093 Value* arg2 = root->appendNew<ConstPtrValue>(proc, Origin(), right);
13094 root->appendNewControlValue(
13095 proc, Branch, Origin(),
13096 root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2),
13097 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
13098
13099 bool trueResult = true;
13100 thenCase->appendNewControlValue(
13101 proc, Return, Origin(),
13102 thenCase->appendNew<MemoryValue>(
13103 proc, Load8Z, Origin(),
13104 thenCase->appendNew<ConstPtrValue>(proc, Origin(), &trueResult)));
13105
13106 bool elseResult = false;
13107 elseCase->appendNewControlValue(
13108 proc, Return, Origin(),
13109 elseCase->appendNew<MemoryValue>(
13110 proc, Load8Z, Origin(),
13111 elseCase->appendNew<ConstPtrValue>(proc, Origin(), &elseResult)));
13112
13113 CHECK(compileAndRun<bool>(proc, &left) == (left == right));
13114}
13115
13116void testStore8Load8Z(int32_t value)
13117{
13118 Procedure proc;
13119 BasicBlock* root = proc.addBlock();
13120
13121 int8_t byte;
13122 Value* ptr = root->appendNew<ConstPtrValue>(proc, Origin(), &byte);
13123
13124 root->appendNew<MemoryValue>(
13125 proc, Store8, Origin(),
13126 root->appendNew<Value>(
13127 proc, Trunc, Origin(),
13128 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
13129 ptr);
13130
13131 root->appendNewControlValue(
13132 proc, Return, Origin(),
13133 root->appendNew<MemoryValue>(proc, Load8Z, Origin(), ptr));
13134
13135 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<uint8_t>(value));
13136}
13137
13138void testStore16Load16Z(int32_t value)
13139{
13140 Procedure proc;
13141 BasicBlock* root = proc.addBlock();
13142
13143 int16_t byte;
13144 Value* ptr = root->appendNew<ConstPtrValue>(proc, Origin(), &byte);
13145
13146 root->appendNew<MemoryValue>(
13147 proc, Store16, Origin(),
13148 root->appendNew<Value>(
13149 proc, Trunc, Origin(),
13150 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
13151 ptr);
13152
13153 root->appendNewControlValue(
13154 proc, Return, Origin(),
13155 root->appendNew<MemoryValue>(proc, Load16Z, Origin(), ptr));
13156
13157 CHECK(compileAndRun<int32_t>(proc, value) == static_cast<uint16_t>(value));
13158}
13159
13160void testSShrShl32(int32_t value, int32_t sshrAmount, int32_t shlAmount)
13161{
13162 Procedure proc;
13163 BasicBlock* root = proc.addBlock();
13164
13165 root->appendNewControlValue(
13166 proc, Return, Origin(),
13167 root->appendNew<Value>(
13168 proc, SShr, Origin(),
13169 root->appendNew<Value>(
13170 proc, Shl, Origin(),
13171 root->appendNew<Value>(
13172 proc, Trunc, Origin(),
13173 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
13174 root->appendNew<Const32Value>(proc, Origin(), shlAmount)),
13175 root->appendNew<Const32Value>(proc, Origin(), sshrAmount)));
13176
13177 CHECK(
13178 compileAndRun<int32_t>(proc, value)
13179 == ((value << (shlAmount & 31)) >> (sshrAmount & 31)));
13180}
13181
13182void testSShrShl64(int64_t value, int32_t sshrAmount, int32_t shlAmount)
13183{
13184 Procedure proc;
13185 BasicBlock* root = proc.addBlock();
13186
13187 root->appendNewControlValue(
13188 proc, Return, Origin(),
13189 root->appendNew<Value>(
13190 proc, SShr, Origin(),
13191 root->appendNew<Value>(
13192 proc, Shl, Origin(),
13193 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
13194 root->appendNew<Const32Value>(proc, Origin(), shlAmount)),
13195 root->appendNew<Const32Value>(proc, Origin(), sshrAmount)));
13196
13197 CHECK(
13198 compileAndRun<int64_t>(proc, value)
13199 == ((value << (shlAmount & 63)) >> (sshrAmount & 63)));
13200}
13201
13202template<typename T>
13203void testRotR(T valueInt, int32_t shift)
13204{
13205 Procedure proc;
13206 BasicBlock* root = proc.addBlock();
13207
13208 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13209 if (sizeof(T) == 4)
13210 value = root->appendNew<Value>(proc, Trunc, Origin(), value);
13211
13212 Value* ammount = root->appendNew<Value>(proc, Trunc, Origin(),
13213 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
13214 root->appendNewControlValue(proc, Return, Origin(),
13215 root->appendNew<Value>(proc, RotR, Origin(), value, ammount));
13216
13217 CHECK_EQ(compileAndRun<T>(proc, valueInt, shift), rotateRight(valueInt, shift));
13218}
13219
13220template<typename T>
13221void testRotL(T valueInt, int32_t shift)
13222{
13223 Procedure proc;
13224 BasicBlock* root = proc.addBlock();
13225
13226 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13227 if (sizeof(T) == 4)
13228 value = root->appendNew<Value>(proc, Trunc, Origin(), value);
13229
13230 Value* ammount = root->appendNew<Value>(proc, Trunc, Origin(),
13231 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
13232 root->appendNewControlValue(proc, Return, Origin(),
13233 root->appendNew<Value>(proc, RotL, Origin(), value, ammount));
13234
13235 CHECK_EQ(compileAndRun<T>(proc, valueInt, shift), rotateLeft(valueInt, shift));
13236}
13237
13238template<typename T>
13239void testRotRWithImmShift(T valueInt, int32_t shift)
13240{
13241 Procedure proc;
13242 BasicBlock* root = proc.addBlock();
13243
13244 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13245 if (sizeof(T) == 4)
13246 value = root->appendNew<Value>(proc, Trunc, Origin(), value);
13247
13248 Value* ammount = root->appendIntConstant(proc, Origin(), Int32, shift);
13249 root->appendNewControlValue(proc, Return, Origin(),
13250 root->appendNew<Value>(proc, RotR, Origin(), value, ammount));
13251
13252 CHECK_EQ(compileAndRun<T>(proc, valueInt, shift), rotateRight(valueInt, shift));
13253}
13254
13255template<typename T>
13256void testRotLWithImmShift(T valueInt, int32_t shift)
13257{
13258 Procedure proc;
13259 BasicBlock* root = proc.addBlock();
13260
13261 Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13262 if (sizeof(T) == 4)
13263 value = root->appendNew<Value>(proc, Trunc, Origin(), value);
13264
13265 Value* ammount = root->appendIntConstant(proc, Origin(), Int32, shift);
13266 root->appendNewControlValue(proc, Return, Origin(),
13267 root->appendNew<Value>(proc, RotL, Origin(), value, ammount));
13268
13269 CHECK_EQ(compileAndRun<T>(proc, valueInt, shift), rotateLeft(valueInt, shift));
13270}
13271
13272template<typename T>
13273void testComputeDivisionMagic(T value, T magicMultiplier, unsigned shift)
13274{
13275 DivisionMagic<T> magic = computeDivisionMagic(value);
13276 CHECK(magic.magicMultiplier == magicMultiplier);
13277 CHECK(magic.shift == shift);
13278}
13279
13280void testTrivialInfiniteLoop()
13281{
13282 Procedure proc;
13283 BasicBlock* root = proc.addBlock();
13284 BasicBlock* loop = proc.addBlock();
13285 root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop));
13286 loop->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop));
13287
13288 compileProc(proc);
13289}
13290
13291void testFoldPathEqual()
13292{
13293 Procedure proc;
13294 BasicBlock* root = proc.addBlock();
13295 BasicBlock* thenBlock = proc.addBlock();
13296 BasicBlock* elseBlock = proc.addBlock();
13297
13298 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13299
13300 root->appendNewControlValue(
13301 proc, Branch, Origin(), arg, FrequentedBlock(thenBlock), FrequentedBlock(elseBlock));
13302
13303 thenBlock->appendNewControlValue(
13304 proc, Return, Origin(),
13305 thenBlock->appendNew<Value>(
13306 proc, Equal, Origin(), arg, thenBlock->appendNew<ConstPtrValue>(proc, Origin(), 0)));
13307
13308 elseBlock->appendNewControlValue(
13309 proc, Return, Origin(),
13310 elseBlock->appendNew<Value>(
13311 proc, Equal, Origin(), arg, elseBlock->appendNew<ConstPtrValue>(proc, Origin(), 0)));
13312
13313 auto code = compileProc(proc);
13314 CHECK(invoke<intptr_t>(*code, 0) == 1);
13315 CHECK(invoke<intptr_t>(*code, 1) == 0);
13316 CHECK(invoke<intptr_t>(*code, 42) == 0);
13317}
13318
13319void testLShiftSelf32()
13320{
13321 Procedure proc;
13322 BasicBlock* root = proc.addBlock();
13323 Value* arg = root->appendNew<Value>(
13324 proc, Trunc, Origin(),
13325 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
13326 root->appendNewControlValue(
13327 proc, Return, Origin(),
13328 root->appendNew<Value>(proc, Shl, Origin(), arg, arg));
13329
13330 auto code = compileProc(proc);
13331
13332 auto check = [&] (int32_t value) {
13333 CHECK(invoke<int32_t>(*code, value) == value << (value & 31));
13334 };
13335
13336 check(0);
13337 check(1);
13338 check(31);
13339 check(32);
13340}
13341
13342void testRShiftSelf32()
13343{
13344 Procedure proc;
13345 BasicBlock* root = proc.addBlock();
13346 Value* arg = root->appendNew<Value>(
13347 proc, Trunc, Origin(),
13348 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
13349 root->appendNewControlValue(
13350 proc, Return, Origin(),
13351 root->appendNew<Value>(proc, SShr, Origin(), arg, arg));
13352
13353 auto code = compileProc(proc);
13354
13355 auto check = [&] (int32_t value) {
13356 CHECK(invoke<int32_t>(*code, value) == value >> (value & 31));
13357 };
13358
13359 check(0);
13360 check(1);
13361 check(31);
13362 check(32);
13363}
13364
13365void testURShiftSelf32()
13366{
13367 Procedure proc;
13368 BasicBlock* root = proc.addBlock();
13369 Value* arg = root->appendNew<Value>(
13370 proc, Trunc, Origin(),
13371 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
13372 root->appendNewControlValue(
13373 proc, Return, Origin(),
13374 root->appendNew<Value>(proc, ZShr, Origin(), arg, arg));
13375
13376 auto code = compileProc(proc);
13377
13378 auto check = [&] (uint32_t value) {
13379 CHECK(invoke<uint32_t>(*code, value) == value >> (value & 31));
13380 };
13381
13382 check(0);
13383 check(1);
13384 check(31);
13385 check(32);
13386}
13387
13388void testLShiftSelf64()
13389{
13390 Procedure proc;
13391 BasicBlock* root = proc.addBlock();
13392 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13393 root->appendNewControlValue(
13394 proc, Return, Origin(),
13395 root->appendNew<Value>(
13396 proc, Shl, Origin(), arg, root->appendNew<Value>(proc, Trunc, Origin(), arg)));
13397
13398 auto code = compileProc(proc);
13399
13400 auto check = [&] (int64_t value) {
13401 CHECK(invoke<int64_t>(*code, value) == value << (value & 63));
13402 };
13403
13404 check(0);
13405 check(1);
13406 check(31);
13407 check(32);
13408 check(63);
13409 check(64);
13410}
13411
13412void testRShiftSelf64()
13413{
13414 Procedure proc;
13415 BasicBlock* root = proc.addBlock();
13416 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13417 root->appendNewControlValue(
13418 proc, Return, Origin(),
13419 root->appendNew<Value>(
13420 proc, SShr, Origin(), arg, root->appendNew<Value>(proc, Trunc, Origin(), arg)));
13421
13422 auto code = compileProc(proc);
13423
13424 auto check = [&] (int64_t value) {
13425 CHECK(invoke<int64_t>(*code, value) == value >> (value & 63));
13426 };
13427
13428 check(0);
13429 check(1);
13430 check(31);
13431 check(32);
13432 check(63);
13433 check(64);
13434}
13435
13436void testURShiftSelf64()
13437{
13438 Procedure proc;
13439 BasicBlock* root = proc.addBlock();
13440 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13441 root->appendNewControlValue(
13442 proc, Return, Origin(),
13443 root->appendNew<Value>(
13444 proc, ZShr, Origin(), arg, root->appendNew<Value>(proc, Trunc, Origin(), arg)));
13445
13446 auto code = compileProc(proc);
13447
13448 auto check = [&] (uint64_t value) {
13449 CHECK(invoke<uint64_t>(*code, value) == value >> (value & 63));
13450 };
13451
13452 check(0);
13453 check(1);
13454 check(31);
13455 check(32);
13456 check(63);
13457 check(64);
13458}
13459
13460void testPatchpointDoubleRegs()
13461{
13462 Procedure proc;
13463 BasicBlock* root = proc.addBlock();
13464
13465 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
13466
13467 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin());
13468 patchpoint->append(arg, ValueRep(FPRInfo::fpRegT0));
13469 patchpoint->resultConstraint = ValueRep(FPRInfo::fpRegT0);
13470
13471 unsigned numCalls = 0;
13472 patchpoint->setGenerator(
13473 [&] (CCallHelpers&, const StackmapGenerationParams&) {
13474 numCalls++;
13475 });
13476
13477 root->appendNewControlValue(proc, Return, Origin(), patchpoint);
13478
13479 auto code = compileProc(proc);
13480 CHECK(numCalls == 1);
13481 CHECK(invoke<double>(*code, 42.5) == 42.5);
13482}
13483
13484void testSpillDefSmallerThanUse()
13485{
13486 Procedure proc;
13487 BasicBlock* root = proc.addBlock();
13488
13489 // Move32.
13490 Value* arg32 = root->appendNew<Value>(
13491 proc, Trunc, Origin(),
13492 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
13493 Value* arg64 = root->appendNew<Value>(proc, ZExt32, Origin(), arg32);
13494
13495 // Make sure arg64 is on the stack.
13496 PatchpointValue* forceSpill = root->appendNew<PatchpointValue>(proc, Int64, Origin());
13497 RegisterSet clobberSet = RegisterSet::allGPRs();
13498 clobberSet.exclude(RegisterSet::stackRegisters());
13499 clobberSet.exclude(RegisterSet::reservedHardwareRegisters());
13500 clobberSet.clear(GPRInfo::returnValueGPR); // Force the return value for aliasing below.
13501 forceSpill->clobberLate(clobberSet);
13502 forceSpill->setGenerator(
13503 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
13504 AllowMacroScratchRegisterUsage allowScratch(jit);
13505 jit.xor64(params[0].gpr(), params[0].gpr());
13506 });
13507
13508 // On x86, Sub admit an address for any operand. If it uses the stack, the top bits must be zero.
13509 Value* result = root->appendNew<Value>(proc, Sub, Origin(), forceSpill, arg64);
13510 root->appendNewControlValue(proc, Return, Origin(), result);
13511
13512 auto code = compileProc(proc);
13513 CHECK(invoke<int64_t>(*code, 0xffffffff00000000) == 0);
13514}
13515
13516void testSpillUseLargerThanDef()
13517{
13518 Procedure proc;
13519 BasicBlock* root = proc.addBlock();
13520 BasicBlock* thenCase = proc.addBlock();
13521 BasicBlock* elseCase = proc.addBlock();
13522 BasicBlock* tail = proc.addBlock();
13523
13524 RegisterSet clobberSet = RegisterSet::allGPRs();
13525 clobberSet.exclude(RegisterSet::stackRegisters());
13526 clobberSet.exclude(RegisterSet::reservedHardwareRegisters());
13527
13528 Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13529 Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
13530 root->appendNewControlValue(
13531 proc, Branch, Origin(),
13532 root->appendNew<Value>(
13533 proc, Trunc, Origin(),
13534 condition),
13535 FrequentedBlock(thenCase), FrequentedBlock(elseCase));
13536
13537 Value* truncated = thenCase->appendNew<Value>(proc, ZExt32, Origin(),
13538 thenCase->appendNew<Value>(proc, Trunc, Origin(), argument));
13539 UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>(proc, Origin(), truncated);
13540 thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
13541
13542 UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>(proc, Origin(), argument);
13543 elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail));
13544
13545 for (unsigned i = 0; i < 100; ++i) {
13546 PatchpointValue* preventTailDuplication = tail->appendNew<PatchpointValue>(proc, Void, Origin());
13547 preventTailDuplication->clobberLate(clobberSet);
13548 preventTailDuplication->setGenerator([] (CCallHelpers&, const StackmapGenerationParams&) { });
13549 }
13550
13551 PatchpointValue* forceSpill = tail->appendNew<PatchpointValue>(proc, Void, Origin());
13552 forceSpill->clobberLate(clobberSet);
13553 forceSpill->setGenerator(
13554 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
13555 AllowMacroScratchRegisterUsage allowScratch(jit);
13556 clobberSet.forEach([&] (Reg reg) {
13557 jit.move(CCallHelpers::TrustedImm64(0xffffffffffffffff), reg.gpr());
13558 });
13559 });
13560
13561 Value* phi = tail->appendNew<Value>(proc, Phi, Int64, Origin());
13562 thenResult->setPhi(phi);
13563 elseResult->setPhi(phi);
13564 tail->appendNewControlValue(proc, Return, Origin(), phi);
13565
13566 auto code = compileProc(proc);
13567 CHECK(invoke<uint64_t>(*code, 1, 0xffffffff00000000) == 0);
13568 CHECK(invoke<uint64_t>(*code, 0, 0xffffffff00000000) == 0xffffffff00000000);
13569
13570 // A second time since the previous run is still on the stack.
13571 CHECK(invoke<uint64_t>(*code, 1, 0xffffffff00000000) == 0);
13572
13573}
13574
13575void testLateRegister()
13576{
13577 Procedure proc;
13578
13579 if (!proc.optLevel()) {
13580 // FIXME: Make O0 handle such situations:
13581 // https://bugs.webkit.org/show_bug.cgi?id=194633
13582 return;
13583 }
13584
13585 BasicBlock* root = proc.addBlock();
13586
13587 // This works by making all but 1 register be input to the first patchpoint as LateRegister.
13588 // The other 1 register is just a regular Register input. We assert our result is the regular
13589 // register input. There would be no other way for the register allocator to arrange things
13590 // because LateRegister interferes with the result.
13591 // Then, the second patchpoint takes the result of the first as an argument and asks for
13592 // it in a register that was a LateRegister. This is to incentivize the register allocator
13593 // to use that LateRegister as the result for the first patchpoint. But of course it can not do that.
13594 // So it must issue a mov after the first patchpoint from the first's result into the second's input.
13595
13596 RegisterSet regs = RegisterSet::allGPRs();
13597 regs.exclude(RegisterSet::stackRegisters());
13598 regs.exclude(RegisterSet::reservedHardwareRegisters());
13599 Vector<Value*> lateUseArgs;
13600 unsigned result = 0;
13601 for (GPRReg reg = CCallHelpers::firstRegister(); reg <= CCallHelpers::lastRegister(); reg = CCallHelpers::nextRegister(reg)) {
13602 if (!regs.get(reg))
13603 continue;
13604 result++;
13605 if (reg == GPRInfo::regT0)
13606 continue;
13607 Value* value = root->appendNew<Const64Value>(proc, Origin(), 1);
13608 lateUseArgs.append(value);
13609 }
13610 Value* regularUse = root->appendNew<Const64Value>(proc, Origin(), 1);
13611 PatchpointValue* firstPatchpoint = root->appendNew<PatchpointValue>(proc, Int64, Origin());
13612 {
13613 unsigned i = 0;
13614 for (GPRReg reg = CCallHelpers::firstRegister(); reg <= CCallHelpers::lastRegister(); reg = CCallHelpers::nextRegister(reg)) {
13615 if (!regs.get(reg))
13616 continue;
13617 if (reg == GPRInfo::regT0)
13618 continue;
13619 Value* value = lateUseArgs[i++];
13620 firstPatchpoint->append(value, ValueRep::lateReg(reg));
13621 }
13622 firstPatchpoint->append(regularUse, ValueRep::reg(GPRInfo::regT0));
13623 }
13624
13625 firstPatchpoint->setGenerator(
13626 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
13627 AllowMacroScratchRegisterUsage allowScratch(jit);
13628 CHECK(params[0].gpr() == GPRInfo::regT0);
13629 // Note that regT0 should also start off as 1, so we're implicitly starting our add with 1, which is also an argument.
13630 unsigned skipped = 0;
13631 for (unsigned i = 1; i < params.size(); i++) {
13632 if (params[i].gpr() == params[0].gpr()) {
13633 skipped = i;
13634 continue;
13635 }
13636 jit.add64(params[i].gpr(), params[0].gpr());
13637 }
13638 CHECK(!!skipped);
13639 });
13640
13641 PatchpointValue* secondPatchpoint = root->appendNew<PatchpointValue>(proc, Int64, Origin());
13642 secondPatchpoint->append(firstPatchpoint, ValueRep::reg(GPRInfo::regT1));
13643 secondPatchpoint->setGenerator(
13644 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
13645 AllowMacroScratchRegisterUsage allowScratch(jit);
13646 CHECK(params[1].gpr() == GPRInfo::regT1);
13647 jit.nop();
13648 jit.nop();
13649 jit.move(params[1].gpr(), params[0].gpr());
13650 jit.nop();
13651 jit.nop();
13652 });
13653 root->appendNewControlValue(proc, Return, Origin(), secondPatchpoint);
13654
13655 auto code = compileProc(proc);
13656 CHECK(invoke<uint64_t>(*code) == result);
13657}
13658
13659void interpreterPrint(Vector<intptr_t>* stream, intptr_t value)
13660{
13661 stream->append(value);
13662}
13663
13664void testInterpreter()
13665{
13666 // This implements a silly interpreter to test building custom switch statements using
13667 // Patchpoint.
13668
13669 Procedure proc;
13670
13671 BasicBlock* root = proc.addBlock();
13672 BasicBlock* dispatch = proc.addBlock();
13673 BasicBlock* addToDataPointer = proc.addBlock();
13674 BasicBlock* addToCodePointer = proc.addBlock();
13675 BasicBlock* addToCodePointerTaken = proc.addBlock();
13676 BasicBlock* addToCodePointerNotTaken = proc.addBlock();
13677 BasicBlock* addToData = proc.addBlock();
13678 BasicBlock* print = proc.addBlock();
13679 BasicBlock* stop = proc.addBlock();
13680
13681 Variable* dataPointer = proc.addVariable(pointerType());
13682 Variable* codePointer = proc.addVariable(pointerType());
13683
13684 root->appendNew<VariableValue>(
13685 proc, Set, Origin(), dataPointer,
13686 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
13687 root->appendNew<VariableValue>(
13688 proc, Set, Origin(), codePointer,
13689 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
13690 Value* context = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
13691 root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch));
13692
13693 // NOTE: It's totally valid for this patchpoint to be tail-duplicated.
13694 Value* codePointerValue =
13695 dispatch->appendNew<VariableValue>(proc, B3::Get, Origin(), codePointer);
13696 Value* opcode = dispatch->appendNew<MemoryValue>(
13697 proc, Load, pointerType(), Origin(), codePointerValue);
13698 PatchpointValue* polyJump = dispatch->appendNew<PatchpointValue>(proc, Void, Origin());
13699 polyJump->effects = Effects();
13700 polyJump->effects.terminal = true;
13701 polyJump->appendSomeRegister(opcode);
13702 polyJump->clobber(RegisterSet::macroScratchRegisters());
13703 polyJump->numGPScratchRegisters = 2;
13704 dispatch->appendSuccessor(FrequentedBlock(addToDataPointer));
13705 dispatch->appendSuccessor(FrequentedBlock(addToCodePointer));
13706 dispatch->appendSuccessor(FrequentedBlock(addToData));
13707 dispatch->appendSuccessor(FrequentedBlock(print));
13708 dispatch->appendSuccessor(FrequentedBlock(stop));
13709
13710 // Our "opcodes".
13711 static const intptr_t AddDP = 0;
13712 static const intptr_t AddCP = 1;
13713 static const intptr_t Add = 2;
13714 static const intptr_t Print = 3;
13715 static const intptr_t Stop = 4;
13716
13717 polyJump->setGenerator(
13718 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
13719 AllowMacroScratchRegisterUsage allowScratch(jit);
13720 Vector<Box<CCallHelpers::Label>> labels = params.successorLabels();
13721
13722 MacroAssemblerCodePtr<B3CompilationPtrTag>* jumpTable = bitwise_cast<MacroAssemblerCodePtr<B3CompilationPtrTag>*>(
13723 params.proc().addDataSection(sizeof(MacroAssemblerCodePtr<B3CompilationPtrTag>) * labels.size()));
13724
13725 GPRReg scratch = params.gpScratch(0);
13726
13727 jit.move(CCallHelpers::TrustedImmPtr(jumpTable), scratch);
13728 jit.load64(CCallHelpers::BaseIndex(scratch, params[0].gpr(), CCallHelpers::timesPtr()), scratch);
13729 jit.jump(scratch, B3CompilationPtrTag);
13730
13731 jit.addLinkTask(
13732 [&, jumpTable, labels] (LinkBuffer& linkBuffer) {
13733 for (unsigned i = labels.size(); i--;)
13734 jumpTable[i] = linkBuffer.locationOf<B3CompilationPtrTag>(*labels[i]);
13735 });
13736 });
13737
13738 // AddDP <operand>: adds <operand> to DP.
13739 codePointerValue =
13740 addToDataPointer->appendNew<VariableValue>(proc, B3::Get, Origin(), codePointer);
13741 addToDataPointer->appendNew<VariableValue>(
13742 proc, Set, Origin(), dataPointer,
13743 addToDataPointer->appendNew<Value>(
13744 proc, B3::Add, Origin(),
13745 addToDataPointer->appendNew<VariableValue>(proc, B3::Get, Origin(), dataPointer),
13746 addToDataPointer->appendNew<Value>(
13747 proc, Mul, Origin(),
13748 addToDataPointer->appendNew<MemoryValue>(
13749 proc, Load, pointerType(), Origin(), codePointerValue, static_cast<int32_t>(sizeof(intptr_t))),
13750 addToDataPointer->appendIntConstant(
13751 proc, Origin(), pointerType(), sizeof(intptr_t)))));
13752 addToDataPointer->appendNew<VariableValue>(
13753 proc, Set, Origin(), codePointer,
13754 addToDataPointer->appendNew<Value>(
13755 proc, B3::Add, Origin(), codePointerValue,
13756 addToDataPointer->appendIntConstant(
13757 proc, Origin(), pointerType(), sizeof(intptr_t) * 2)));
13758 addToDataPointer->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch));
13759
13760 // AddCP <operand>: adds <operand> to CP if the current value at DP is non-zero, otherwise
13761 // falls through normally.
13762 codePointerValue =
13763 addToCodePointer->appendNew<VariableValue>(proc, B3::Get, Origin(), codePointer);
13764 Value* dataPointerValue =
13765 addToCodePointer->appendNew<VariableValue>(proc, B3::Get, Origin(), dataPointer);
13766 addToCodePointer->appendNewControlValue(
13767 proc, Branch, Origin(),
13768 addToCodePointer->appendNew<MemoryValue>(
13769 proc, Load, pointerType(), Origin(), dataPointerValue),
13770 FrequentedBlock(addToCodePointerTaken), FrequentedBlock(addToCodePointerNotTaken));
13771 addToCodePointerTaken->appendNew<VariableValue>(
13772 proc, Set, Origin(), codePointer,
13773 addToCodePointerTaken->appendNew<Value>(
13774 proc, B3::Add, Origin(), codePointerValue,
13775 addToCodePointerTaken->appendNew<Value>(
13776 proc, Mul, Origin(),
13777 addToCodePointerTaken->appendNew<MemoryValue>(
13778 proc, Load, pointerType(), Origin(), codePointerValue, static_cast<int32_t>(sizeof(intptr_t))),
13779 addToCodePointerTaken->appendIntConstant(
13780 proc, Origin(), pointerType(), sizeof(intptr_t)))));
13781 addToCodePointerTaken->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch));
13782 addToCodePointerNotTaken->appendNew<VariableValue>(
13783 proc, Set, Origin(), codePointer,
13784 addToCodePointerNotTaken->appendNew<Value>(
13785 proc, B3::Add, Origin(), codePointerValue,
13786 addToCodePointerNotTaken->appendIntConstant(
13787 proc, Origin(), pointerType(), sizeof(intptr_t) * 2)));
13788 addToCodePointerNotTaken->appendNewControlValue(
13789 proc, Jump, Origin(), FrequentedBlock(dispatch));
13790
13791 // Add <operand>: adds <operand> to the slot pointed to by DP.
13792 codePointerValue = addToData->appendNew<VariableValue>(proc, B3::Get, Origin(), codePointer);
13793 dataPointerValue = addToData->appendNew<VariableValue>(proc, B3::Get, Origin(), dataPointer);
13794 addToData->appendNew<MemoryValue>(
13795 proc, Store, Origin(),
13796 addToData->appendNew<Value>(
13797 proc, B3::Add, Origin(),
13798 addToData->appendNew<MemoryValue>(
13799 proc, Load, pointerType(), Origin(), dataPointerValue),
13800 addToData->appendNew<MemoryValue>(
13801 proc, Load, pointerType(), Origin(), codePointerValue, static_cast<int32_t>(sizeof(intptr_t)))),
13802 dataPointerValue);
13803 addToData->appendNew<VariableValue>(
13804 proc, Set, Origin(), codePointer,
13805 addToData->appendNew<Value>(
13806 proc, B3::Add, Origin(), codePointerValue,
13807 addToData->appendIntConstant(proc, Origin(), pointerType(), sizeof(intptr_t) * 2)));
13808 addToData->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch));
13809
13810 // Print: "prints" the value pointed to by DP. What this actually means is that the value is
13811 // appended to the stream vector by the interpreterPrint function.
13812 codePointerValue = print->appendNew<VariableValue>(proc, B3::Get, Origin(), codePointer);
13813 dataPointerValue = print->appendNew<VariableValue>(proc, B3::Get, Origin(), dataPointer);
13814 print->appendNew<CCallValue>(
13815 proc, Void, Origin(),
13816 print->appendNew<ConstPtrValue>(
13817 proc, Origin(), tagCFunctionPtr<void*>(interpreterPrint, B3CCallPtrTag)),
13818 context,
13819 print->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), dataPointerValue));
13820 print->appendNew<VariableValue>(
13821 proc, Set, Origin(), codePointer,
13822 print->appendNew<Value>(
13823 proc, B3::Add, Origin(), codePointerValue,
13824 print->appendIntConstant(proc, Origin(), pointerType(), sizeof(intptr_t))));
13825 print->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch));
13826
13827 // Stop: returns.
13828 stop->appendNewControlValue(
13829 proc, Return, Origin(),
13830 stop->appendIntConstant(proc, Origin(), pointerType(), 0));
13831
13832 auto interpreter = compileProc(proc);
13833
13834 Vector<uintptr_t> data;
13835 Vector<uintptr_t> code;
13836 Vector<uintptr_t> stream;
13837
13838 data.append(1);
13839 data.append(0);
13840
13841 if (shouldBeVerbose())
13842 dataLog("data = ", listDump(data), "\n");
13843
13844 // We'll write a program that prints the numbers 1..100.
13845 // We expect DP to point at #0.
13846 code.append(AddCP);
13847 code.append(6); // go to loop body
13848
13849 // Loop re-entry:
13850 // We expect DP to point at #1 and for #1 to be offset by -100.
13851 code.append(Add);
13852 code.append(100);
13853
13854 code.append(AddDP);
13855 code.append(-1);
13856
13857 // Loop header:
13858 // We expect DP to point at #0.
13859 code.append(AddDP);
13860 code.append(1);
13861
13862 code.append(Add);
13863 code.append(1);
13864
13865 code.append(Print);
13866
13867 code.append(Add);
13868 code.append(-100);
13869
13870 // We want to stop if it's zero and continue if it's non-zero. AddCP takes the branch if it's
13871 // non-zero.
13872 code.append(AddCP);
13873 code.append(-11); // go to loop re-entry.
13874
13875 code.append(Stop);
13876
13877 if (shouldBeVerbose())
13878 dataLog("code = ", listDump(code), "\n");
13879
13880 CHECK(!invoke<intptr_t>(*interpreter, data.data(), code.data(), &stream));
13881
13882 CHECK(stream.size() == 100);
13883 for (unsigned i = 0; i < 100; ++i)
13884 CHECK(stream[i] == i + 1);
13885
13886 if (shouldBeVerbose())
13887 dataLog("stream = ", listDump(stream), "\n");
13888}
13889
13890void testReduceStrengthCheckBottomUseInAnotherBlock()
13891{
13892 Procedure proc;
13893 if (proc.optLevel() < 1)
13894 return;
13895
13896 BasicBlock* one = proc.addBlock();
13897 BasicBlock* two = proc.addBlock();
13898
13899 CheckValue* check = one->appendNew<CheckValue>(
13900 proc, Check, Origin(), one->appendNew<Const32Value>(proc, Origin(), 1));
13901 check->setGenerator(
13902 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
13903 AllowMacroScratchRegisterUsage allowScratch(jit);
13904
13905 jit.move(CCallHelpers::TrustedImm32(666), GPRInfo::returnValueGPR);
13906 jit.emitFunctionEpilogue();
13907 jit.ret();
13908 });
13909 Value* arg = one->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
13910 one->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(two));
13911
13912 check = two->appendNew<CheckValue>(
13913 proc, CheckAdd, Origin(), arg,
13914 two->appendNew<ConstPtrValue>(proc, Origin(), 1));
13915 check->setGenerator(
13916 [&] (CCallHelpers&, const StackmapGenerationParams&) {
13917 CHECK(!"Should not execute");
13918 });
13919 two->appendNewControlValue(proc, Return, Origin(), check);
13920
13921 proc.resetReachability();
13922 reduceStrength(proc);
13923}
13924
13925void testResetReachabilityDanglingReference()
13926{
13927 Procedure proc;
13928
13929 BasicBlock* one = proc.addBlock();
13930 BasicBlock* two = proc.addBlock();
13931
13932 UpsilonValue* upsilon = one->appendNew<UpsilonValue>(
13933 proc, Origin(), one->appendNew<Const32Value>(proc, Origin(), 42));
13934 one->appendNewControlValue(proc, Oops, Origin());
13935
13936 Value* phi = two->appendNew<Value>(proc, Phi, Int32, Origin());
13937 upsilon->setPhi(phi);
13938 two->appendNewControlValue(proc, Oops, Origin());
13939
13940 proc.resetReachability();
13941 validate(proc);
13942}
13943
13944void testEntrySwitchSimple()
13945{
13946 Procedure proc;
13947 proc.setNumEntrypoints(3);
13948
13949 BasicBlock* root = proc.addBlock();
13950 BasicBlock* one = proc.addBlock();
13951 BasicBlock* two = proc.addBlock();
13952 BasicBlock* three = proc.addBlock();
13953
13954 root->appendNew<Value>(proc, EntrySwitch, Origin());
13955 root->appendSuccessor(FrequentedBlock(one));
13956 root->appendSuccessor(FrequentedBlock(two));
13957 root->appendSuccessor(FrequentedBlock(three));
13958
13959 one->appendNew<Value>(
13960 proc, Return, Origin(),
13961 one->appendNew<Value>(
13962 proc, Add, Origin(),
13963 one->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
13964 one->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
13965
13966 two->appendNew<Value>(
13967 proc, Return, Origin(),
13968 two->appendNew<Value>(
13969 proc, Sub, Origin(),
13970 two->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
13971 two->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
13972
13973 three->appendNew<Value>(
13974 proc, Return, Origin(),
13975 three->appendNew<Value>(
13976 proc, Mul, Origin(),
13977 three->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
13978 three->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
13979
13980 prepareForGeneration(proc);
13981
13982 CCallHelpers jit;
13983 generate(proc, jit);
13984 LinkBuffer linkBuffer(jit, nullptr);
13985 CodeLocationLabel<B3CompilationPtrTag> labelOne = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(0));
13986 CodeLocationLabel<B3CompilationPtrTag> labelTwo = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(1));
13987 CodeLocationLabel<B3CompilationPtrTag> labelThree = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(2));
13988
13989 MacroAssemblerCodeRef<B3CompilationPtrTag> codeRef = FINALIZE_CODE(linkBuffer, B3CompilationPtrTag, "testb3 compilation");
13990
13991 CHECK(invoke<int>(labelOne, 1, 2) == 3);
13992 CHECK(invoke<int>(labelTwo, 1, 2) == -1);
13993 CHECK(invoke<int>(labelThree, 1, 2) == 2);
13994 CHECK(invoke<int>(labelOne, -1, 2) == 1);
13995 CHECK(invoke<int>(labelTwo, -1, 2) == -3);
13996 CHECK(invoke<int>(labelThree, -1, 2) == -2);
13997}
13998
13999void testEntrySwitchNoEntrySwitch()
14000{
14001 Procedure proc;
14002 proc.setNumEntrypoints(3);
14003
14004 BasicBlock* root = proc.addBlock();
14005
14006 root->appendNew<Value>(
14007 proc, Return, Origin(),
14008 root->appendNew<Value>(
14009 proc, Add, Origin(),
14010 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
14011 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
14012
14013 prepareForGeneration(proc);
14014
14015 CCallHelpers jit;
14016 generate(proc, jit);
14017 LinkBuffer linkBuffer(jit, nullptr);
14018 CodeLocationLabel<B3CompilationPtrTag> labelOne = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(0));
14019 CodeLocationLabel<B3CompilationPtrTag> labelTwo = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(1));
14020 CodeLocationLabel<B3CompilationPtrTag> labelThree = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(2));
14021
14022 MacroAssemblerCodeRef<B3CompilationPtrTag> codeRef = FINALIZE_CODE(linkBuffer, B3CompilationPtrTag, "testb3 compilation");
14023
14024 CHECK_EQ(invoke<int>(labelOne, 1, 2), 3);
14025 CHECK_EQ(invoke<int>(labelTwo, 1, 2), 3);
14026 CHECK_EQ(invoke<int>(labelThree, 1, 2), 3);
14027 CHECK_EQ(invoke<int>(labelOne, -1, 2), 1);
14028 CHECK_EQ(invoke<int>(labelTwo, -1, 2), 1);
14029 CHECK_EQ(invoke<int>(labelThree, -1, 2), 1);
14030}
14031
14032void testEntrySwitchWithCommonPaths()
14033{
14034 Procedure proc;
14035 proc.setNumEntrypoints(3);
14036
14037 BasicBlock* root = proc.addBlock();
14038 BasicBlock* one = proc.addBlock();
14039 BasicBlock* two = proc.addBlock();
14040 BasicBlock* three = proc.addBlock();
14041 BasicBlock* end = proc.addBlock();
14042
14043 root->appendNew<Value>(proc, EntrySwitch, Origin());
14044 root->appendSuccessor(FrequentedBlock(one));
14045 root->appendSuccessor(FrequentedBlock(two));
14046 root->appendSuccessor(FrequentedBlock(three));
14047
14048 UpsilonValue* upsilonOne = one->appendNew<UpsilonValue>(
14049 proc, Origin(),
14050 one->appendNew<Value>(
14051 proc, Add, Origin(),
14052 one->appendNew<Value>(
14053 proc, Trunc, Origin(),
14054 one->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
14055 one->appendNew<Value>(
14056 proc, Trunc, Origin(),
14057 one->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
14058 one->appendNew<Value>(proc, Jump, Origin());
14059 one->setSuccessors(FrequentedBlock(end));
14060
14061 UpsilonValue* upsilonTwo = two->appendNew<UpsilonValue>(
14062 proc, Origin(),
14063 two->appendNew<Value>(
14064 proc, Sub, Origin(),
14065 two->appendNew<Value>(
14066 proc, Trunc, Origin(),
14067 two->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
14068 two->appendNew<Value>(
14069 proc, Trunc, Origin(),
14070 two->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
14071 two->appendNew<Value>(proc, Jump, Origin());
14072 two->setSuccessors(FrequentedBlock(end));
14073
14074 UpsilonValue* upsilonThree = three->appendNew<UpsilonValue>(
14075 proc, Origin(),
14076 three->appendNew<Value>(
14077 proc, Mul, Origin(),
14078 three->appendNew<Value>(
14079 proc, Trunc, Origin(),
14080 three->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
14081 three->appendNew<Value>(
14082 proc, Trunc, Origin(),
14083 three->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
14084 three->appendNew<Value>(proc, Jump, Origin());
14085 three->setSuccessors(FrequentedBlock(end));
14086
14087 Value* phi = end->appendNew<Value>(proc, Phi, Int32, Origin());
14088 upsilonOne->setPhi(phi);
14089 upsilonTwo->setPhi(phi);
14090 upsilonThree->setPhi(phi);
14091
14092 end->appendNew<Value>(
14093 proc, Return, Origin(),
14094 end->appendNew<Value>(
14095 proc, chill(Mod), Origin(),
14096 phi, end->appendNew<Value>(
14097 proc, Trunc, Origin(),
14098 end->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))));
14099
14100 prepareForGeneration(proc);
14101
14102 CCallHelpers jit;
14103 generate(proc, jit);
14104 LinkBuffer linkBuffer(jit, nullptr);
14105 CodeLocationLabel<B3CompilationPtrTag> labelOne = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(0));
14106 CodeLocationLabel<B3CompilationPtrTag> labelTwo = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(1));
14107 CodeLocationLabel<B3CompilationPtrTag> labelThree = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(2));
14108
14109 MacroAssemblerCodeRef<B3CompilationPtrTag> codeRef = FINALIZE_CODE(linkBuffer, B3CompilationPtrTag, "testb3 compilation");
14110
14111 CHECK_EQ(invoke<int>(labelOne, 1, 2, 10), 3);
14112 CHECK_EQ(invoke<int>(labelTwo, 1, 2, 10), -1);
14113 CHECK_EQ(invoke<int>(labelThree, 1, 2, 10), 2);
14114 CHECK_EQ(invoke<int>(labelOne, -1, 2, 10), 1);
14115 CHECK_EQ(invoke<int>(labelTwo, -1, 2, 10), -3);
14116 CHECK_EQ(invoke<int>(labelThree, -1, 2, 10), -2);
14117 CHECK_EQ(invoke<int>(labelOne, 1, 2, 2), 1);
14118 CHECK_EQ(invoke<int>(labelTwo, 1, 2, 2), -1);
14119 CHECK_EQ(invoke<int>(labelThree, 1, 2, 2), 0);
14120 CHECK_EQ(invoke<int>(labelOne, -1, 2, 2), 1);
14121 CHECK_EQ(invoke<int>(labelTwo, -1, 2, 2), -1);
14122 CHECK_EQ(invoke<int>(labelThree, -1, 2, 2), 0);
14123 CHECK_EQ(invoke<int>(labelOne, 1, 2, 0), 0);
14124 CHECK_EQ(invoke<int>(labelTwo, 1, 2, 0), 0);
14125 CHECK_EQ(invoke<int>(labelThree, 1, 2, 0), 0);
14126 CHECK_EQ(invoke<int>(labelOne, -1, 2, 0), 0);
14127 CHECK_EQ(invoke<int>(labelTwo, -1, 2, 0), 0);
14128 CHECK_EQ(invoke<int>(labelThree, -1, 2, 0), 0);
14129}
14130
14131void testEntrySwitchWithCommonPathsAndNonTrivialEntrypoint()
14132{
14133 Procedure proc;
14134 proc.setNumEntrypoints(3);
14135
14136 BasicBlock* root = proc.addBlock();
14137 BasicBlock* negate = proc.addBlock();
14138 BasicBlock* dispatch = proc.addBlock();
14139 BasicBlock* one = proc.addBlock();
14140 BasicBlock* two = proc.addBlock();
14141 BasicBlock* three = proc.addBlock();
14142 BasicBlock* end = proc.addBlock();
14143
14144 UpsilonValue* upsilonBase = root->appendNew<UpsilonValue>(
14145 proc, Origin(), root->appendNew<Value>(
14146 proc, Trunc, Origin(),
14147 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
14148 root->appendNew<Value>(
14149 proc, Branch, Origin(),
14150 root->appendNew<Value>(
14151 proc, BitAnd, Origin(),
14152 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3),
14153 root->appendNew<ConstPtrValue>(proc, Origin(), 0xff)));
14154 root->setSuccessors(FrequentedBlock(negate), FrequentedBlock(dispatch));
14155
14156 UpsilonValue* upsilonNegate = negate->appendNew<UpsilonValue>(
14157 proc, Origin(),
14158 negate->appendNew<Value>(
14159 proc, Neg, Origin(),
14160 negate->appendNew<Value>(
14161 proc, Trunc, Origin(),
14162 negate->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
14163 negate->appendNew<Value>(proc, Jump, Origin());
14164 negate->setSuccessors(FrequentedBlock(dispatch));
14165
14166 Value* arg0 = dispatch->appendNew<Value>(proc, Phi, Int32, Origin());
14167 upsilonBase->setPhi(arg0);
14168 upsilonNegate->setPhi(arg0);
14169 dispatch->appendNew<Value>(proc, EntrySwitch, Origin());
14170 dispatch->appendSuccessor(FrequentedBlock(one));
14171 dispatch->appendSuccessor(FrequentedBlock(two));
14172 dispatch->appendSuccessor(FrequentedBlock(three));
14173
14174 UpsilonValue* upsilonOne = one->appendNew<UpsilonValue>(
14175 proc, Origin(),
14176 one->appendNew<Value>(
14177 proc, Add, Origin(),
14178 arg0, one->appendNew<Value>(
14179 proc, Trunc, Origin(),
14180 one->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
14181 one->appendNew<Value>(proc, Jump, Origin());
14182 one->setSuccessors(FrequentedBlock(end));
14183
14184 UpsilonValue* upsilonTwo = two->appendNew<UpsilonValue>(
14185 proc, Origin(),
14186 two->appendNew<Value>(
14187 proc, Sub, Origin(),
14188 arg0, two->appendNew<Value>(
14189 proc, Trunc, Origin(),
14190 two->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
14191 two->appendNew<Value>(proc, Jump, Origin());
14192 two->setSuccessors(FrequentedBlock(end));
14193
14194 UpsilonValue* upsilonThree = three->appendNew<UpsilonValue>(
14195 proc, Origin(),
14196 three->appendNew<Value>(
14197 proc, Mul, Origin(),
14198 arg0, three->appendNew<Value>(
14199 proc, Trunc, Origin(),
14200 three->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
14201 three->appendNew<Value>(proc, Jump, Origin());
14202 three->setSuccessors(FrequentedBlock(end));
14203
14204 Value* phi = end->appendNew<Value>(proc, Phi, Int32, Origin());
14205 upsilonOne->setPhi(phi);
14206 upsilonTwo->setPhi(phi);
14207 upsilonThree->setPhi(phi);
14208
14209 end->appendNew<Value>(
14210 proc, Return, Origin(),
14211 end->appendNew<Value>(
14212 proc, chill(Mod), Origin(),
14213 phi, end->appendNew<Value>(
14214 proc, Trunc, Origin(),
14215 end->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))));
14216
14217 prepareForGeneration(proc);
14218
14219 CCallHelpers jit;
14220 generate(proc, jit);
14221 LinkBuffer linkBuffer(jit, nullptr);
14222 CodeLocationLabel<B3CompilationPtrTag> labelOne = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(0));
14223 CodeLocationLabel<B3CompilationPtrTag> labelTwo = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(1));
14224 CodeLocationLabel<B3CompilationPtrTag> labelThree = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(2));
14225
14226 MacroAssemblerCodeRef<B3CompilationPtrTag> codeRef = FINALIZE_CODE(linkBuffer, B3CompilationPtrTag, "testb3 compilation");
14227
14228 CHECK_EQ(invoke<int>(labelOne, 1, 2, 10, false), 3);
14229 CHECK_EQ(invoke<int>(labelTwo, 1, 2, 10, false), -1);
14230 CHECK_EQ(invoke<int>(labelThree, 1, 2, 10, false), 2);
14231 CHECK_EQ(invoke<int>(labelOne, -1, 2, 10, false), 1);
14232 CHECK_EQ(invoke<int>(labelTwo, -1, 2, 10, false), -3);
14233 CHECK_EQ(invoke<int>(labelThree, -1, 2, 10, false), -2);
14234 CHECK_EQ(invoke<int>(labelOne, 1, 2, 10, true), 1);
14235 CHECK_EQ(invoke<int>(labelTwo, 1, 2, 10, true), -3);
14236 CHECK_EQ(invoke<int>(labelThree, 1, 2, 10, true), -2);
14237 CHECK_EQ(invoke<int>(labelOne, -1, 2, 10, true), 3);
14238 CHECK_EQ(invoke<int>(labelTwo, -1, 2, 10, true), -1);
14239 CHECK_EQ(invoke<int>(labelThree, -1, 2, 10, true), 2);
14240 CHECK_EQ(invoke<int>(labelOne, 1, 2, 2, false), 1);
14241 CHECK_EQ(invoke<int>(labelTwo, 1, 2, 2, false), -1);
14242 CHECK_EQ(invoke<int>(labelThree, 1, 2, 2, false), 0);
14243 CHECK_EQ(invoke<int>(labelOne, -1, 2, 2, false), 1);
14244 CHECK_EQ(invoke<int>(labelTwo, -1, 2, 2, false), -1);
14245 CHECK_EQ(invoke<int>(labelThree, -1, 2, 2, false), 0);
14246 CHECK_EQ(invoke<int>(labelOne, 1, 2, 0, false), 0);
14247 CHECK_EQ(invoke<int>(labelTwo, 1, 2, 0, false), 0);
14248 CHECK_EQ(invoke<int>(labelThree, 1, 2, 0, false), 0);
14249 CHECK_EQ(invoke<int>(labelOne, -1, 2, 0, false), 0);
14250 CHECK_EQ(invoke<int>(labelTwo, -1, 2, 0, false), 0);
14251 CHECK_EQ(invoke<int>(labelThree, -1, 2, 0, false), 0);
14252}
14253
14254void testEntrySwitchLoop()
14255{
14256 // This is a completely absurd use of EntrySwitch, where it impacts the loop condition. This
14257 // should cause duplication of either nearly the entire Procedure. At time of writing, we ended
14258 // up duplicating all of it, which is fine. It's important to test this case, to make sure that
14259 // the duplication algorithm can handle interesting control flow.
14260
14261 Procedure proc;
14262 proc.setNumEntrypoints(2);
14263
14264 BasicBlock* root = proc.addBlock();
14265 BasicBlock* loopHeader = proc.addBlock();
14266 BasicBlock* loopFooter = proc.addBlock();
14267 BasicBlock* end = proc.addBlock();
14268
14269 UpsilonValue* initialValue = root->appendNew<UpsilonValue>(
14270 proc, Origin(), root->appendNew<Value>(
14271 proc, Trunc, Origin(),
14272 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
14273 root->appendNew<Value>(proc, Jump, Origin());
14274 root->setSuccessors(loopHeader);
14275
14276 Value* valueInLoop = loopHeader->appendNew<Value>(proc, Phi, Int32, Origin());
14277 initialValue->setPhi(valueInLoop);
14278 Value* newValue = loopHeader->appendNew<Value>(
14279 proc, Add, Origin(), valueInLoop,
14280 loopHeader->appendNew<Const32Value>(proc, Origin(), 1));
14281 loopHeader->appendNew<Value>(proc, EntrySwitch, Origin());
14282 loopHeader->appendSuccessor(end);
14283 loopHeader->appendSuccessor(loopFooter);
14284
14285 loopFooter->appendNew<UpsilonValue>(proc, Origin(), newValue, valueInLoop);
14286 loopFooter->appendNew<Value>(
14287 proc, Branch, Origin(),
14288 loopFooter->appendNew<Value>(
14289 proc, LessThan, Origin(), newValue,
14290 loopFooter->appendNew<Const32Value>(proc, Origin(), 100)));
14291 loopFooter->setSuccessors(loopHeader, end);
14292
14293 end->appendNew<Value>(proc, Return, Origin(), newValue);
14294
14295 prepareForGeneration(proc);
14296
14297 CCallHelpers jit;
14298 generate(proc, jit);
14299 LinkBuffer linkBuffer(jit, nullptr);
14300 CodeLocationLabel<B3CompilationPtrTag> labelOne = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(0));
14301 CodeLocationLabel<B3CompilationPtrTag> labelTwo = linkBuffer.locationOf<B3CompilationPtrTag>(proc.entrypointLabel(1));
14302
14303 MacroAssemblerCodeRef<B3CompilationPtrTag> codeRef = FINALIZE_CODE(linkBuffer, B3CompilationPtrTag, "testb3 compilation");
14304
14305 CHECK(invoke<int>(labelOne, 0) == 1);
14306 CHECK(invoke<int>(labelOne, 42) == 43);
14307 CHECK(invoke<int>(labelOne, 1000) == 1001);
14308
14309 CHECK(invoke<int>(labelTwo, 0) == 100);
14310 CHECK(invoke<int>(labelTwo, 42) == 100);
14311 CHECK(invoke<int>(labelTwo, 1000) == 1001);
14312}
14313
14314void testSomeEarlyRegister()
14315{
14316 auto run = [&] (bool succeed) {
14317 Procedure proc;
14318
14319 BasicBlock* root = proc.addBlock();
14320
14321 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
14322 patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR);
14323 bool ranFirstPatchpoint = false;
14324 patchpoint->setGenerator(
14325 [&] (CCallHelpers&, const StackmapGenerationParams& params) {
14326 CHECK(params[0].gpr() == GPRInfo::returnValueGPR);
14327 ranFirstPatchpoint = true;
14328 });
14329
14330 Value* arg = patchpoint;
14331
14332 patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
14333 patchpoint->appendSomeRegister(arg);
14334 if (succeed)
14335 patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
14336 bool ranSecondPatchpoint = false;
14337 unsigned optLevel = proc.optLevel();
14338 patchpoint->setGenerator(
14339 [&] (CCallHelpers&, const StackmapGenerationParams& params) {
14340 if (succeed)
14341 CHECK(params[0].gpr() != params[1].gpr());
14342 else if (optLevel > 1)
14343 CHECK(params[0].gpr() == params[1].gpr());
14344 ranSecondPatchpoint = true;
14345 });
14346
14347 root->appendNew<Value>(proc, Return, Origin(), patchpoint);
14348
14349 compileProc(proc);
14350 CHECK(ranFirstPatchpoint);
14351 CHECK(ranSecondPatchpoint);
14352 };
14353
14354 run(true);
14355 run(false);
14356}
14357
14358void testBranchBitAndImmFusion(
14359 B3::Opcode valueModifier, Type valueType, int64_t constant,
14360 Air::Opcode expectedOpcode, Air::Arg::Kind firstKind)
14361{
14362 // Currently this test should pass on all CPUs. But some CPUs may not support this fused
14363 // instruction. It's OK to skip this test on those CPUs.
14364
14365 Procedure proc;
14366
14367 BasicBlock* root = proc.addBlock();
14368 BasicBlock* one = proc.addBlock();
14369 BasicBlock* two = proc.addBlock();
14370
14371 Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
14372
14373 if (valueModifier != Identity) {
14374 if (MemoryValue::accepts(valueModifier))
14375 left = root->appendNew<MemoryValue>(proc, valueModifier, valueType, Origin(), left);
14376 else
14377 left = root->appendNew<Value>(proc, valueModifier, valueType, Origin(), left);
14378 }
14379
14380 root->appendNew<Value>(
14381 proc, Branch, Origin(),
14382 root->appendNew<Value>(
14383 proc, BitAnd, Origin(), left,
14384 root->appendIntConstant(proc, Origin(), valueType, constant)));
14385 root->setSuccessors(FrequentedBlock(one), FrequentedBlock(two));
14386
14387 one->appendNew<Value>(proc, Oops, Origin());
14388 two->appendNew<Value>(proc, Oops, Origin());
14389
14390 lowerToAirForTesting(proc);
14391
14392 // The first basic block must end in a BranchTest64(resCond, tmp, bitImm).
14393 Air::Inst terminal = proc.code()[0]->last();
14394 CHECK_EQ(terminal.kind.opcode, expectedOpcode);
14395 CHECK_EQ(terminal.args[0].kind(), Air::Arg::ResCond);
14396 CHECK_EQ(terminal.args[1].kind(), firstKind);
14397 CHECK(terminal.args[2].kind() == Air::Arg::BitImm || terminal.args[2].kind() == Air::Arg::BitImm64);
14398}
14399
14400void testTerminalPatchpointThatNeedsToBeSpilled()
14401{
14402 // This is a unit test for how FTL's heap allocation fast paths behave.
14403 Procedure proc;
14404
14405 BasicBlock* root = proc.addBlock();
14406 BasicBlock* success = proc.addBlock();
14407 BasicBlock* slowPath = proc.addBlock();
14408
14409 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
14410 patchpoint->effects.terminal = true;
14411 patchpoint->clobber(RegisterSet::macroScratchRegisters());
14412
14413 root->appendSuccessor(success);
14414 root->appendSuccessor(FrequentedBlock(slowPath, FrequencyClass::Rare));
14415
14416 patchpoint->setGenerator(
14417 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
14418 AllowMacroScratchRegisterUsage allowScratch(jit);
14419 jit.move(CCallHelpers::TrustedImm32(42), params[0].gpr());
14420
14421 CCallHelpers::Jump jumpToSuccess;
14422 if (!params.fallsThroughToSuccessor(0))
14423 jumpToSuccess = jit.jump();
14424
14425 Vector<Box<CCallHelpers::Label>> labels = params.successorLabels();
14426
14427 params.addLatePath(
14428 [=] (CCallHelpers& jit) {
14429 if (jumpToSuccess.isSet())
14430 jumpToSuccess.linkTo(*labels[0], &jit);
14431 });
14432 });
14433
14434 Vector<Value*> args;
14435 {
14436 RegisterSet fillAllGPRsSet = proc.mutableGPRs();
14437 for (unsigned i = 0; i < fillAllGPRsSet.numberOfSetRegisters(); i++)
14438 args.append(success->appendNew<Const32Value>(proc, Origin(), i));
14439 }
14440
14441 {
14442 // Now force all values into every available register.
14443 PatchpointValue* p = success->appendNew<PatchpointValue>(proc, Void, Origin());
14444 for (Value* v : args)
14445 p->append(v, ValueRep::SomeRegister);
14446 p->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
14447 }
14448
14449 {
14450 // Now require the original patchpoint to be materialized into a register.
14451 PatchpointValue* p = success->appendNew<PatchpointValue>(proc, Void, Origin());
14452 p->append(patchpoint, ValueRep::SomeRegister);
14453 p->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
14454 }
14455
14456 success->appendNew<Value>(proc, Return, Origin(), success->appendNew<Const32Value>(proc, Origin(), 10));
14457
14458 slowPath->appendNew<Value>(proc, Return, Origin(), slowPath->appendNew<Const32Value>(proc, Origin(), 20));
14459
14460 auto code = compileProc(proc);
14461 CHECK_EQ(invoke<int>(*code), 10);
14462}
14463
14464void testTerminalPatchpointThatNeedsToBeSpilled2()
14465{
14466 // This is a unit test for how FTL's heap allocation fast paths behave.
14467 Procedure proc;
14468
14469 // FIXME: Air O0/O1 allocator can't handle such programs. We rely on WasmAirIRGenerator
14470 // to not use any such constructs where the register allocator is cornered in such
14471 // a way.
14472 // https://bugs.webkit.org/show_bug.cgi?id=194633
14473 if (proc.optLevel() < 2)
14474 return;
14475
14476 BasicBlock* root = proc.addBlock();
14477 BasicBlock* one = proc.addBlock();
14478 BasicBlock* success = proc.addBlock();
14479 BasicBlock* slowPath = proc.addBlock();
14480
14481 Value* arg = root->appendNew<Value>(
14482 proc, Trunc, Origin(),
14483 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
14484
14485 root->appendNew<Value>(
14486 proc, Branch, Origin(), arg);
14487 root->appendSuccessor(one);
14488 root->appendSuccessor(FrequentedBlock(slowPath, FrequencyClass::Rare));
14489
14490 PatchpointValue* patchpoint = one->appendNew<PatchpointValue>(proc, Int32, Origin());
14491 patchpoint->effects.terminal = true;
14492 patchpoint->clobber(RegisterSet::macroScratchRegisters());
14493 patchpoint->append(arg, ValueRep::SomeRegister);
14494
14495 one->appendSuccessor(success);
14496 one->appendSuccessor(FrequentedBlock(slowPath, FrequencyClass::Rare));
14497
14498 patchpoint->setGenerator(
14499 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
14500 AllowMacroScratchRegisterUsage allowScratch(jit);
14501 jit.move(CCallHelpers::TrustedImm32(666), params[0].gpr());
14502 auto goToFastPath = jit.branch32(CCallHelpers::Equal, params[1].gpr(), CCallHelpers::TrustedImm32(42));
14503 auto jumpToSlow = jit.jump();
14504
14505 // Make sure the asserts here pass.
14506 params.fallsThroughToSuccessor(0);
14507 params.fallsThroughToSuccessor(1);
14508
14509 Vector<Box<CCallHelpers::Label>> labels = params.successorLabels();
14510
14511 params.addLatePath(
14512 [=] (CCallHelpers& jit) {
14513 goToFastPath.linkTo(*labels[0], &jit);
14514 jumpToSlow.linkTo(*labels[1], &jit);
14515 });
14516 });
14517
14518 Vector<Value*> args;
14519 {
14520 RegisterSet fillAllGPRsSet = proc.mutableGPRs();
14521 for (unsigned i = 0; i < fillAllGPRsSet.numberOfSetRegisters(); i++)
14522 args.append(success->appendNew<Const32Value>(proc, Origin(), i));
14523 }
14524
14525 {
14526 // Now force all values into every available register.
14527 PatchpointValue* p = success->appendNew<PatchpointValue>(proc, Void, Origin());
14528 for (Value* v : args)
14529 p->append(v, ValueRep::SomeRegister);
14530 p->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
14531 }
14532
14533 {
14534 // Now require the original patchpoint to be materialized into a register.
14535 PatchpointValue* p = success->appendNew<PatchpointValue>(proc, Void, Origin());
14536 p->append(patchpoint, ValueRep::SomeRegister);
14537 p->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
14538 }
14539
14540 success->appendNew<Value>(proc, Return, Origin(), patchpoint);
14541
14542 slowPath->appendNew<Value>(proc, Return, Origin(), arg);
14543
14544 auto original1 = Options::maxB3TailDupBlockSize();
14545 auto original2 = Options::maxB3TailDupBlockSuccessors();
14546
14547 // Tail duplication will break the critical edge we're trying to test because it
14548 // will clone the slowPath block for both edges to it!
14549 Options::maxB3TailDupBlockSize() = 0;
14550 Options::maxB3TailDupBlockSuccessors() = 0;
14551
14552 auto code = compileProc(proc);
14553 CHECK_EQ(invoke<int>(*code, 1), 1);
14554 CHECK_EQ(invoke<int>(*code, 0), 0);
14555 CHECK_EQ(invoke<int>(*code, 42), 666);
14556
14557 Options::maxB3TailDupBlockSize() = original1;
14558 Options::maxB3TailDupBlockSuccessors() = original2;
14559}
14560
14561void testPatchpointTerminalReturnValue(bool successIsRare)
14562{
14563 // This is a unit test for how FTL's heap allocation fast paths behave.
14564 Procedure proc;
14565
14566 BasicBlock* root = proc.addBlock();
14567 BasicBlock* success = proc.addBlock();
14568 BasicBlock* slowPath = proc.addBlock();
14569 BasicBlock* continuation = proc.addBlock();
14570
14571 Value* arg = root->appendNew<Value>(
14572 proc, Trunc, Origin(),
14573 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
14574
14575 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
14576 patchpoint->effects.terminal = true;
14577 patchpoint->clobber(RegisterSet::macroScratchRegisters());
14578
14579 if (successIsRare) {
14580 root->appendSuccessor(FrequentedBlock(success, FrequencyClass::Rare));
14581 root->appendSuccessor(slowPath);
14582 } else {
14583 root->appendSuccessor(success);
14584 root->appendSuccessor(FrequentedBlock(slowPath, FrequencyClass::Rare));
14585 }
14586
14587 patchpoint->appendSomeRegister(arg);
14588
14589 patchpoint->setGenerator(
14590 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
14591 AllowMacroScratchRegisterUsage allowScratch(jit);
14592
14593 CCallHelpers::Jump jumpToSlow =
14594 jit.branch32(CCallHelpers::Above, params[1].gpr(), CCallHelpers::TrustedImm32(42));
14595
14596 jit.add32(CCallHelpers::TrustedImm32(31), params[1].gpr(), params[0].gpr());
14597
14598 CCallHelpers::Jump jumpToSuccess;
14599 if (!params.fallsThroughToSuccessor(0))
14600 jumpToSuccess = jit.jump();
14601
14602 Vector<Box<CCallHelpers::Label>> labels = params.successorLabels();
14603
14604 params.addLatePath(
14605 [=] (CCallHelpers& jit) {
14606 jumpToSlow.linkTo(*labels[1], &jit);
14607 if (jumpToSuccess.isSet())
14608 jumpToSuccess.linkTo(*labels[0], &jit);
14609 });
14610 });
14611
14612 UpsilonValue* successUpsilon = success->appendNew<UpsilonValue>(proc, Origin(), patchpoint);
14613 success->appendNew<Value>(proc, Jump, Origin());
14614 success->setSuccessors(continuation);
14615
14616 UpsilonValue* slowPathUpsilon = slowPath->appendNew<UpsilonValue>(
14617 proc, Origin(), slowPath->appendNew<Const32Value>(proc, Origin(), 666));
14618 slowPath->appendNew<Value>(proc, Jump, Origin());
14619 slowPath->setSuccessors(continuation);
14620
14621 Value* phi = continuation->appendNew<Value>(proc, Phi, Int32, Origin());
14622 successUpsilon->setPhi(phi);
14623 slowPathUpsilon->setPhi(phi);
14624 continuation->appendNew<Value>(proc, Return, Origin(), phi);
14625
14626 auto code = compileProc(proc);
14627 CHECK_EQ(invoke<int>(*code, 0), 31);
14628 CHECK_EQ(invoke<int>(*code, 1), 32);
14629 CHECK_EQ(invoke<int>(*code, 41), 72);
14630 CHECK_EQ(invoke<int>(*code, 42), 73);
14631 CHECK_EQ(invoke<int>(*code, 43), 666);
14632 CHECK_EQ(invoke<int>(*code, -1), 666);
14633}
14634
14635void testMemoryFence()
14636{
14637 Procedure proc;
14638
14639 BasicBlock* root = proc.addBlock();
14640
14641 root->appendNew<FenceValue>(proc, Origin());
14642 root->appendNew<Value>(proc, Return, Origin(), root->appendIntConstant(proc, Origin(), Int32, 42));
14643
14644 auto code = compileProc(proc);
14645 CHECK_EQ(invoke<int>(*code), 42);
14646 if (isX86())
14647 checkUsesInstruction(*code, "lock or $0x0, (%rsp)");
14648 if (isARM64())
14649 checkUsesInstruction(*code, "dmb ish");
14650 checkDoesNotUseInstruction(*code, "mfence");
14651 checkDoesNotUseInstruction(*code, "dmb ishst");
14652}
14653
14654void testStoreFence()
14655{
14656 Procedure proc;
14657
14658 BasicBlock* root = proc.addBlock();
14659
14660 root->appendNew<FenceValue>(proc, Origin(), HeapRange::top(), HeapRange());
14661 root->appendNew<Value>(proc, Return, Origin(), root->appendIntConstant(proc, Origin(), Int32, 42));
14662
14663 auto code = compileProc(proc);
14664 CHECK_EQ(invoke<int>(*code), 42);
14665 checkDoesNotUseInstruction(*code, "lock");
14666 checkDoesNotUseInstruction(*code, "mfence");
14667 if (isARM64())
14668 checkUsesInstruction(*code, "dmb ishst");
14669}
14670
14671void testLoadFence()
14672{
14673 Procedure proc;
14674
14675 BasicBlock* root = proc.addBlock();
14676
14677 root->appendNew<FenceValue>(proc, Origin(), HeapRange(), HeapRange::top());
14678 root->appendNew<Value>(proc, Return, Origin(), root->appendIntConstant(proc, Origin(), Int32, 42));
14679
14680 auto code = compileProc(proc);
14681 CHECK_EQ(invoke<int>(*code), 42);
14682 checkDoesNotUseInstruction(*code, "lock");
14683 checkDoesNotUseInstruction(*code, "mfence");
14684 if (isARM64())
14685 checkUsesInstruction(*code, "dmb ish");
14686 checkDoesNotUseInstruction(*code, "dmb ishst");
14687}
14688
14689void testTrappingLoad()
14690{
14691 Procedure proc;
14692 BasicBlock* root = proc.addBlock();
14693 int x = 42;
14694 MemoryValue* value = root->appendNew<MemoryValue>(
14695 proc, trapping(Load), Int32, Origin(),
14696 root->appendNew<ConstPtrValue>(proc, Origin(), &x));
14697 Effects expectedEffects;
14698 expectedEffects.exitsSideways = true;
14699 expectedEffects.controlDependent= true;
14700 expectedEffects.reads = HeapRange::top();
14701 CHECK_EQ(value->range(), HeapRange::top());
14702 CHECK_EQ(value->effects(), expectedEffects);
14703 value->setRange(HeapRange(0));
14704 CHECK_EQ(value->range(), HeapRange(0));
14705 CHECK_EQ(value->effects(), expectedEffects); // We still reads top!
14706 root->appendNew<Value>(proc, Return, Origin(), value);
14707 CHECK_EQ(compileAndRun<int>(proc), 42);
14708 unsigned trapsCount = 0;
14709 for (Air::BasicBlock* block : proc.code()) {
14710 for (Air::Inst& inst : *block) {
14711 if (inst.kind.effects)
14712 trapsCount++;
14713 }
14714 }
14715 CHECK_EQ(trapsCount, 1u);
14716}
14717
14718void testTrappingStore()
14719{
14720 Procedure proc;
14721 BasicBlock* root = proc.addBlock();
14722 int x = 42;
14723 MemoryValue* value = root->appendNew<MemoryValue>(
14724 proc, trapping(Store), Origin(),
14725 root->appendNew<Const32Value>(proc, Origin(), 111),
14726 root->appendNew<ConstPtrValue>(proc, Origin(), &x), 0);
14727 Effects expectedEffects;
14728 expectedEffects.exitsSideways = true;
14729 expectedEffects.controlDependent= true;
14730 expectedEffects.reads = HeapRange::top();
14731 expectedEffects.writes = HeapRange::top();
14732 CHECK_EQ(value->range(), HeapRange::top());
14733 CHECK_EQ(value->effects(), expectedEffects);
14734 value->setRange(HeapRange(0));
14735 CHECK_EQ(value->range(), HeapRange(0));
14736 expectedEffects.writes = HeapRange(0);
14737 CHECK_EQ(value->effects(), expectedEffects); // We still reads top!
14738 root->appendNew<Value>(proc, Return, Origin());
14739 compileAndRun<int>(proc);
14740 CHECK_EQ(x, 111);
14741 unsigned trapsCount = 0;
14742 for (Air::BasicBlock* block : proc.code()) {
14743 for (Air::Inst& inst : *block) {
14744 if (inst.kind.effects)
14745 trapsCount++;
14746 }
14747 }
14748 CHECK_EQ(trapsCount, 1u);
14749}
14750
14751void testTrappingLoadAddStore()
14752{
14753 Procedure proc;
14754 BasicBlock* root = proc.addBlock();
14755 int x = 42;
14756 ConstPtrValue* ptr = root->appendNew<ConstPtrValue>(proc, Origin(), &x);
14757 root->appendNew<MemoryValue>(
14758 proc, trapping(Store), Origin(),
14759 root->appendNew<Value>(
14760 proc, Add, Origin(),
14761 root->appendNew<MemoryValue>(proc, trapping(Load), Int32, Origin(), ptr),
14762 root->appendNew<Const32Value>(proc, Origin(), 3)),
14763 ptr, 0);
14764 root->appendNew<Value>(proc, Return, Origin());
14765 compileAndRun<int>(proc);
14766 CHECK_EQ(x, 45);
14767 bool traps = false;
14768 for (Air::BasicBlock* block : proc.code()) {
14769 for (Air::Inst& inst : *block) {
14770 if (inst.kind.effects)
14771 traps = true;
14772 }
14773 }
14774 CHECK(traps);
14775}
14776
14777void testTrappingLoadDCE()
14778{
14779 Procedure proc;
14780 BasicBlock* root = proc.addBlock();
14781 int x = 42;
14782 root->appendNew<MemoryValue>(
14783 proc, trapping(Load), Int32, Origin(),
14784 root->appendNew<ConstPtrValue>(proc, Origin(), &x));
14785 root->appendNew<Value>(proc, Return, Origin());
14786 compileAndRun<int>(proc);
14787 unsigned trapsCount = 0;
14788 for (Air::BasicBlock* block : proc.code()) {
14789 for (Air::Inst& inst : *block) {
14790 if (inst.kind.effects)
14791 trapsCount++;
14792 }
14793 }
14794 CHECK_EQ(trapsCount, 1u);
14795}
14796
14797void testTrappingStoreElimination()
14798{
14799 Procedure proc;
14800 BasicBlock* root = proc.addBlock();
14801 int x = 42;
14802 Value* ptr = root->appendNew<ConstPtrValue>(proc, Origin(), &x);
14803 root->appendNew<MemoryValue>(
14804 proc, trapping(Store), Origin(),
14805 root->appendNew<Const32Value>(proc, Origin(), 43),
14806 ptr);
14807 root->appendNew<MemoryValue>(
14808 proc, trapping(Store), Origin(),
14809 root->appendNew<Const32Value>(proc, Origin(), 44),
14810 ptr);
14811 root->appendNew<Value>(proc, Return, Origin());
14812 compileAndRun<int>(proc);
14813 unsigned storeCount = 0;
14814 for (Value* value : proc.values()) {
14815 if (isStore(value->opcode()))
14816 storeCount++;
14817 }
14818 CHECK_EQ(storeCount, 2u);
14819}
14820
14821void testMoveConstants()
14822{
14823 auto check = [] (Procedure& proc) {
14824 proc.resetReachability();
14825
14826 if (shouldBeVerbose()) {
14827 dataLog("IR before:\n");
14828 dataLog(proc);
14829 }
14830
14831 moveConstants(proc);
14832
14833 if (shouldBeVerbose()) {
14834 dataLog("IR after:\n");
14835 dataLog(proc);
14836 }
14837
14838 UseCounts useCounts(proc);
14839 unsigned count = 0;
14840 for (Value* value : proc.values()) {
14841 if (useCounts.numUses(value) && value->hasInt64())
14842 count++;
14843 }
14844
14845 if (count == 1)
14846 return;
14847
14848 crashLock.lock();
14849 dataLog("Fail in testMoveConstants: got more than one Const64:\n");
14850 dataLog(proc);
14851 CRASH();
14852 };
14853
14854 {
14855 Procedure proc;
14856 BasicBlock* root = proc.addBlock();
14857 Value* a = root->appendNew<MemoryValue>(
14858 proc, Load, pointerType(), Origin(),
14859 root->appendNew<ConstPtrValue>(proc, Origin(), 0x123412341234));
14860 Value* b = root->appendNew<MemoryValue>(
14861 proc, Load, pointerType(), Origin(),
14862 root->appendNew<ConstPtrValue>(proc, Origin(), 0x123412341334));
14863 root->appendNew<CCallValue>(proc, Void, Origin(), a, b);
14864 root->appendNew<Value>(proc, Return, Origin());
14865 check(proc);
14866 }
14867
14868 {
14869 Procedure proc;
14870 BasicBlock* root = proc.addBlock();
14871 Value* x = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
14872 Value* a = root->appendNew<Value>(
14873 proc, Add, Origin(), x, root->appendNew<ConstPtrValue>(proc, Origin(), 0x123412341234));
14874 Value* b = root->appendNew<Value>(
14875 proc, Add, Origin(), x, root->appendNew<ConstPtrValue>(proc, Origin(), -0x123412341234));
14876 root->appendNew<CCallValue>(proc, Void, Origin(), a, b);
14877 root->appendNew<Value>(proc, Return, Origin());
14878 check(proc);
14879 }
14880}
14881
14882void testPCOriginMapDoesntInsertNops()
14883{
14884 Procedure proc;
14885 BasicBlock* root = proc.addBlock();
14886
14887 CCallHelpers::Label watchpointLabel;
14888
14889 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
14890 patchpoint->setGenerator(
14891 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
14892 watchpointLabel = jit.watchpointLabel();
14893 });
14894
14895 patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
14896 patchpoint->setGenerator(
14897 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
14898 CCallHelpers::Label labelIgnoringWatchpoints = jit.labelIgnoringWatchpoints();
14899
14900 CHECK(watchpointLabel == labelIgnoringWatchpoints);
14901 });
14902
14903 root->appendNew<Value>(proc, Return, Origin());
14904
14905 compileProc(proc);
14906}
14907
14908void testPinRegisters()
14909{
14910 auto go = [&] (bool pin) {
14911 Procedure proc;
14912 RegisterSet csrs;
14913 csrs.merge(RegisterSet::calleeSaveRegisters());
14914 csrs.exclude(RegisterSet::stackRegisters());
14915 if (pin) {
14916 csrs.forEach(
14917 [&] (Reg reg) {
14918 proc.pinRegister(reg);
14919 });
14920 }
14921 BasicBlock* root = proc.addBlock();
14922 Value* a = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
14923 Value* b = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
14924 Value* c = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
14925 Value* d = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::regCS0);
14926 root->appendNew<CCallValue>(
14927 proc, Void, Origin(),
14928 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<intptr_t>(0x1234)));
14929 root->appendNew<CCallValue>(
14930 proc, Void, Origin(),
14931 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<intptr_t>(0x1235)),
14932 a, b, c);
14933 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
14934 patchpoint->appendSomeRegister(d);
14935 unsigned optLevel = proc.optLevel();
14936 patchpoint->setGenerator(
14937 [&] (CCallHelpers&, const StackmapGenerationParams& params) {
14938 if (optLevel > 1)
14939 CHECK_EQ(params[0].gpr(), GPRInfo::regCS0);
14940 });
14941 root->appendNew<Value>(proc, Return, Origin());
14942 auto code = compileProc(proc);
14943 bool usesCSRs = false;
14944 for (Air::BasicBlock* block : proc.code()) {
14945 for (Air::Inst& inst : *block) {
14946 if (inst.kind.opcode == Air::Patch && inst.origin == patchpoint)
14947 continue;
14948 inst.forEachTmpFast(
14949 [&] (Air::Tmp tmp) {
14950 if (tmp.isReg())
14951 usesCSRs |= csrs.get(tmp.reg());
14952 });
14953 }
14954 }
14955 if (proc.optLevel() < 2) {
14956 // Our less good register allocators may use the
14957 // pinned CSRs in a move.
14958 usesCSRs = false;
14959 }
14960 for (const RegisterAtOffset& regAtOffset : proc.calleeSaveRegisterAtOffsetList())
14961 usesCSRs |= csrs.get(regAtOffset.reg());
14962 CHECK_EQ(usesCSRs, !pin);
14963 };
14964
14965 go(true);
14966 go(false);
14967}
14968
14969void testX86LeaAddAddShlLeft()
14970{
14971 // Add(Add(Shl(@x, $c), @y), $d)
14972 Procedure proc;
14973 BasicBlock* root = proc.addBlock();
14974 Value* result = root->appendNew<Value>(
14975 proc, Add, Origin(),
14976 root->appendNew<Value>(
14977 proc, Add, Origin(),
14978 root->appendNew<Value>(
14979 proc, Shl, Origin(),
14980 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
14981 root->appendNew<Const32Value>(proc, Origin(), 2)),
14982 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
14983 root->appendNew<ConstPtrValue>(proc, Origin(), 100));
14984 root->appendNew<Value>(proc, Return, Origin(), result);
14985
14986 auto code = compileProc(proc);
14987 if (proc.optLevel() > 1)
14988 checkUsesInstruction(*code, "lea 0x64(%rdi,%rsi,4), %rax");
14989 else
14990 checkUsesInstruction(*code, "lea");
14991 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), (1 + (2 << 2)) + 100);
14992}
14993
14994void testX86LeaAddAddShlRight()
14995{
14996 // Add(Add(@x, Shl(@y, $c)), $d)
14997 Procedure proc;
14998 BasicBlock* root = proc.addBlock();
14999 Value* result = root->appendNew<Value>(
15000 proc, Add, Origin(),
15001 root->appendNew<Value>(
15002 proc, Add, Origin(),
15003 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15004 root->appendNew<Value>(
15005 proc, Shl, Origin(),
15006 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15007 root->appendNew<Const32Value>(proc, Origin(), 2))),
15008 root->appendNew<ConstPtrValue>(proc, Origin(), 100));
15009 root->appendNew<Value>(proc, Return, Origin(), result);
15010
15011 auto code = compileProc(proc);
15012 if (proc.optLevel() > 1)
15013 checkUsesInstruction(*code, "lea 0x64(%rdi,%rsi,4), %rax");
15014 else
15015 checkUsesInstruction(*code, "lea");
15016 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), (1 + (2 << 2)) + 100);
15017}
15018
15019void testX86LeaAddAdd()
15020{
15021 // Add(Add(@x, @y), $c)
15022 Procedure proc;
15023 BasicBlock* root = proc.addBlock();
15024 Value* result = root->appendNew<Value>(
15025 proc, Add, Origin(),
15026 root->appendNew<Value>(
15027 proc, Add, Origin(),
15028 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15029 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
15030 root->appendNew<ConstPtrValue>(proc, Origin(), 100));
15031 root->appendNew<Value>(proc, Return, Origin(), result);
15032
15033 auto code = compileProc(proc);
15034 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), (1 + 2) + 100);
15035 if (proc.optLevel() > 1) {
15036 checkDisassembly(
15037 *code,
15038 [&] (const char* disassembly) -> bool {
15039 return strstr(disassembly, "lea 0x64(%rdi,%rsi), %rax")
15040 || strstr(disassembly, "lea 0x64(%rsi,%rdi), %rax");
15041 },
15042 "Expected to find something like lea 0x64(%rdi,%rsi), %rax but didn't!");
15043 }
15044}
15045
15046void testX86LeaAddShlRight()
15047{
15048 // Add(Shl(@x, $c), @y)
15049 Procedure proc;
15050 BasicBlock* root = proc.addBlock();
15051 Value* result = root->appendNew<Value>(
15052 proc, Add, Origin(),
15053 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15054 root->appendNew<Value>(
15055 proc, Shl, Origin(),
15056 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15057 root->appendNew<Const32Value>(proc, Origin(), 2)));
15058 root->appendNew<Value>(proc, Return, Origin(), result);
15059
15060 auto code = compileProc(proc);
15061 if (proc.optLevel() > 1)
15062 checkUsesInstruction(*code, "lea (%rdi,%rsi,4), %rax");
15063 else
15064 checkUsesInstruction(*code, "lea");
15065 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + (2 << 2));
15066}
15067
15068void testX86LeaAddShlLeftScale1()
15069{
15070 // Add(Shl(@x, $c), @y)
15071 Procedure proc;
15072 BasicBlock* root = proc.addBlock();
15073 Value* result = root->appendNew<Value>(
15074 proc, Add, Origin(),
15075 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15076 root->appendNew<Value>(
15077 proc, Shl, Origin(),
15078 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15079 root->appendNew<Const32Value>(proc, Origin(), 0)));
15080 root->appendNew<Value>(proc, Return, Origin(), result);
15081
15082 auto code = compileProc(proc);
15083 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + 2);
15084 if (proc.optLevel() > 1) {
15085 checkDisassembly(
15086 *code,
15087 [&] (const char* disassembly) -> bool {
15088 return strstr(disassembly, "lea (%rdi,%rsi), %rax")
15089 || strstr(disassembly, "lea (%rsi,%rdi), %rax");
15090 },
15091 "Expected to find something like lea (%rdi,%rsi), %rax but didn't!");
15092 }
15093}
15094
15095void testX86LeaAddShlLeftScale2()
15096{
15097 // Add(Shl(@x, $c), @y)
15098 Procedure proc;
15099 BasicBlock* root = proc.addBlock();
15100 Value* result = root->appendNew<Value>(
15101 proc, Add, Origin(),
15102 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15103 root->appendNew<Value>(
15104 proc, Shl, Origin(),
15105 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15106 root->appendNew<Const32Value>(proc, Origin(), 1)));
15107 root->appendNew<Value>(proc, Return, Origin(), result);
15108
15109 auto code = compileProc(proc);
15110 if (proc.optLevel() > 1)
15111 checkUsesInstruction(*code, "lea (%rdi,%rsi,2), %rax");
15112 else
15113 checkUsesInstruction(*code, "lea");
15114 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + (2 << 1));
15115}
15116
15117void testX86LeaAddShlLeftScale4()
15118{
15119 // Add(Shl(@x, $c), @y)
15120 Procedure proc;
15121 BasicBlock* root = proc.addBlock();
15122 Value* result = root->appendNew<Value>(
15123 proc, Add, Origin(),
15124 root->appendNew<Value>(
15125 proc, Shl, Origin(),
15126 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15127 root->appendNew<Const32Value>(proc, Origin(), 2)),
15128 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15129 root->appendNew<Value>(proc, Return, Origin(), result);
15130
15131 auto code = compileProc(proc);
15132 if (proc.optLevel() > 1)
15133 checkUsesInstruction(*code, "lea (%rdi,%rsi,4), %rax");
15134 else
15135 checkUsesInstruction(*code, "lea");
15136 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + (2 << 2));
15137}
15138
15139void testX86LeaAddShlLeftScale8()
15140{
15141 // Add(Shl(@x, $c), @y)
15142 Procedure proc;
15143 BasicBlock* root = proc.addBlock();
15144 Value* result = root->appendNew<Value>(
15145 proc, Add, Origin(),
15146 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15147 root->appendNew<Value>(
15148 proc, Shl, Origin(),
15149 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15150 root->appendNew<Const32Value>(proc, Origin(), 3)));
15151 root->appendNew<Value>(proc, Return, Origin(), result);
15152
15153 auto code = compileProc(proc);
15154 if (proc.optLevel() > 1)
15155 checkUsesInstruction(*code, "lea (%rdi,%rsi,8), %rax");
15156 else
15157 checkUsesInstruction(*code, "lea");
15158 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + (2 << 3));
15159}
15160
15161void testAddShl32()
15162{
15163 // Add(Shl(@x, $c), @y)
15164 Procedure proc;
15165 BasicBlock* root = proc.addBlock();
15166 Value* result = root->appendNew<Value>(
15167 proc, Add, Origin(),
15168 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15169 root->appendNew<Value>(
15170 proc, Shl, Origin(),
15171 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15172 root->appendNew<Const32Value>(proc, Origin(), 32)));
15173 root->appendNew<Value>(proc, Return, Origin(), result);
15174
15175 auto code = compileProc(proc);
15176 CHECK_EQ(invoke<int64_t>(*code, 1, 2), 1 + (static_cast<int64_t>(2) << static_cast<int64_t>(32)));
15177}
15178
15179void testAddShl64()
15180{
15181 // Add(Shl(@x, $c), @y)
15182 Procedure proc;
15183 BasicBlock* root = proc.addBlock();
15184 Value* result = root->appendNew<Value>(
15185 proc, Add, Origin(),
15186 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15187 root->appendNew<Value>(
15188 proc, Shl, Origin(),
15189 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15190 root->appendNew<Const32Value>(proc, Origin(), 64)));
15191 root->appendNew<Value>(proc, Return, Origin(), result);
15192
15193 auto code = compileProc(proc);
15194 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + 2);
15195}
15196
15197void testAddShl65()
15198{
15199 // Add(Shl(@x, $c), @y)
15200 Procedure proc;
15201 BasicBlock* root = proc.addBlock();
15202 Value* result = root->appendNew<Value>(
15203 proc, Add, Origin(),
15204 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15205 root->appendNew<Value>(
15206 proc, Shl, Origin(),
15207 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15208 root->appendNew<Const32Value>(proc, Origin(), 65)));
15209 root->appendNew<Value>(proc, Return, Origin(), result);
15210
15211 auto code = compileProc(proc);
15212 CHECK_EQ(invoke<intptr_t>(*code, 1, 2), 1 + (2 << 1));
15213}
15214
15215void testReduceStrengthReassociation(bool flip)
15216{
15217 // Add(Add(@x, $c), @y) -> Add(Add(@x, @y), $c)
15218 // and
15219 // Add(@y, Add(@x, $c)) -> Add(Add(@x, @y), $c)
15220 Procedure proc;
15221 BasicBlock* root = proc.addBlock();
15222 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
15223 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
15224
15225 Value* innerAdd = root->appendNew<Value>(
15226 proc, Add, Origin(), arg1,
15227 root->appendNew<ConstPtrValue>(proc, Origin(), 42));
15228
15229 Value* outerAdd;
15230 if (flip)
15231 outerAdd = root->appendNew<Value>(proc, Add, Origin(), arg2, innerAdd);
15232 else
15233 outerAdd = root->appendNew<Value>(proc, Add, Origin(), innerAdd, arg2);
15234
15235 root->appendNew<Value>(proc, Return, Origin(), outerAdd);
15236
15237 proc.resetReachability();
15238
15239 if (shouldBeVerbose()) {
15240 dataLog("IR before reduceStrength:\n");
15241 dataLog(proc);
15242 }
15243
15244 reduceStrength(proc);
15245
15246 if (shouldBeVerbose()) {
15247 dataLog("IR after reduceStrength:\n");
15248 dataLog(proc);
15249 }
15250
15251 CHECK_EQ(root->last()->opcode(), Return);
15252 CHECK_EQ(root->last()->child(0)->opcode(), Add);
15253 CHECK(root->last()->child(0)->child(1)->isIntPtr(42));
15254 CHECK_EQ(root->last()->child(0)->child(0)->opcode(), Add);
15255 CHECK(
15256 (root->last()->child(0)->child(0)->child(0) == arg1 && root->last()->child(0)->child(0)->child(1) == arg2) ||
15257 (root->last()->child(0)->child(0)->child(0) == arg2 && root->last()->child(0)->child(0)->child(1) == arg1));
15258}
15259
15260void testLoadBaseIndexShift2()
15261{
15262 Procedure proc;
15263 BasicBlock* root = proc.addBlock();
15264 root->appendNew<Value>(
15265 proc, Return, Origin(),
15266 root->appendNew<MemoryValue>(
15267 proc, Load, Int32, Origin(),
15268 root->appendNew<Value>(
15269 proc, Add, Origin(),
15270 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15271 root->appendNew<Value>(
15272 proc, Shl, Origin(),
15273 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15274 root->appendNew<Const32Value>(proc, Origin(), 2)))));
15275 auto code = compileProc(proc);
15276 if (isX86() && proc.optLevel() > 1)
15277 checkUsesInstruction(*code, "(%rdi,%rsi,4)");
15278 int32_t value = 12341234;
15279 char* ptr = bitwise_cast<char*>(&value);
15280 for (unsigned i = 0; i < 10; ++i)
15281 CHECK_EQ(invoke<int32_t>(*code, ptr - (static_cast<intptr_t>(1) << static_cast<intptr_t>(2)) * i, i), 12341234);
15282}
15283
15284void testLoadBaseIndexShift32()
15285{
15286#if CPU(ADDRESS64)
15287 Procedure proc;
15288 BasicBlock* root = proc.addBlock();
15289 root->appendNew<Value>(
15290 proc, Return, Origin(),
15291 root->appendNew<MemoryValue>(
15292 proc, Load, Int32, Origin(),
15293 root->appendNew<Value>(
15294 proc, Add, Origin(),
15295 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15296 root->appendNew<Value>(
15297 proc, Shl, Origin(),
15298 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1),
15299 root->appendNew<Const32Value>(proc, Origin(), 32)))));
15300 auto code = compileProc(proc);
15301 int32_t value = 12341234;
15302 char* ptr = bitwise_cast<char*>(&value);
15303 for (unsigned i = 0; i < 10; ++i)
15304 CHECK_EQ(invoke<int32_t>(*code, ptr - (static_cast<intptr_t>(1) << static_cast<intptr_t>(32)) * i, i), 12341234);
15305#endif
15306}
15307
15308void testOptimizeMaterialization()
15309{
15310 Procedure proc;
15311 if (proc.optLevel() < 2)
15312 return;
15313
15314 BasicBlock* root = proc.addBlock();
15315 root->appendNew<CCallValue>(
15316 proc, Void, Origin(),
15317 root->appendNew<ConstPtrValue>(proc, Origin(), 0x123423453456llu),
15318 root->appendNew<ConstPtrValue>(proc, Origin(), 0x123423453456llu + 35));
15319 root->appendNew<Value>(proc, Return, Origin());
15320
15321 auto code = compileProc(proc);
15322 bool found = false;
15323 for (Air::BasicBlock* block : proc.code()) {
15324 for (Air::Inst& inst : *block) {
15325 if (inst.kind.opcode != Air::Add64)
15326 continue;
15327 if (inst.args[0] != Air::Arg::imm(35))
15328 continue;
15329 found = true;
15330 }
15331 }
15332 CHECK(found);
15333}
15334
15335template<typename Func>
15336void generateLoop(Procedure& proc, const Func& func)
15337{
15338 BasicBlock* root = proc.addBlock();
15339 BasicBlock* loop = proc.addBlock();
15340 BasicBlock* end = proc.addBlock();
15341
15342 UpsilonValue* initialIndex = root->appendNew<UpsilonValue>(
15343 proc, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
15344 root->appendNew<Value>(proc, Jump, Origin());
15345 root->setSuccessors(loop);
15346
15347 Value* index = loop->appendNew<Value>(proc, Phi, Int32, Origin());
15348 initialIndex->setPhi(index);
15349
15350 Value* one = func(loop, index);
15351
15352 Value* nextIndex = loop->appendNew<Value>(proc, Add, Origin(), index, one);
15353 UpsilonValue* loopIndex = loop->appendNew<UpsilonValue>(proc, Origin(), nextIndex);
15354 loopIndex->setPhi(index);
15355 loop->appendNew<Value>(
15356 proc, Branch, Origin(),
15357 loop->appendNew<Value>(
15358 proc, LessThan, Origin(), nextIndex,
15359 loop->appendNew<Const32Value>(proc, Origin(), 100)));
15360 loop->setSuccessors(loop, end);
15361
15362 end->appendNew<Value>(proc, Return, Origin());
15363}
15364
15365std::array<int, 100> makeArrayForLoops()
15366{
15367 std::array<int, 100> result;
15368 for (unsigned i = 0; i < result.size(); ++i)
15369 result[i] = i & 1;
15370 return result;
15371}
15372
15373template<typename Func>
15374void generateLoopNotBackwardsDominant(Procedure& proc, std::array<int, 100>& array, const Func& func)
15375{
15376 BasicBlock* root = proc.addBlock();
15377 BasicBlock* loopHeader = proc.addBlock();
15378 BasicBlock* loopCall = proc.addBlock();
15379 BasicBlock* loopFooter = proc.addBlock();
15380 BasicBlock* end = proc.addBlock();
15381
15382 UpsilonValue* initialIndex = root->appendNew<UpsilonValue>(
15383 proc, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
15384 // If you look carefully, you'll notice that this is an extremely sneaky use of Upsilon that demonstrates
15385 // the extent to which our SSA is different from normal-person SSA.
15386 UpsilonValue* defaultOne = root->appendNew<UpsilonValue>(
15387 proc, Origin(), root->appendNew<Const32Value>(proc, Origin(), 1));
15388 root->appendNew<Value>(proc, Jump, Origin());
15389 root->setSuccessors(loopHeader);
15390
15391 Value* index = loopHeader->appendNew<Value>(proc, Phi, Int32, Origin());
15392 initialIndex->setPhi(index);
15393
15394 // if (array[index])
15395 loopHeader->appendNew<Value>(
15396 proc, Branch, Origin(),
15397 loopHeader->appendNew<MemoryValue>(
15398 proc, Load, Int32, Origin(),
15399 loopHeader->appendNew<Value>(
15400 proc, Add, Origin(),
15401 loopHeader->appendNew<ConstPtrValue>(proc, Origin(), &array),
15402 loopHeader->appendNew<Value>(
15403 proc, Mul, Origin(),
15404 loopHeader->appendNew<Value>(proc, ZExt32, Origin(), index),
15405 loopHeader->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))))));
15406 loopHeader->setSuccessors(loopCall, loopFooter);
15407
15408 Value* functionCall = func(loopCall, index);
15409 UpsilonValue* oneFromFunction = loopCall->appendNew<UpsilonValue>(proc, Origin(), functionCall);
15410 loopCall->appendNew<Value>(proc, Jump, Origin());
15411 loopCall->setSuccessors(loopFooter);
15412
15413 Value* one = loopFooter->appendNew<Value>(proc, Phi, Int32, Origin());
15414 defaultOne->setPhi(one);
15415 oneFromFunction->setPhi(one);
15416 Value* nextIndex = loopFooter->appendNew<Value>(proc, Add, Origin(), index, one);
15417 UpsilonValue* loopIndex = loopFooter->appendNew<UpsilonValue>(proc, Origin(), nextIndex);
15418 loopIndex->setPhi(index);
15419 loopFooter->appendNew<Value>(
15420 proc, Branch, Origin(),
15421 loopFooter->appendNew<Value>(
15422 proc, LessThan, Origin(), nextIndex,
15423 loopFooter->appendNew<Const32Value>(proc, Origin(), 100)));
15424 loopFooter->setSuccessors(loopHeader, end);
15425
15426 end->appendNew<Value>(proc, Return, Origin());
15427}
15428
15429static int oneFunction(int* callCount)
15430{
15431 (*callCount)++;
15432 return 1;
15433}
15434
15435static void noOpFunction()
15436{
15437}
15438
15439void testLICMPure()
15440{
15441 Procedure proc;
15442
15443 if (proc.optLevel() < 2)
15444 return;
15445
15446 generateLoop(
15447 proc,
15448 [&] (BasicBlock* loop, Value*) -> Value* {
15449 return loop->appendNew<CCallValue>(
15450 proc, Int32, Origin(), Effects::none(),
15451 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15452 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15453 });
15454
15455 unsigned callCount = 0;
15456 compileAndRun<void>(proc, &callCount);
15457 CHECK_EQ(callCount, 1u);
15458}
15459
15460void testLICMPureSideExits()
15461{
15462 Procedure proc;
15463 if (proc.optLevel() < 2)
15464 return;
15465 generateLoop(
15466 proc,
15467 [&] (BasicBlock* loop, Value*) -> Value* {
15468 Effects effects = Effects::none();
15469 effects.exitsSideways = true;
15470 loop->appendNew<CCallValue>(
15471 proc, Void, Origin(), effects,
15472 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(noOpFunction, B3CCallPtrTag)));
15473
15474 return loop->appendNew<CCallValue>(
15475 proc, Int32, Origin(), Effects::none(),
15476 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15477 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15478 });
15479
15480 unsigned callCount = 0;
15481 compileAndRun<void>(proc, &callCount);
15482 CHECK_EQ(callCount, 1u);
15483}
15484
15485void testLICMPureWritesPinned()
15486{
15487 Procedure proc;
15488 if (proc.optLevel() < 2)
15489 return;
15490 generateLoop(
15491 proc,
15492 [&] (BasicBlock* loop, Value*) -> Value* {
15493 Effects effects = Effects::none();
15494 effects.writesPinned = true;
15495 loop->appendNew<CCallValue>(
15496 proc, Void, Origin(), effects,
15497 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(noOpFunction, B3CCallPtrTag)));
15498
15499 return loop->appendNew<CCallValue>(
15500 proc, Int32, Origin(), Effects::none(),
15501 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15502 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15503 });
15504
15505 unsigned callCount = 0;
15506 compileAndRun<void>(proc, &callCount);
15507 CHECK_EQ(callCount, 1u);
15508}
15509
15510void testLICMPureWrites()
15511{
15512 Procedure proc;
15513 if (proc.optLevel() < 2)
15514 return;
15515 generateLoop(
15516 proc,
15517 [&] (BasicBlock* loop, Value*) -> Value* {
15518 Effects effects = Effects::none();
15519 effects.writes = HeapRange(63479);
15520 loop->appendNew<CCallValue>(
15521 proc, Void, Origin(), effects,
15522 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(noOpFunction, B3CCallPtrTag)));
15523
15524 return loop->appendNew<CCallValue>(
15525 proc, Int32, Origin(), Effects::none(),
15526 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15527 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15528 });
15529
15530 unsigned callCount = 0;
15531 compileAndRun<void>(proc, &callCount);
15532 CHECK_EQ(callCount, 1u);
15533}
15534
15535void testLICMReadsLocalState()
15536{
15537 Procedure proc;
15538 generateLoop(
15539 proc,
15540 [&] (BasicBlock* loop, Value*) -> Value* {
15541 Effects effects = Effects::none();
15542 effects.readsLocalState = true;
15543 return loop->appendNew<CCallValue>(
15544 proc, Int32, Origin(), effects,
15545 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15546 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15547 });
15548
15549 unsigned callCount = 0;
15550 compileAndRun<void>(proc, &callCount);
15551 CHECK_EQ(callCount, 100u); // We'll fail to hoist because the loop has Upsilons.
15552}
15553
15554void testLICMReadsPinned()
15555{
15556 Procedure proc;
15557 if (proc.optLevel() < 2)
15558 return;
15559 generateLoop(
15560 proc,
15561 [&] (BasicBlock* loop, Value*) -> Value* {
15562 Effects effects = Effects::none();
15563 effects.readsPinned = true;
15564 return loop->appendNew<CCallValue>(
15565 proc, Int32, Origin(), effects,
15566 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15567 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15568 });
15569
15570 unsigned callCount = 0;
15571 compileAndRun<void>(proc, &callCount);
15572 CHECK_EQ(callCount, 1u);
15573}
15574
15575void testLICMReads()
15576{
15577 Procedure proc;
15578 if (proc.optLevel() < 2)
15579 return;
15580 generateLoop(
15581 proc,
15582 [&] (BasicBlock* loop, Value*) -> Value* {
15583 Effects effects = Effects::none();
15584 effects.reads = HeapRange::top();
15585 return loop->appendNew<CCallValue>(
15586 proc, Int32, Origin(), effects,
15587 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15588 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15589 });
15590
15591 unsigned callCount = 0;
15592 compileAndRun<void>(proc, &callCount);
15593 CHECK_EQ(callCount, 1u);
15594}
15595
15596void testLICMPureNotBackwardsDominant()
15597{
15598 Procedure proc;
15599 if (proc.optLevel() < 2)
15600 return;
15601 auto array = makeArrayForLoops();
15602 generateLoopNotBackwardsDominant(
15603 proc, array,
15604 [&] (BasicBlock* loop, Value*) -> Value* {
15605 return loop->appendNew<CCallValue>(
15606 proc, Int32, Origin(), Effects::none(),
15607 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15608 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15609 });
15610
15611 unsigned callCount = 0;
15612 compileAndRun<void>(proc, &callCount);
15613 CHECK_EQ(callCount, 1u);
15614}
15615
15616void testLICMPureFoiledByChild()
15617{
15618 Procedure proc;
15619 generateLoop(
15620 proc,
15621 [&] (BasicBlock* loop, Value* index) -> Value* {
15622 return loop->appendNew<CCallValue>(
15623 proc, Int32, Origin(), Effects::none(),
15624 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15625 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15626 index);
15627 });
15628
15629 unsigned callCount = 0;
15630 compileAndRun<void>(proc, &callCount);
15631 CHECK_EQ(callCount, 100u);
15632}
15633
15634void testLICMPureNotBackwardsDominantFoiledByChild()
15635{
15636 Procedure proc;
15637 if (proc.optLevel() < 2)
15638 return;
15639 auto array = makeArrayForLoops();
15640 generateLoopNotBackwardsDominant(
15641 proc, array,
15642 [&] (BasicBlock* loop, Value* index) -> Value* {
15643 return loop->appendNew<CCallValue>(
15644 proc, Int32, Origin(), Effects::none(),
15645 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15646 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
15647 index);
15648 });
15649
15650 unsigned callCount = 0;
15651 compileAndRun<void>(proc, &callCount);
15652 CHECK_EQ(callCount, 50u);
15653}
15654
15655void testLICMExitsSideways()
15656{
15657 Procedure proc;
15658 generateLoop(
15659 proc,
15660 [&] (BasicBlock* loop, Value*) -> Value* {
15661 Effects effects = Effects::none();
15662 effects.exitsSideways = true;
15663 return loop->appendNew<CCallValue>(
15664 proc, Int32, Origin(), effects,
15665 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15666 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15667 });
15668
15669 unsigned callCount = 0;
15670 compileAndRun<void>(proc, &callCount);
15671 CHECK_EQ(callCount, 100u);
15672}
15673
15674void testLICMWritesLocalState()
15675{
15676 Procedure proc;
15677 generateLoop(
15678 proc,
15679 [&] (BasicBlock* loop, Value*) -> Value* {
15680 Effects effects = Effects::none();
15681 effects.writesLocalState = true;
15682 return loop->appendNew<CCallValue>(
15683 proc, Int32, Origin(), effects,
15684 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15685 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15686 });
15687
15688 unsigned callCount = 0;
15689 compileAndRun<void>(proc, &callCount);
15690 CHECK_EQ(callCount, 100u);
15691}
15692
15693void testLICMWrites()
15694{
15695 Procedure proc;
15696 generateLoop(
15697 proc,
15698 [&] (BasicBlock* loop, Value*) -> Value* {
15699 Effects effects = Effects::none();
15700 effects.writes = HeapRange(666);
15701 return loop->appendNew<CCallValue>(
15702 proc, Int32, Origin(), effects,
15703 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15704 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15705 });
15706
15707 unsigned callCount = 0;
15708 compileAndRun<void>(proc, &callCount);
15709 CHECK_EQ(callCount, 100u);
15710}
15711
15712void testLICMFence()
15713{
15714 Procedure proc;
15715 generateLoop(
15716 proc,
15717 [&] (BasicBlock* loop, Value*) -> Value* {
15718 Effects effects = Effects::none();
15719 effects.fence = true;
15720 return loop->appendNew<CCallValue>(
15721 proc, Int32, Origin(), effects,
15722 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15723 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15724 });
15725
15726 unsigned callCount = 0;
15727 compileAndRun<void>(proc, &callCount);
15728 CHECK_EQ(callCount, 100u);
15729}
15730
15731void testLICMWritesPinned()
15732{
15733 Procedure proc;
15734 generateLoop(
15735 proc,
15736 [&] (BasicBlock* loop, Value*) -> Value* {
15737 Effects effects = Effects::none();
15738 effects.writesPinned = true;
15739 return loop->appendNew<CCallValue>(
15740 proc, Int32, Origin(), effects,
15741 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15742 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15743 });
15744
15745 unsigned callCount = 0;
15746 compileAndRun<void>(proc, &callCount);
15747 CHECK_EQ(callCount, 100u);
15748}
15749
15750void testLICMControlDependent()
15751{
15752 Procedure proc;
15753 if (proc.optLevel() < 2)
15754 return;
15755 generateLoop(
15756 proc,
15757 [&] (BasicBlock* loop, Value*) -> Value* {
15758 Effects effects = Effects::none();
15759 effects.controlDependent = true;
15760 return loop->appendNew<CCallValue>(
15761 proc, Int32, Origin(), effects,
15762 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15763 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15764 });
15765
15766 unsigned callCount = 0;
15767 compileAndRun<void>(proc, &callCount);
15768 CHECK_EQ(callCount, 1u);
15769}
15770
15771void testLICMControlDependentNotBackwardsDominant()
15772{
15773 Procedure proc;
15774 if (proc.optLevel() < 2)
15775 return;
15776 auto array = makeArrayForLoops();
15777 generateLoopNotBackwardsDominant(
15778 proc, array,
15779 [&] (BasicBlock* loop, Value*) -> Value* {
15780 Effects effects = Effects::none();
15781 effects.controlDependent = true;
15782 return loop->appendNew<CCallValue>(
15783 proc, Int32, Origin(), effects,
15784 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15785 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15786 });
15787
15788 unsigned callCount = 0;
15789 compileAndRun<void>(proc, &callCount);
15790 CHECK_EQ(callCount, 50u);
15791}
15792
15793void testLICMControlDependentSideExits()
15794{
15795 Procedure proc;
15796 generateLoop(
15797 proc,
15798 [&] (BasicBlock* loop, Value*) -> Value* {
15799 Effects effects = Effects::none();
15800 effects.exitsSideways = true;
15801 loop->appendNew<CCallValue>(
15802 proc, Void, Origin(), effects,
15803 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(noOpFunction, B3CCallPtrTag)));
15804
15805 effects = Effects::none();
15806 effects.controlDependent = true;
15807 return loop->appendNew<CCallValue>(
15808 proc, Int32, Origin(), effects,
15809 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15810 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15811 });
15812
15813 unsigned callCount = 0;
15814 compileAndRun<void>(proc, &callCount);
15815 CHECK_EQ(callCount, 100u);
15816}
15817
15818void testLICMReadsPinnedWritesPinned()
15819{
15820 Procedure proc;
15821 generateLoop(
15822 proc,
15823 [&] (BasicBlock* loop, Value*) -> Value* {
15824 Effects effects = Effects::none();
15825 effects.writesPinned = true;
15826 loop->appendNew<CCallValue>(
15827 proc, Void, Origin(), effects,
15828 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(noOpFunction, B3CCallPtrTag)));
15829
15830 effects = Effects::none();
15831 effects.readsPinned = true;
15832 return loop->appendNew<CCallValue>(
15833 proc, Int32, Origin(), effects,
15834 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15835 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15836 });
15837
15838 unsigned callCount = 0;
15839 compileAndRun<void>(proc, &callCount);
15840 CHECK_EQ(callCount, 100u);
15841}
15842
15843void testLICMReadsWritesDifferentHeaps()
15844{
15845 Procedure proc;
15846 if (proc.optLevel() < 2)
15847 return;
15848 generateLoop(
15849 proc,
15850 [&] (BasicBlock* loop, Value*) -> Value* {
15851 Effects effects = Effects::none();
15852 effects.writes = HeapRange(6436);
15853 loop->appendNew<CCallValue>(
15854 proc, Void, Origin(), effects,
15855 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(noOpFunction, B3CCallPtrTag)));
15856
15857 effects = Effects::none();
15858 effects.reads = HeapRange(4886);
15859 return loop->appendNew<CCallValue>(
15860 proc, Int32, Origin(), effects,
15861 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15862 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15863 });
15864
15865 unsigned callCount = 0;
15866 compileAndRun<void>(proc, &callCount);
15867 CHECK_EQ(callCount, 1u);
15868}
15869
15870void testLICMReadsWritesOverlappingHeaps()
15871{
15872 Procedure proc;
15873 generateLoop(
15874 proc,
15875 [&] (BasicBlock* loop, Value*) -> Value* {
15876 Effects effects = Effects::none();
15877 effects.writes = HeapRange(6436, 74458);
15878 loop->appendNew<CCallValue>(
15879 proc, Void, Origin(), effects,
15880 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(noOpFunction, B3CCallPtrTag)));
15881
15882 effects = Effects::none();
15883 effects.reads = HeapRange(48864, 78239);
15884 return loop->appendNew<CCallValue>(
15885 proc, Int32, Origin(), effects,
15886 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15887 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15888 });
15889
15890 unsigned callCount = 0;
15891 compileAndRun<void>(proc, &callCount);
15892 CHECK_EQ(callCount, 100u);
15893}
15894
15895void testLICMDefaultCall()
15896{
15897 Procedure proc;
15898 generateLoop(
15899 proc,
15900 [&] (BasicBlock* loop, Value*) -> Value* {
15901 return loop->appendNew<CCallValue>(
15902 proc, Int32, Origin(),
15903 loop->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(oneFunction, B3CCallPtrTag)),
15904 loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
15905 });
15906
15907 unsigned callCount = 0;
15908 compileAndRun<void>(proc, &callCount);
15909 CHECK_EQ(callCount, 100u);
15910}
15911
15912template<typename T>
15913void testAtomicWeakCAS()
15914{
15915 Type type = NativeTraits<T>::type;
15916 Width width = NativeTraits<T>::width;
15917
15918 auto checkMyDisassembly = [&] (Compilation& compilation, bool fenced) {
15919 if (isX86()) {
15920 checkUsesInstruction(compilation, "lock");
15921 checkUsesInstruction(compilation, "cmpxchg");
15922 } else {
15923 if (fenced) {
15924 checkUsesInstruction(compilation, "ldax");
15925 checkUsesInstruction(compilation, "stlx");
15926 } else {
15927 checkUsesInstruction(compilation, "ldx");
15928 checkUsesInstruction(compilation, "stx");
15929 }
15930 }
15931 };
15932
15933 {
15934 Procedure proc;
15935 BasicBlock* root = proc.addBlock();
15936 BasicBlock* reloop = proc.addBlock();
15937 BasicBlock* done = proc.addBlock();
15938
15939 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
15940 root->appendNew<Value>(proc, Jump, Origin());
15941 root->setSuccessors(reloop);
15942
15943 reloop->appendNew<Value>(
15944 proc, Branch, Origin(),
15945 reloop->appendNew<AtomicValue>(
15946 proc, AtomicWeakCAS, Origin(), width,
15947 reloop->appendIntConstant(proc, Origin(), type, 42),
15948 reloop->appendIntConstant(proc, Origin(), type, 0xbeef),
15949 ptr));
15950 reloop->setSuccessors(done, reloop);
15951
15952 done->appendNew<Value>(proc, Return, Origin());
15953
15954 auto code = compileProc(proc);
15955 T value[2];
15956 value[0] = 42;
15957 value[1] = 13;
15958 invoke<void>(*code, value);
15959 CHECK_EQ(value[0], static_cast<T>(0xbeef));
15960 CHECK_EQ(value[1], 13);
15961 checkMyDisassembly(*code, true);
15962 }
15963
15964 {
15965 Procedure proc;
15966 BasicBlock* root = proc.addBlock();
15967 BasicBlock* reloop = proc.addBlock();
15968 BasicBlock* done = proc.addBlock();
15969
15970 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
15971 root->appendNew<Value>(proc, Jump, Origin());
15972 root->setSuccessors(reloop);
15973
15974 reloop->appendNew<Value>(
15975 proc, Branch, Origin(),
15976 reloop->appendNew<AtomicValue>(
15977 proc, AtomicWeakCAS, Origin(), width,
15978 reloop->appendIntConstant(proc, Origin(), type, 42),
15979 reloop->appendIntConstant(proc, Origin(), type, 0xbeef),
15980 ptr, 0, HeapRange(42), HeapRange()));
15981 reloop->setSuccessors(done, reloop);
15982
15983 done->appendNew<Value>(proc, Return, Origin());
15984
15985 auto code = compileProc(proc);
15986 T value[2];
15987 value[0] = 42;
15988 value[1] = 13;
15989 invoke<void>(*code, value);
15990 CHECK_EQ(value[0], static_cast<T>(0xbeef));
15991 CHECK_EQ(value[1], 13);
15992 checkMyDisassembly(*code, false);
15993 }
15994
15995 {
15996 Procedure proc;
15997 BasicBlock* root = proc.addBlock();
15998 BasicBlock* succ = proc.addBlock();
15999 BasicBlock* fail = proc.addBlock();
16000
16001 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
16002 root->appendNew<Value>(
16003 proc, Branch, Origin(),
16004 root->appendNew<AtomicValue>(
16005 proc, AtomicWeakCAS, Origin(), width,
16006 root->appendIntConstant(proc, Origin(), type, 42),
16007 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16008 ptr));
16009 root->setSuccessors(succ, fail);
16010
16011 succ->appendNew<MemoryValue>(
16012 proc, storeOpcode(GP, width), Origin(),
16013 succ->appendIntConstant(proc, Origin(), type, 100),
16014 ptr);
16015 succ->appendNew<Value>(proc, Return, Origin());
16016
16017 fail->appendNew<Value>(proc, Return, Origin());
16018
16019 auto code = compileProc(proc);
16020 T value[2];
16021 value[0] = 42;
16022 value[1] = 13;
16023 while (value[0] == 42)
16024 invoke<void>(*code, value);
16025 CHECK_EQ(value[0], static_cast<T>(100));
16026 CHECK_EQ(value[1], 13);
16027 value[0] = static_cast<T>(300);
16028 invoke<void>(*code, value);
16029 CHECK_EQ(value[0], static_cast<T>(300));
16030 CHECK_EQ(value[1], 13);
16031 checkMyDisassembly(*code, true);
16032 }
16033
16034 {
16035 Procedure proc;
16036 BasicBlock* root = proc.addBlock();
16037 BasicBlock* succ = proc.addBlock();
16038 BasicBlock* fail = proc.addBlock();
16039
16040 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
16041 root->appendNew<Value>(
16042 proc, Branch, Origin(),
16043 root->appendNew<Value>(
16044 proc, Equal, Origin(),
16045 root->appendNew<AtomicValue>(
16046 proc, AtomicWeakCAS, Origin(), width,
16047 root->appendIntConstant(proc, Origin(), type, 42),
16048 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16049 ptr),
16050 root->appendIntConstant(proc, Origin(), Int32, 0)));
16051 root->setSuccessors(fail, succ);
16052
16053 succ->appendNew<MemoryValue>(
16054 proc, storeOpcode(GP, width), Origin(),
16055 succ->appendIntConstant(proc, Origin(), type, 100),
16056 ptr);
16057 succ->appendNew<Value>(proc, Return, Origin());
16058
16059 fail->appendNew<Value>(proc, Return, Origin());
16060
16061 auto code = compileProc(proc);
16062 T value[2];
16063 value[0] = 42;
16064 value[1] = 13;
16065 while (value[0] == 42)
16066 invoke<void>(*code, value);
16067 CHECK_EQ(value[0], static_cast<T>(100));
16068 CHECK_EQ(value[1], 13);
16069 value[0] = static_cast<T>(300);
16070 invoke<void>(*code, value);
16071 CHECK_EQ(value[0], static_cast<T>(300));
16072 CHECK_EQ(value[1], 13);
16073 checkMyDisassembly(*code, true);
16074 }
16075
16076 {
16077 Procedure proc;
16078 BasicBlock* root = proc.addBlock();
16079 root->appendNew<Value>(
16080 proc, Return, Origin(),
16081 root->appendNew<AtomicValue>(
16082 proc, AtomicWeakCAS, Origin(), width,
16083 root->appendIntConstant(proc, Origin(), type, 42),
16084 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16085 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
16086
16087 auto code = compileProc(proc);
16088 T value[2];
16089 value[0] = 42;
16090 value[1] = 13;
16091 while (!invoke<bool>(*code, value)) { }
16092 CHECK_EQ(value[0], static_cast<T>(0xbeef));
16093 CHECK_EQ(value[1], 13);
16094
16095 value[0] = static_cast<T>(300);
16096 CHECK(!invoke<bool>(*code, value));
16097 CHECK_EQ(value[0], static_cast<T>(300));
16098 CHECK_EQ(value[1], 13);
16099 checkMyDisassembly(*code, true);
16100 }
16101
16102 {
16103 Procedure proc;
16104 BasicBlock* root = proc.addBlock();
16105 root->appendNew<Value>(
16106 proc, Return, Origin(),
16107 root->appendNew<Value>(
16108 proc, Equal, Origin(),
16109 root->appendNew<AtomicValue>(
16110 proc, AtomicWeakCAS, Origin(), width,
16111 root->appendIntConstant(proc, Origin(), type, 42),
16112 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16113 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
16114 root->appendNew<Const32Value>(proc, Origin(), 0)));
16115
16116 auto code = compileProc(proc);
16117 T value[2];
16118 value[0] = 42;
16119 value[1] = 13;
16120 while (invoke<bool>(*code, value)) { }
16121 CHECK_EQ(value[0], static_cast<T>(0xbeef));
16122 CHECK_EQ(value[1], 13);
16123
16124 value[0] = static_cast<T>(300);
16125 CHECK(invoke<bool>(*code, value));
16126 CHECK_EQ(value[0], static_cast<T>(300));
16127 CHECK_EQ(value[1], 13);
16128 checkMyDisassembly(*code, true);
16129 }
16130
16131 {
16132 Procedure proc;
16133 BasicBlock* root = proc.addBlock();
16134 root->appendNew<Value>(
16135 proc, Return, Origin(),
16136 root->appendNew<AtomicValue>(
16137 proc, AtomicWeakCAS, Origin(), width,
16138 root->appendIntConstant(proc, Origin(), type, 42),
16139 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16140 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
16141 42));
16142
16143 auto code = compileProc(proc);
16144 T value[2];
16145 value[0] = 42;
16146 value[1] = 13;
16147 while (!invoke<bool>(*code, bitwise_cast<intptr_t>(value) - 42)) { }
16148 CHECK_EQ(value[0], static_cast<T>(0xbeef));
16149 CHECK_EQ(value[1], 13);
16150
16151 value[0] = static_cast<T>(300);
16152 CHECK(!invoke<bool>(*code, bitwise_cast<intptr_t>(value) - 42));
16153 CHECK_EQ(value[0], static_cast<T>(300));
16154 CHECK_EQ(value[1], 13);
16155 checkMyDisassembly(*code, true);
16156 }
16157}
16158
16159template<typename T>
16160void testAtomicStrongCAS()
16161{
16162 Type type = NativeTraits<T>::type;
16163 Width width = NativeTraits<T>::width;
16164
16165 auto checkMyDisassembly = [&] (Compilation& compilation, bool fenced) {
16166 if (isX86()) {
16167 checkUsesInstruction(compilation, "lock");
16168 checkUsesInstruction(compilation, "cmpxchg");
16169 } else {
16170 if (fenced) {
16171 checkUsesInstruction(compilation, "ldax");
16172 checkUsesInstruction(compilation, "stlx");
16173 } else {
16174 checkUsesInstruction(compilation, "ldx");
16175 checkUsesInstruction(compilation, "stx");
16176 }
16177 }
16178 };
16179
16180 {
16181 Procedure proc;
16182 BasicBlock* root = proc.addBlock();
16183 BasicBlock* succ = proc.addBlock();
16184 BasicBlock* fail = proc.addBlock();
16185
16186 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
16187 root->appendNew<Value>(
16188 proc, Branch, Origin(),
16189 root->appendNew<Value>(
16190 proc, Equal, Origin(),
16191 root->appendNew<AtomicValue>(
16192 proc, AtomicStrongCAS, Origin(), width,
16193 root->appendIntConstant(proc, Origin(), type, 42),
16194 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16195 ptr),
16196 root->appendIntConstant(proc, Origin(), type, 42)));
16197 root->setSuccessors(succ, fail);
16198
16199 succ->appendNew<MemoryValue>(
16200 proc, storeOpcode(GP, width), Origin(),
16201 succ->appendIntConstant(proc, Origin(), type, 100),
16202 ptr);
16203 succ->appendNew<Value>(proc, Return, Origin());
16204
16205 fail->appendNew<Value>(proc, Return, Origin());
16206
16207 auto code = compileProc(proc);
16208 T value[2];
16209 value[0] = 42;
16210 value[1] = 13;
16211 invoke<void>(*code, value);
16212 CHECK_EQ(value[0], static_cast<T>(100));
16213 CHECK_EQ(value[1], 13);
16214 value[0] = static_cast<T>(300);
16215 invoke<void>(*code, value);
16216 CHECK_EQ(value[0], static_cast<T>(300));
16217 CHECK_EQ(value[1], 13);
16218 checkMyDisassembly(*code, true);
16219 }
16220
16221 {
16222 Procedure proc;
16223 BasicBlock* root = proc.addBlock();
16224 BasicBlock* succ = proc.addBlock();
16225 BasicBlock* fail = proc.addBlock();
16226
16227 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
16228 root->appendNew<Value>(
16229 proc, Branch, Origin(),
16230 root->appendNew<Value>(
16231 proc, Equal, Origin(),
16232 root->appendNew<AtomicValue>(
16233 proc, AtomicStrongCAS, Origin(), width,
16234 root->appendIntConstant(proc, Origin(), type, 42),
16235 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16236 ptr, 0, HeapRange(42), HeapRange()),
16237 root->appendIntConstant(proc, Origin(), type, 42)));
16238 root->setSuccessors(succ, fail);
16239
16240 succ->appendNew<MemoryValue>(
16241 proc, storeOpcode(GP, width), Origin(),
16242 succ->appendIntConstant(proc, Origin(), type, 100),
16243 ptr);
16244 succ->appendNew<Value>(proc, Return, Origin());
16245
16246 fail->appendNew<Value>(proc, Return, Origin());
16247
16248 auto code = compileProc(proc);
16249 T value[2];
16250 value[0] = 42;
16251 value[1] = 13;
16252 invoke<void>(*code, value);
16253 CHECK_EQ(value[0], static_cast<T>(100));
16254 CHECK_EQ(value[1], 13);
16255 value[0] = static_cast<T>(300);
16256 invoke<void>(*code, value);
16257 CHECK_EQ(value[0], static_cast<T>(300));
16258 CHECK_EQ(value[1], 13);
16259 checkMyDisassembly(*code, false);
16260 }
16261
16262 {
16263 Procedure proc;
16264 BasicBlock* root = proc.addBlock();
16265 BasicBlock* succ = proc.addBlock();
16266 BasicBlock* fail = proc.addBlock();
16267
16268 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
16269 root->appendNew<Value>(
16270 proc, Branch, Origin(),
16271 root->appendNew<Value>(
16272 proc, NotEqual, Origin(),
16273 root->appendNew<AtomicValue>(
16274 proc, AtomicStrongCAS, Origin(), width,
16275 root->appendIntConstant(proc, Origin(), type, 42),
16276 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16277 ptr),
16278 root->appendIntConstant(proc, Origin(), type, 42)));
16279 root->setSuccessors(fail, succ);
16280
16281 succ->appendNew<MemoryValue>(
16282 proc, storeOpcode(GP, width), Origin(),
16283 succ->appendIntConstant(proc, Origin(), type, 100),
16284 ptr);
16285 succ->appendNew<Value>(proc, Return, Origin());
16286
16287 fail->appendNew<Value>(proc, Return, Origin());
16288
16289 auto code = compileProc(proc);
16290 T value[2];
16291 value[0] = 42;
16292 value[1] = 13;
16293 invoke<void>(*code, value);
16294 CHECK_EQ(value[0], static_cast<T>(100));
16295 CHECK_EQ(value[1], 13);
16296 value[0] = static_cast<T>(300);
16297 invoke<void>(*code, value);
16298 CHECK_EQ(value[0], static_cast<T>(300));
16299 CHECK_EQ(value[1], 13);
16300 checkMyDisassembly(*code, true);
16301 }
16302
16303 {
16304 Procedure proc;
16305 BasicBlock* root = proc.addBlock();
16306 root->appendNew<Value>(
16307 proc, Return, Origin(),
16308 root->appendNew<AtomicValue>(
16309 proc, AtomicStrongCAS, Origin(), width,
16310 root->appendIntConstant(proc, Origin(), type, 42),
16311 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16312 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
16313
16314 auto code = compileProc(proc);
16315 T value[2];
16316 value[0] = 42;
16317 value[1] = 13;
16318 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), 42);
16319 CHECK_EQ(value[0], static_cast<T>(0xbeef));
16320 CHECK_EQ(value[1], 13);
16321 value[0] = static_cast<T>(300);
16322 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), static_cast<typename NativeTraits<T>::CanonicalType>(static_cast<T>(300)));
16323 CHECK_EQ(value[0], static_cast<T>(300));
16324 CHECK_EQ(value[1], 13);
16325 value[0] = static_cast<T>(-1);
16326 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), static_cast<typename NativeTraits<T>::CanonicalType>(static_cast<T>(-1)));
16327 CHECK_EQ(value[0], static_cast<T>(-1));
16328 CHECK_EQ(value[1], 13);
16329 checkMyDisassembly(*code, true);
16330 }
16331
16332 {
16333 // Test for https://bugs.webkit.org/show_bug.cgi?id=169867.
16334
16335 Procedure proc;
16336 BasicBlock* root = proc.addBlock();
16337 root->appendNew<Value>(
16338 proc, Return, Origin(),
16339 root->appendNew<Value>(
16340 proc, BitXor, Origin(),
16341 root->appendNew<AtomicValue>(
16342 proc, AtomicStrongCAS, Origin(), width,
16343 root->appendIntConstant(proc, Origin(), type, 42),
16344 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16345 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
16346 root->appendIntConstant(proc, Origin(), type, 1)));
16347
16348 typename NativeTraits<T>::CanonicalType one = 1;
16349
16350 auto code = compileProc(proc);
16351 T value[2];
16352 value[0] = 42;
16353 value[1] = 13;
16354 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), 42 ^ one);
16355 CHECK_EQ(value[0], static_cast<T>(0xbeef));
16356 CHECK_EQ(value[1], 13);
16357 value[0] = static_cast<T>(300);
16358 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), static_cast<typename NativeTraits<T>::CanonicalType>(static_cast<T>(300)) ^ one);
16359 CHECK_EQ(value[0], static_cast<T>(300));
16360 CHECK_EQ(value[1], 13);
16361 value[0] = static_cast<T>(-1);
16362 CHECK_EQ(invoke<typename NativeTraits<T>::CanonicalType>(*code, value), static_cast<typename NativeTraits<T>::CanonicalType>(static_cast<T>(-1)) ^ one);
16363 CHECK_EQ(value[0], static_cast<T>(-1));
16364 CHECK_EQ(value[1], 13);
16365 checkMyDisassembly(*code, true);
16366 }
16367
16368 {
16369 Procedure proc;
16370 BasicBlock* root = proc.addBlock();
16371 root->appendNew<Value>(
16372 proc, Return, Origin(),
16373 root->appendNew<Value>(
16374 proc, Equal, Origin(),
16375 root->appendNew<AtomicValue>(
16376 proc, AtomicStrongCAS, Origin(), width,
16377 root->appendIntConstant(proc, Origin(), type, 42),
16378 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16379 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
16380 root->appendIntConstant(proc, Origin(), type, 42)));
16381
16382 auto code = compileProc(proc);
16383 T value[2];
16384 value[0] = 42;
16385 value[1] = 13;
16386 CHECK(invoke<bool>(*code, value));
16387 CHECK_EQ(value[0], static_cast<T>(0xbeef));
16388 CHECK_EQ(value[1], 13);
16389 value[0] = static_cast<T>(300);
16390 CHECK(!invoke<bool>(*code, value));
16391 CHECK_EQ(value[0], static_cast<T>(300));
16392 CHECK_EQ(value[1], 13);
16393 checkMyDisassembly(*code, true);
16394 }
16395
16396 {
16397 Procedure proc;
16398 BasicBlock* root = proc.addBlock();
16399 root->appendNew<Value>(
16400 proc, Return, Origin(),
16401 root->appendNew<Value>(
16402 proc, Equal, Origin(),
16403 root->appendNew<Value>(
16404 proc, NotEqual, Origin(),
16405 root->appendNew<AtomicValue>(
16406 proc, AtomicStrongCAS, Origin(), width,
16407 root->appendIntConstant(proc, Origin(), type, 42),
16408 root->appendIntConstant(proc, Origin(), type, 0xbeef),
16409 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
16410 root->appendIntConstant(proc, Origin(), type, 42)),
16411 root->appendNew<Const32Value>(proc, Origin(), 0)));
16412
16413 auto code = compileProc(proc);
16414 T value[2];
16415 value[0] = 42;
16416 value[1] = 13;
16417 CHECK(invoke<bool>(*code, value));
16418 CHECK_EQ(value[0], static_cast<T>(0xbeef));
16419 CHECK_EQ(value[1], 13);
16420 value[0] = static_cast<T>(300);
16421 CHECK(!invoke<bool>(*code, &value));
16422 CHECK_EQ(value[0], static_cast<T>(300));
16423 CHECK_EQ(value[1], 13);
16424 checkMyDisassembly(*code, true);
16425 }
16426}
16427
16428template<typename T>
16429void testAtomicXchg(B3::Opcode opcode)
16430{
16431 Type type = NativeTraits<T>::type;
16432 Width width = NativeTraits<T>::width;
16433
16434 auto doTheMath = [&] (T& memory, T operand) -> T {
16435 T oldValue = memory;
16436 switch (opcode) {
16437 case AtomicXchgAdd:
16438 memory += operand;
16439 break;
16440 case AtomicXchgAnd:
16441 memory &= operand;
16442 break;
16443 case AtomicXchgOr:
16444 memory |= operand;
16445 break;
16446 case AtomicXchgSub:
16447 memory -= operand;
16448 break;
16449 case AtomicXchgXor:
16450 memory ^= operand;
16451 break;
16452 case AtomicXchg:
16453 memory = operand;
16454 break;
16455 default:
16456 RELEASE_ASSERT_NOT_REACHED();
16457 }
16458 return oldValue;
16459 };
16460
16461 auto oldValue = [&] (T memory, T operand) -> T {
16462 return doTheMath(memory, operand);
16463 };
16464
16465 auto newValue = [&] (T memory, T operand) -> T {
16466 doTheMath(memory, operand);
16467 return memory;
16468 };
16469
16470 auto checkMyDisassembly = [&] (Compilation& compilation, bool fenced) {
16471 if (isX86())
16472 checkUsesInstruction(compilation, "lock");
16473 else {
16474 if (fenced) {
16475 checkUsesInstruction(compilation, "ldax");
16476 checkUsesInstruction(compilation, "stlx");
16477 } else {
16478 checkUsesInstruction(compilation, "ldx");
16479 checkUsesInstruction(compilation, "stx");
16480 }
16481 }
16482 };
16483
16484 {
16485 Procedure proc;
16486 BasicBlock* root = proc.addBlock();
16487 root->appendNew<Value>(
16488 proc, Return, Origin(),
16489 root->appendNew<AtomicValue>(
16490 proc, opcode, Origin(), width,
16491 root->appendIntConstant(proc, Origin(), type, 1),
16492 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
16493
16494 auto code = compileProc(proc);
16495 T value[2];
16496 value[0] = 5;
16497 value[1] = 100;
16498 CHECK_EQ(invoke<T>(*code, value), oldValue(5, 1));
16499 CHECK_EQ(value[0], newValue(5, 1));
16500 CHECK_EQ(value[1], 100);
16501 checkMyDisassembly(*code, true);
16502 }
16503
16504 {
16505 Procedure proc;
16506 BasicBlock* root = proc.addBlock();
16507 root->appendNew<Value>(
16508 proc, Return, Origin(),
16509 root->appendNew<AtomicValue>(
16510 proc, opcode, Origin(), width,
16511 root->appendIntConstant(proc, Origin(), type, 42),
16512 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
16513
16514 auto code = compileProc(proc);
16515 T value[2];
16516 value[0] = 5;
16517 value[1] = 100;
16518 CHECK_EQ(invoke<T>(*code, value), oldValue(5, 42));
16519 CHECK_EQ(value[0], newValue(5, 42));
16520 CHECK_EQ(value[1], 100);
16521 checkMyDisassembly(*code, true);
16522 }
16523
16524 {
16525 Procedure proc;
16526 BasicBlock* root = proc.addBlock();
16527 root->appendNew<AtomicValue>(
16528 proc, opcode, Origin(), width,
16529 root->appendIntConstant(proc, Origin(), type, 42),
16530 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
16531 root->appendNew<Value>(proc, Return, Origin());
16532
16533 auto code = compileProc(proc);
16534 T value[2];
16535 value[0] = 5;
16536 value[1] = 100;
16537 invoke<T>(*code, value);
16538 CHECK_EQ(value[0], newValue(5, 42));
16539 CHECK_EQ(value[1], 100);
16540 checkMyDisassembly(*code, true);
16541 }
16542
16543 {
16544 Procedure proc;
16545 BasicBlock* root = proc.addBlock();
16546 root->appendNew<AtomicValue>(
16547 proc, opcode, Origin(), width,
16548 root->appendIntConstant(proc, Origin(), type, 42),
16549 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
16550 0, HeapRange(42), HeapRange());
16551 root->appendNew<Value>(proc, Return, Origin());
16552
16553 auto code = compileProc(proc);
16554 T value[2];
16555 value[0] = 5;
16556 value[1] = 100;
16557 invoke<T>(*code, value);
16558 CHECK_EQ(value[0], newValue(5, 42));
16559 CHECK_EQ(value[1], 100);
16560 checkMyDisassembly(*code, false);
16561 }
16562}
16563
16564void testDepend32()
16565{
16566 Procedure proc;
16567 BasicBlock* root = proc.addBlock();
16568 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
16569 Value* first = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), ptr, 0);
16570 Value* second = root->appendNew<MemoryValue>(
16571 proc, Load, Int32, Origin(),
16572 root->appendNew<Value>(
16573 proc, Add, Origin(), ptr,
16574 root->appendNew<Value>(
16575 proc, ZExt32, Origin(),
16576 root->appendNew<Value>(proc, Depend, Origin(), first))),
16577 4);
16578 root->appendNew<Value>(
16579 proc, Return, Origin(),
16580 root->appendNew<Value>(proc, Add, Origin(), first, second));
16581
16582 int32_t values[2];
16583 values[0] = 42;
16584 values[1] = 0xbeef;
16585
16586 auto code = compileProc(proc);
16587 if (isARM64())
16588 checkUsesInstruction(*code, "eor");
16589 else if (isX86()) {
16590 checkDoesNotUseInstruction(*code, "mfence");
16591 checkDoesNotUseInstruction(*code, "lock");
16592 }
16593 CHECK_EQ(invoke<int32_t>(*code, values), 42 + 0xbeef);
16594}
16595
16596void testDepend64()
16597{
16598 Procedure proc;
16599 BasicBlock* root = proc.addBlock();
16600 Value* ptr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
16601 Value* first = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), ptr, 0);
16602 Value* second = root->appendNew<MemoryValue>(
16603 proc, Load, Int64, Origin(),
16604 root->appendNew<Value>(
16605 proc, Add, Origin(), ptr,
16606 root->appendNew<Value>(proc, Depend, Origin(), first)),
16607 8);
16608 root->appendNew<Value>(
16609 proc, Return, Origin(),
16610 root->appendNew<Value>(proc, Add, Origin(), first, second));
16611
16612 int64_t values[2];
16613 values[0] = 42;
16614 values[1] = 0xbeef;
16615
16616 auto code = compileProc(proc);
16617 if (isARM64())
16618 checkUsesInstruction(*code, "eor");
16619 else if (isX86()) {
16620 checkDoesNotUseInstruction(*code, "mfence");
16621 checkDoesNotUseInstruction(*code, "lock");
16622 }
16623 CHECK_EQ(invoke<int64_t>(*code, values), 42 + 0xbeef);
16624}
16625
16626void testWasmBoundsCheck(unsigned offset)
16627{
16628 Procedure proc;
16629 if (proc.optLevel() < 1)
16630 return;
16631 GPRReg pinned = GPRInfo::argumentGPR1;
16632 proc.pinRegister(pinned);
16633
16634 proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR) {
16635 CHECK_EQ(pinnedGPR, pinned);
16636
16637 // This should always work because a function this simple should never have callee
16638 // saves.
16639 jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
16640 jit.emitFunctionEpilogue();
16641 jit.ret();
16642 });
16643
16644 BasicBlock* root = proc.addBlock();
16645 Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
16646 if (pointerType() != Int32)
16647 left = root->appendNew<Value>(proc, Trunc, Origin(), left);
16648 root->appendNew<WasmBoundsCheckValue>(proc, Origin(), pinned, left, offset);
16649 Value* result = root->appendNew<Const32Value>(proc, Origin(), 0x42);
16650 root->appendNewControlValue(proc, Return, Origin(), result);
16651
16652 auto code = compileProc(proc);
16653 uint32_t bound = 2 + offset;
16654 auto computeResult = [&] (uint32_t input) {
16655 return input + offset < bound ? 0x42 : 42;
16656 };
16657
16658 CHECK_EQ(invoke<int32_t>(*code, 1, bound), computeResult(1));
16659 CHECK_EQ(invoke<int32_t>(*code, 3, bound), computeResult(3));
16660 CHECK_EQ(invoke<int32_t>(*code, 2, bound), computeResult(2));
16661}
16662
16663void testWasmAddress()
16664{
16665 Procedure proc;
16666 GPRReg pinnedGPR = GPRInfo::argumentGPR2;
16667 proc.pinRegister(pinnedGPR);
16668
16669 unsigned loopCount = 100;
16670 Vector<unsigned> values(loopCount);
16671 unsigned numToStore = 42;
16672
16673 BasicBlock* root = proc.addBlock();
16674 BasicBlock* header = proc.addBlock();
16675 BasicBlock* body = proc.addBlock();
16676 BasicBlock* continuation = proc.addBlock();
16677
16678 // Root
16679 Value* loopCountValue = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
16680 Value* valueToStore = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
16681 UpsilonValue* beginUpsilon = root->appendNew<UpsilonValue>(proc, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
16682 root->appendNewControlValue(proc, Jump, Origin(), header);
16683
16684 // Header
16685 Value* indexPhi = header->appendNew<Value>(proc, Phi, Int32, Origin());
16686 header->appendNewControlValue(proc, Branch, Origin(),
16687 header->appendNew<Value>(proc, Below, Origin(), indexPhi, loopCountValue),
16688 body, continuation);
16689
16690 // Body
16691 Value* pointer = body->appendNew<Value>(proc, Mul, Origin(), indexPhi,
16692 body->appendNew<Const32Value>(proc, Origin(), sizeof(unsigned)));
16693 pointer = body->appendNew<Value>(proc, ZExt32, Origin(), pointer);
16694 body->appendNew<MemoryValue>(proc, Store, Origin(), valueToStore,
16695 body->appendNew<WasmAddressValue>(proc, Origin(), pointer, pinnedGPR), 0);
16696 UpsilonValue* incUpsilon = body->appendNew<UpsilonValue>(proc, Origin(),
16697 body->appendNew<Value>(proc, Add, Origin(), indexPhi,
16698 body->appendNew<Const32Value>(proc, Origin(), 1)));
16699 body->appendNewControlValue(proc, Jump, Origin(), header);
16700
16701 // Continuation
16702 continuation->appendNewControlValue(proc, Return, Origin());
16703
16704 beginUpsilon->setPhi(indexPhi);
16705 incUpsilon->setPhi(indexPhi);
16706
16707
16708 auto code = compileProc(proc);
16709 invoke<void>(*code, loopCount, numToStore, values.data());
16710 for (unsigned value : values)
16711 CHECK_EQ(numToStore, value);
16712}
16713
16714void testFastTLSLoad()
16715{
16716#if ENABLE(FAST_TLS_JIT)
16717 _pthread_setspecific_direct(WTF_TESTING_KEY, bitwise_cast<void*>(static_cast<uintptr_t>(0xbeef)));
16718
16719 Procedure proc;
16720 BasicBlock* root = proc.addBlock();
16721
16722 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, pointerType(), Origin());
16723 patchpoint->clobber(RegisterSet::macroScratchRegisters());
16724 patchpoint->setGenerator(
16725 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
16726 AllowMacroScratchRegisterUsage allowScratch(jit);
16727 jit.loadFromTLSPtr(fastTLSOffsetForKey(WTF_TESTING_KEY), params[0].gpr());
16728 });
16729
16730 root->appendNew<Value>(proc, Return, Origin(), patchpoint);
16731
16732 CHECK_EQ(compileAndRun<uintptr_t>(proc), static_cast<uintptr_t>(0xbeef));
16733#endif
16734}
16735
16736void testFastTLSStore()
16737{
16738#if ENABLE(FAST_TLS_JIT)
16739 Procedure proc;
16740 BasicBlock* root = proc.addBlock();
16741
16742 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
16743 patchpoint->clobber(RegisterSet::macroScratchRegisters());
16744 patchpoint->numGPScratchRegisters = 1;
16745 patchpoint->setGenerator(
16746 [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
16747 AllowMacroScratchRegisterUsage allowScratch(jit);
16748 GPRReg scratch = params.gpScratch(0);
16749 jit.move(CCallHelpers::TrustedImm32(0xdead), scratch);
16750 jit.storeToTLSPtr(scratch, fastTLSOffsetForKey(WTF_TESTING_KEY));
16751 });
16752
16753 root->appendNewControlValue(proc, Return, Origin());
16754
16755 compileAndRun<void>(proc);
16756 CHECK_EQ(bitwise_cast<uintptr_t>(_pthread_getspecific_direct(WTF_TESTING_KEY)), static_cast<uintptr_t>(0xdead));
16757#endif
16758}
16759
16760NEVER_INLINE bool doubleEq(double a, double b) { return a == b; }
16761NEVER_INLINE bool doubleNeq(double a, double b) { return a != b; }
16762NEVER_INLINE bool doubleGt(double a, double b) { return a > b; }
16763NEVER_INLINE bool doubleGte(double a, double b) { return a >= b; }
16764NEVER_INLINE bool doubleLt(double a, double b) { return a < b; }
16765NEVER_INLINE bool doubleLte(double a, double b) { return a <= b; }
16766
16767void testDoubleLiteralComparison(double a, double b)
16768{
16769 using Test = std::tuple<B3::Opcode, bool (*)(double, double)>;
16770 StdList<Test> tests = {
16771 Test { NotEqual, doubleNeq },
16772 Test { Equal, doubleEq },
16773 Test { EqualOrUnordered, doubleEq },
16774 Test { GreaterThan, doubleGt },
16775 Test { GreaterEqual, doubleGte },
16776 Test { LessThan, doubleLt },
16777 Test { LessEqual, doubleLte },
16778 };
16779
16780 for (const Test& test : tests) {
16781 Procedure proc;
16782 BasicBlock* root = proc.addBlock();
16783 Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
16784 Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
16785
16786 // This is here just to make reduceDoubleToFloat do things.
16787 Value* valueC = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.0);
16788 Value* valueAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), valueC);
16789
16790 root->appendNewControlValue(
16791 proc, Return, Origin(),
16792 root->appendNew<Value>(proc, BitAnd, Origin(),
16793 root->appendNew<Value>(proc, std::get<0>(test), Origin(), valueA, valueB),
16794 root->appendNew<Value>(proc, Equal, Origin(), valueAsFloat, valueAsFloat)));
16795
16796 CHECK(!!compileAndRun<int32_t>(proc) == std::get<1>(test)(a, b));
16797 }
16798}
16799
16800void testFloatEqualOrUnorderedFolding()
16801{
16802 for (auto& first : floatingPointOperands<float>()) {
16803 for (auto& second : floatingPointOperands<float>()) {
16804 float a = first.value;
16805 float b = second.value;
16806 bool expectedResult = (a == b) || std::isunordered(a, b);
16807 Procedure proc;
16808 BasicBlock* root = proc.addBlock();
16809 Value* constA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
16810 Value* constB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
16811
16812 root->appendNewControlValue(proc, Return, Origin(),
16813 root->appendNew<Value>(
16814 proc, EqualOrUnordered, Origin(),
16815 constA,
16816 constB));
16817 CHECK(!!compileAndRun<int32_t>(proc) == expectedResult);
16818 }
16819 }
16820}
16821
16822void testFloatEqualOrUnorderedFoldingNaN()
16823{
16824 StdList<float> nans = {
16825 bitwise_cast<float>(0xfffffffd),
16826 bitwise_cast<float>(0xfffffffe),
16827 bitwise_cast<float>(0xfffffff0),
16828 static_cast<float>(PNaN),
16829 };
16830
16831 unsigned i = 0;
16832 for (float nan : nans) {
16833 RELEASE_ASSERT(std::isnan(nan));
16834 Procedure proc;
16835 BasicBlock* root = proc.addBlock();
16836 Value* a = root->appendNew<ConstFloatValue>(proc, Origin(), nan);
16837 Value* b = root->appendNew<Value>(proc, DoubleToFloat, Origin(),
16838 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
16839
16840 if (i % 2)
16841 std::swap(a, b);
16842 ++i;
16843 root->appendNewControlValue(proc, Return, Origin(),
16844 root->appendNew<Value>(proc, EqualOrUnordered, Origin(), a, b));
16845 CHECK(!!compileAndRun<int32_t>(proc, static_cast<double>(1.0)));
16846 }
16847}
16848
16849void testFloatEqualOrUnorderedDontFold()
16850{
16851 for (auto& first : floatingPointOperands<float>()) {
16852 float a = first.value;
16853 Procedure proc;
16854 BasicBlock* root = proc.addBlock();
16855 Value* constA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
16856 Value* b = root->appendNew<Value>(proc, DoubleToFloat, Origin(),
16857 root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
16858 root->appendNewControlValue(proc, Return, Origin(),
16859 root->appendNew<Value>(
16860 proc, EqualOrUnordered, Origin(), constA, b));
16861
16862 auto code = compileProc(proc);
16863
16864 for (auto& second : floatingPointOperands<float>()) {
16865 float b = second.value;
16866 bool expectedResult = (a == b) || std::isunordered(a, b);
16867 CHECK(!!invoke<int32_t>(*code, static_cast<double>(b)) == expectedResult);
16868 }
16869 }
16870}
16871
16872void functionNineArgs(int32_t, void*, void*, void*, void*, void*, void*, void*, void*) { }
16873
16874void testShuffleDoesntTrashCalleeSaves()
16875{
16876 Procedure proc;
16877
16878 BasicBlock* root = proc.addBlock();
16879 BasicBlock* likely = proc.addBlock();
16880 BasicBlock* unlikely = proc.addBlock();
16881
16882 RegisterSet regs = RegisterSet::allGPRs();
16883 regs.exclude(RegisterSet::stackRegisters());
16884 regs.exclude(RegisterSet::reservedHardwareRegisters());
16885 regs.exclude(RegisterSet::calleeSaveRegisters());
16886 regs.exclude(RegisterSet::argumentGPRS());
16887
16888 unsigned i = 0;
16889 Vector<Value*> patches;
16890 for (Reg reg : regs) {
16891 ++i;
16892 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
16893 patchpoint->clobber(RegisterSet::macroScratchRegisters());
16894 RELEASE_ASSERT(reg.isGPR());
16895 patchpoint->resultConstraint = ValueRep::reg(reg.gpr());
16896 patchpoint->setGenerator(
16897 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
16898 AllowMacroScratchRegisterUsage allowScratch(jit);
16899 jit.move(CCallHelpers::TrustedImm32(i), params[0].gpr());
16900 });
16901 patches.append(patchpoint);
16902 }
16903
16904 Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(0 % GPRInfo::numberOfArgumentRegisters));
16905 Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(1 % GPRInfo::numberOfArgumentRegisters));
16906 Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(2 % GPRInfo::numberOfArgumentRegisters));
16907 Value* arg4 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(3 % GPRInfo::numberOfArgumentRegisters));
16908 Value* arg5 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(4 % GPRInfo::numberOfArgumentRegisters));
16909 Value* arg6 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(5 % GPRInfo::numberOfArgumentRegisters));
16910 Value* arg7 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(6 % GPRInfo::numberOfArgumentRegisters));
16911 Value* arg8 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(7 % GPRInfo::numberOfArgumentRegisters));
16912
16913 PatchpointValue* ptr = root->appendNew<PatchpointValue>(proc, Int64, Origin());
16914 ptr->clobber(RegisterSet::macroScratchRegisters());
16915 ptr->resultConstraint = ValueRep::reg(GPRInfo::regCS0);
16916 ptr->appendSomeRegister(arg1);
16917 ptr->setGenerator(
16918 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
16919 AllowMacroScratchRegisterUsage allowScratch(jit);
16920 jit.move(params[1].gpr(), params[0].gpr());
16921 });
16922
16923 Value* condition = root->appendNew<Value>(
16924 proc, Equal, Origin(),
16925 ptr,
16926 root->appendNew<Const64Value>(proc, Origin(), 0));
16927
16928 root->appendNewControlValue(
16929 proc, Branch, Origin(),
16930 condition,
16931 FrequentedBlock(likely, FrequencyClass::Normal), FrequentedBlock(unlikely, FrequencyClass::Rare));
16932
16933 // Never executes.
16934 Value* const42 = likely->appendNew<Const32Value>(proc, Origin(), 42);
16935 likely->appendNewControlValue(proc, Return, Origin(), const42);
16936
16937 // Always executes.
16938 Value* constNumber = unlikely->appendNew<Const32Value>(proc, Origin(), 0x1);
16939
16940 unlikely->appendNew<CCallValue>(
16941 proc, Void, Origin(),
16942 unlikely->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionNineArgs, B3CCallPtrTag)),
16943 constNumber, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
16944
16945 PatchpointValue* voidPatch = unlikely->appendNew<PatchpointValue>(proc, Void, Origin());
16946 voidPatch->clobber(RegisterSet::macroScratchRegisters());
16947 for (Value* v : patches)
16948 voidPatch->appendSomeRegister(v);
16949 voidPatch->appendSomeRegister(arg1);
16950 voidPatch->appendSomeRegister(arg2);
16951 voidPatch->appendSomeRegister(arg3);
16952 voidPatch->appendSomeRegister(arg4);
16953 voidPatch->appendSomeRegister(arg5);
16954 voidPatch->appendSomeRegister(arg6);
16955 voidPatch->setGenerator([=] (CCallHelpers&, const StackmapGenerationParams&) { });
16956
16957 unlikely->appendNewControlValue(proc, Return, Origin(),
16958 unlikely->appendNew<MemoryValue>(proc, Load, Int32, Origin(), ptr));
16959
16960 int32_t* inputPtr = static_cast<int32_t*>(fastMalloc(sizeof(int32_t)));
16961 *inputPtr = 48;
16962 CHECK(compileAndRun<int32_t>(proc, inputPtr) == 48);
16963 fastFree(inputPtr);
16964}
16965
16966void testDemotePatchpointTerminal()
16967{
16968 Procedure proc;
16969
16970 BasicBlock* root = proc.addBlock();
16971 BasicBlock* done = proc.addBlock();
16972
16973 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
16974 patchpoint->effects.terminal = true;
16975 root->setSuccessors(done);
16976
16977 done->appendNew<Value>(proc, Return, Origin(), patchpoint);
16978
16979 proc.resetReachability();
16980 breakCriticalEdges(proc);
16981 IndexSet<Value*> valuesToDemote;
16982 valuesToDemote.add(patchpoint);
16983 demoteValues(proc, valuesToDemote);
16984 validate(proc);
16985}
16986
16987void testReportUsedRegistersLateUseFollowedByEarlyDefDoesNotMarkUseAsDead()
16988{
16989 Procedure proc;
16990 if (proc.optLevel() < 2)
16991 return;
16992 BasicBlock* root = proc.addBlock();
16993
16994 RegisterSet allRegs = RegisterSet::allGPRs();
16995 allRegs.exclude(RegisterSet::stackRegisters());
16996 allRegs.exclude(RegisterSet::reservedHardwareRegisters());
16997
16998 {
16999 // Make every reg 42 (just needs to be a value other than 10).
17000 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
17001 Value* const42 = root->appendNew<Const32Value>(proc, Origin(), 42);
17002 for (Reg reg : allRegs)
17003 patchpoint->append(const42, ValueRep::reg(reg));
17004 patchpoint->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { });
17005 }
17006
17007 {
17008 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin());
17009 Value* const10 = root->appendNew<Const32Value>(proc, Origin(), 10);
17010 for (Reg reg : allRegs)
17011 patchpoint->append(const10, ValueRep::lateReg(reg));
17012 patchpoint->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) {
17013 for (Reg reg : allRegs) {
17014 auto done = jit.branch32(CCallHelpers::Equal, reg.gpr(), CCallHelpers::TrustedImm32(10));
17015 jit.breakpoint();
17016 done.link(&jit);
17017 }
17018 });
17019 }
17020
17021 {
17022 PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
17023 patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
17024 patchpoint->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams& params) {
17025 RELEASE_ASSERT(allRegs.contains(params[0].gpr()));
17026 });
17027 }
17028
17029 root->appendNewControlValue(proc, Return, Origin());
17030
17031 compileAndRun<void>(proc);
17032}
17033
17034void testInfiniteLoopDoesntCauseBadHoisting()
17035{
17036 Procedure proc;
17037 if (proc.optLevel() < 2)
17038 return;
17039 BasicBlock* root = proc.addBlock();
17040 BasicBlock* header = proc.addBlock();
17041 BasicBlock* loadBlock = proc.addBlock();
17042 BasicBlock* postLoadBlock = proc.addBlock();
17043
17044 Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
17045 root->appendNewControlValue(proc, Jump, Origin(), header);
17046
17047 header->appendNewControlValue(
17048 proc, Branch, Origin(),
17049 header->appendNew<Value>(proc, Equal, Origin(),
17050 arg,
17051 header->appendNew<Const64Value>(proc, Origin(), 10)), header, loadBlock);
17052
17053 PatchpointValue* patchpoint = loadBlock->appendNew<PatchpointValue>(proc, Void, Origin());
17054 patchpoint->effects = Effects::none();
17055 patchpoint->effects.writesLocalState = true; // Don't DCE this.
17056 patchpoint->setGenerator(
17057 [&] (CCallHelpers& jit, const StackmapGenerationParams&) {
17058 // This works because we don't have callee saves.
17059 jit.emitFunctionEpilogue();
17060 jit.ret();
17061 });
17062
17063 Value* badLoad = loadBlock->appendNew<MemoryValue>(proc, Load, Int64, Origin(), arg, 0);
17064
17065 loadBlock->appendNewControlValue(
17066 proc, Branch, Origin(),
17067 loadBlock->appendNew<Value>(proc, Equal, Origin(),
17068 badLoad,
17069 loadBlock->appendNew<Const64Value>(proc, Origin(), 45)), header, postLoadBlock);
17070
17071 postLoadBlock->appendNewControlValue(proc, Return, Origin(), badLoad);
17072
17073 // The patchpoint early ret() works because we don't have callee saves.
17074 auto code = compileProc(proc);
17075 RELEASE_ASSERT(!proc.calleeSaveRegisterAtOffsetList().size());
17076 invoke<void>(*code, static_cast<uint64_t>(55)); // Shouldn't crash dereferncing 55.
17077}
17078
17079// Make sure the compiler does not try to optimize anything out.
17080NEVER_INLINE double zero()
17081{
17082 return 0.;
17083}
17084
17085double negativeZero()
17086{
17087 return -zero();
17088}
17089
17090#define PREFIX "O", Options::defaultB3OptLevel(), ": "
17091
17092#define RUN_NOW(test) do { \
17093 if (!shouldRun(#test)) \
17094 break; \
17095 dataLog(PREFIX #test "...\n"); \
17096 test; \
17097 dataLog(PREFIX #test ": OK!\n"); \
17098 } while (false)
17099#define RUN(test) do { \
17100 if (!shouldRun(#test)) \
17101 break; \
17102 tasks.append( \
17103 createSharedTask<void()>( \
17104 [&] () { \
17105 dataLog(PREFIX #test "...\n"); \
17106 test; \
17107 dataLog(PREFIX #test ": OK!\n"); \
17108 })); \
17109 } while (false);
17110
17111#define RUN_UNARY(test, values) \
17112 for (auto a : values) { \
17113 CString testStr = toCString(PREFIX #test, "(", a.name, ")"); \
17114 if (!shouldRun(testStr.data())) \
17115 continue; \
17116 tasks.append(createSharedTask<void()>( \
17117 [=] () { \
17118 dataLog(toCString(testStr, "...\n")); \
17119 test(a.value); \
17120 dataLog(toCString(testStr, ": OK!\n")); \
17121 })); \
17122 }
17123
17124#define RUN_BINARY(test, valuesA, valuesB) \
17125 for (auto a : valuesA) { \
17126 for (auto b : valuesB) { \
17127 CString testStr = toCString(PREFIX #test, "(", a.name, ", ", b.name, ")"); \
17128 if (!shouldRun(testStr.data())) \
17129 continue; \
17130 tasks.append(createSharedTask<void()>( \
17131 [=] () { \
17132 dataLog(toCString(testStr, "...\n")); \
17133 test(a.value, b.value); \
17134 dataLog(toCString(testStr, ": OK!\n")); \
17135 })); \
17136 } \
17137 }
17138#define RUN_TERNARY(test, valuesA, valuesB, valuesC) \
17139 for (auto a : valuesA) { \
17140 for (auto b : valuesB) { \
17141 for (auto c : valuesC) { \
17142 CString testStr = toCString(#test, "(", a.name, ", ", b.name, ",", c.name, ")"); \
17143 if (!shouldRun(testStr.data())) \
17144 continue; \
17145 tasks.append(createSharedTask<void()>( \
17146 [=] () { \
17147 dataLog(toCString(testStr, "...\n")); \
17148 test(a.value, b.value, c.value); \
17149 dataLog(toCString(testStr, ": OK!\n")); \
17150 })); \
17151 } \
17152 } \
17153 }
17154
17155void run(const char* filter)
17156{
17157 Deque<RefPtr<SharedTask<void()>>> tasks;
17158
17159 auto shouldRun = [&] (const char* testName) -> bool {
17160 return !filter || WTF::findIgnoringASCIICaseWithoutLength(testName, filter) != WTF::notFound;
17161 };
17162
17163 RUN_NOW(testTerminalPatchpointThatNeedsToBeSpilled2());
17164 RUN(test42());
17165 RUN(testLoad42());
17166 RUN(testLoadAcq42());
17167 RUN(testLoadOffsetImm9Max());
17168 RUN(testLoadOffsetImm9MaxPlusOne());
17169 RUN(testLoadOffsetImm9MaxPlusTwo());
17170 RUN(testLoadOffsetImm9Min());
17171 RUN(testLoadOffsetImm9MinMinusOne());
17172 RUN(testLoadOffsetScaledUnsignedImm12Max());
17173 RUN(testLoadOffsetScaledUnsignedOverImm12Max());
17174 RUN(testArg(43));
17175 RUN(testReturnConst64(5));
17176 RUN(testReturnConst64(-42));
17177 RUN(testReturnVoid());
17178
17179 RUN_BINARY(testBitXorTreeArgs, int64Operands(), int64Operands());
17180 RUN_BINARY(testBitXorTreeArgsEven, int64Operands(), int64Operands());
17181 RUN_BINARY(testBitXorTreeArgImm, int64Operands(), int64Operands());
17182 RUN_UNARY(testAddTreeArg32, int32Operands());
17183 RUN_UNARY(testMulTreeArg32, int32Operands());
17184 RUN_UNARY(testBitAndTreeArg32, int32Operands());
17185 RUN_UNARY(testBitOrTreeArg32, int32Operands());
17186
17187 RUN(testAddArg(111));
17188 RUN(testAddArgs(1, 1));
17189 RUN(testAddArgs(1, 2));
17190 RUN(testAddArgImm(1, 2));
17191 RUN(testAddArgImm(0, 2));
17192 RUN(testAddArgImm(1, 0));
17193 RUN(testAddImmArg(1, 2));
17194 RUN(testAddImmArg(0, 2));
17195 RUN(testAddImmArg(1, 0));
17196 RUN_BINARY(testAddArgMem, int64Operands(), int64Operands());
17197 RUN_BINARY(testAddMemArg, int64Operands(), int64Operands());
17198 RUN_BINARY(testAddImmMem, int64Operands(), int64Operands());
17199 RUN_UNARY(testAddArg32, int32Operands());
17200 RUN(testAddArgs32(1, 1));
17201 RUN(testAddArgs32(1, 2));
17202 RUN_BINARY(testAddArgMem32, int32Operands(), int32Operands());
17203 RUN_BINARY(testAddMemArg32, int32Operands(), int32Operands());
17204 RUN_BINARY(testAddImmMem32, int32Operands(), int32Operands());
17205 RUN_BINARY(testAddNeg1, int32Operands(), int32Operands());
17206 RUN_BINARY(testAddNeg2, int32Operands(), int32Operands());
17207 RUN(testAddArgZeroImmZDef());
17208 RUN(testAddLoadTwice());
17209 RUN_TERNARY(testAddMulMulArgs, int64Operands(), int64Operands(), int64Operands());
17210
17211 RUN(testAddArgDouble(M_PI));
17212 RUN(testAddArgsDouble(M_PI, 1));
17213 RUN(testAddArgsDouble(M_PI, -M_PI));
17214 RUN(testAddArgImmDouble(M_PI, 1));
17215 RUN(testAddArgImmDouble(M_PI, 0));
17216 RUN(testAddArgImmDouble(M_PI, negativeZero()));
17217 RUN(testAddArgImmDouble(0, 0));
17218 RUN(testAddArgImmDouble(0, negativeZero()));
17219 RUN(testAddArgImmDouble(negativeZero(), 0));
17220 RUN(testAddArgImmDouble(negativeZero(), negativeZero()));
17221 RUN(testAddImmArgDouble(M_PI, 1));
17222 RUN(testAddImmArgDouble(M_PI, 0));
17223 RUN(testAddImmArgDouble(M_PI, negativeZero()));
17224 RUN(testAddImmArgDouble(0, 0));
17225 RUN(testAddImmArgDouble(0, negativeZero()));
17226 RUN(testAddImmArgDouble(negativeZero(), 0));
17227 RUN(testAddImmArgDouble(negativeZero(), negativeZero()));
17228 RUN(testAddImmsDouble(M_PI, 1));
17229 RUN(testAddImmsDouble(M_PI, 0));
17230 RUN(testAddImmsDouble(M_PI, negativeZero()));
17231 RUN(testAddImmsDouble(0, 0));
17232 RUN(testAddImmsDouble(0, negativeZero()));
17233 RUN(testAddImmsDouble(negativeZero(), negativeZero()));
17234 RUN_UNARY(testAddArgFloat, floatingPointOperands<float>());
17235 RUN_BINARY(testAddArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17236 RUN_BINARY(testAddFPRArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17237 RUN_BINARY(testAddArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17238 RUN_BINARY(testAddImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17239 RUN_BINARY(testAddImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17240 RUN_UNARY(testAddArgFloatWithUselessDoubleConversion, floatingPointOperands<float>());
17241 RUN_BINARY(testAddArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17242 RUN_BINARY(testAddArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17243
17244 RUN(testMulArg(5));
17245 RUN(testMulAddArg(5));
17246 RUN(testMulAddArg(85));
17247 RUN(testMulArgStore(5));
17248 RUN(testMulArgStore(85));
17249 RUN(testMulArgs(1, 1));
17250 RUN(testMulArgs(1, 2));
17251 RUN(testMulArgs(3, 3));
17252 RUN(testMulArgImm(1, 2));
17253 RUN(testMulArgImm(1, 4));
17254 RUN(testMulArgImm(1, 8));
17255 RUN(testMulArgImm(1, 16));
17256 RUN(testMulArgImm(1, 0x80000000llu));
17257 RUN(testMulArgImm(1, 0x800000000000llu));
17258 RUN(testMulArgImm(7, 2));
17259 RUN(testMulArgImm(7, 4));
17260 RUN(testMulArgImm(7, 8));
17261 RUN(testMulArgImm(7, 16));
17262 RUN(testMulArgImm(7, 0x80000000llu));
17263 RUN(testMulArgImm(7, 0x800000000000llu));
17264 RUN(testMulArgImm(-42, 2));
17265 RUN(testMulArgImm(-42, 4));
17266 RUN(testMulArgImm(-42, 8));
17267 RUN(testMulArgImm(-42, 16));
17268 RUN(testMulArgImm(-42, 0x80000000llu));
17269 RUN(testMulArgImm(-42, 0x800000000000llu));
17270 RUN(testMulArgImm(0, 2));
17271 RUN(testMulArgImm(1, 0));
17272 RUN(testMulArgImm(3, 3));
17273 RUN(testMulArgImm(3, -1));
17274 RUN(testMulArgImm(-3, -1));
17275 RUN(testMulArgImm(0, -1));
17276 RUN(testMulImmArg(1, 2));
17277 RUN(testMulImmArg(0, 2));
17278 RUN(testMulImmArg(1, 0));
17279 RUN(testMulImmArg(3, 3));
17280 RUN(testMulArgs32(1, 1));
17281 RUN(testMulArgs32(1, 2));
17282 RUN(testMulLoadTwice());
17283 RUN(testMulAddArgsLeft());
17284 RUN(testMulAddArgsRight());
17285 RUN(testMulAddArgsLeft32());
17286 RUN(testMulAddArgsRight32());
17287 RUN(testMulSubArgsLeft());
17288 RUN(testMulSubArgsRight());
17289 RUN(testMulSubArgsLeft32());
17290 RUN(testMulSubArgsRight32());
17291 RUN(testMulNegArgs());
17292 RUN(testMulNegArgs32());
17293
17294 RUN_BINARY(testMulArgNegArg, int64Operands(), int64Operands())
17295 RUN_BINARY(testMulNegArgArg, int64Operands(), int64Operands())
17296 RUN_UNARY(testMulArgDouble, floatingPointOperands<double>());
17297 RUN_BINARY(testMulArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17298 RUN_BINARY(testMulArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17299 RUN_BINARY(testMulImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17300 RUN_BINARY(testMulImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17301 RUN_UNARY(testMulArgFloat, floatingPointOperands<float>());
17302 RUN_BINARY(testMulArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17303 RUN_BINARY(testMulArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17304 RUN_BINARY(testMulImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17305 RUN_BINARY(testMulImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17306 RUN_UNARY(testMulArgFloatWithUselessDoubleConversion, floatingPointOperands<float>());
17307 RUN_BINARY(testMulArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17308 RUN_BINARY(testMulArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17309
17310 RUN(testDivArgDouble(M_PI));
17311 RUN(testDivArgsDouble(M_PI, 1));
17312 RUN(testDivArgsDouble(M_PI, -M_PI));
17313 RUN(testDivArgImmDouble(M_PI, 1));
17314 RUN(testDivArgImmDouble(M_PI, 0));
17315 RUN(testDivArgImmDouble(M_PI, negativeZero()));
17316 RUN(testDivArgImmDouble(0, 0));
17317 RUN(testDivArgImmDouble(0, negativeZero()));
17318 RUN(testDivArgImmDouble(negativeZero(), 0));
17319 RUN(testDivArgImmDouble(negativeZero(), negativeZero()));
17320 RUN(testDivImmArgDouble(M_PI, 1));
17321 RUN(testDivImmArgDouble(M_PI, 0));
17322 RUN(testDivImmArgDouble(M_PI, negativeZero()));
17323 RUN(testDivImmArgDouble(0, 0));
17324 RUN(testDivImmArgDouble(0, negativeZero()));
17325 RUN(testDivImmArgDouble(negativeZero(), 0));
17326 RUN(testDivImmArgDouble(negativeZero(), negativeZero()));
17327 RUN(testDivImmsDouble(M_PI, 1));
17328 RUN(testDivImmsDouble(M_PI, 0));
17329 RUN(testDivImmsDouble(M_PI, negativeZero()));
17330 RUN(testDivImmsDouble(0, 0));
17331 RUN(testDivImmsDouble(0, negativeZero()));
17332 RUN(testDivImmsDouble(negativeZero(), negativeZero()));
17333 RUN_UNARY(testDivArgFloat, floatingPointOperands<float>());
17334 RUN_BINARY(testDivArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17335 RUN_BINARY(testDivArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17336 RUN_BINARY(testDivImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17337 RUN_BINARY(testDivImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17338 RUN_UNARY(testDivArgFloatWithUselessDoubleConversion, floatingPointOperands<float>());
17339 RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17340 RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17341
17342 RUN_BINARY(testUDivArgsInt32, int32Operands(), int32Operands());
17343 RUN_BINARY(testUDivArgsInt64, int64Operands(), int64Operands());
17344
17345 RUN_UNARY(testModArgDouble, floatingPointOperands<double>());
17346 RUN_BINARY(testModArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17347 RUN_BINARY(testModArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17348 RUN_BINARY(testModImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17349 RUN_BINARY(testModImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17350 RUN_UNARY(testModArgFloat, floatingPointOperands<float>());
17351 RUN_BINARY(testModArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17352 RUN_BINARY(testModArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17353 RUN_BINARY(testModImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17354 RUN_BINARY(testModImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17355
17356 RUN_BINARY(testUModArgsInt32, int32Operands(), int32Operands());
17357 RUN_BINARY(testUModArgsInt64, int64Operands(), int64Operands());
17358
17359 RUN(testSubArg(24));
17360 RUN(testSubArgs(1, 1));
17361 RUN(testSubArgs(1, 2));
17362 RUN(testSubArgs(13, -42));
17363 RUN(testSubArgs(-13, 42));
17364 RUN(testSubArgImm(1, 1));
17365 RUN(testSubArgImm(1, 2));
17366 RUN(testSubArgImm(13, -42));
17367 RUN(testSubArgImm(-13, 42));
17368 RUN(testSubArgImm(42, 0));
17369 RUN(testSubImmArg(1, 1));
17370 RUN(testSubImmArg(1, 2));
17371 RUN(testSubImmArg(13, -42));
17372 RUN(testSubImmArg(-13, 42));
17373 RUN_BINARY(testSubArgMem, int64Operands(), int64Operands());
17374 RUN_BINARY(testSubMemArg, int64Operands(), int64Operands());
17375 RUN_BINARY(testSubImmMem, int32Operands(), int32Operands());
17376 RUN_BINARY(testSubMemImm, int32Operands(), int32Operands());
17377 RUN_BINARY(testSubNeg, int32Operands(), int32Operands());
17378 RUN_BINARY(testNegSub, int32Operands(), int32Operands());
17379 RUN_UNARY(testNegValueSubOne, int32Operands());
17380 RUN_BINARY(testNegMulArgImm, int64Operands(), int64Operands());
17381 RUN_TERNARY(testSubMulMulArgs, int64Operands(), int64Operands(), int64Operands());
17382
17383 RUN(testSubArgs32(1, 1));
17384 RUN(testSubArgs32(1, 2));
17385 RUN(testSubArgs32(13, -42));
17386 RUN(testSubArgs32(-13, 42));
17387 RUN(testSubArgImm32(1, 1));
17388 RUN(testSubArgImm32(1, 2));
17389 RUN(testSubArgImm32(13, -42));
17390 RUN(testSubArgImm32(-13, 42));
17391 RUN(testSubImmArg32(1, 1));
17392 RUN(testSubImmArg32(1, 2));
17393 RUN(testSubImmArg32(13, -42));
17394 RUN(testSubImmArg32(-13, 42));
17395 RUN_BINARY(testSubArgMem32, int32Operands(), int32Operands());
17396 RUN_BINARY(testSubMemArg32, int32Operands(), int32Operands());
17397 RUN_BINARY(testSubImmMem32, int32Operands(), int32Operands());
17398 RUN_BINARY(testSubMemImm32, int32Operands(), int32Operands());
17399 RUN_UNARY(testNegValueSubOne32, int64Operands());
17400
17401 RUN_UNARY(testSubArgDouble, floatingPointOperands<double>());
17402 RUN_BINARY(testSubArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17403 RUN_BINARY(testSubArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17404 RUN_BINARY(testSubImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17405 RUN_BINARY(testSubImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17406 RUN_UNARY(testSubArgFloat, floatingPointOperands<float>());
17407 RUN_BINARY(testSubArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17408 RUN_BINARY(testSubArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17409 RUN_BINARY(testSubImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17410 RUN_BINARY(testSubImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17411 RUN_UNARY(testSubArgFloatWithUselessDoubleConversion, floatingPointOperands<float>());
17412 RUN_BINARY(testSubArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17413 RUN_BINARY(testSubArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17414
17415 RUN_UNARY(testNegDouble, floatingPointOperands<double>());
17416 RUN_UNARY(testNegFloat, floatingPointOperands<float>());
17417 RUN_UNARY(testNegFloatWithUselessDoubleConversion, floatingPointOperands<float>());
17418
17419 RUN(testBitAndArgs(43, 43));
17420 RUN(testBitAndArgs(43, 0));
17421 RUN(testBitAndArgs(10, 3));
17422 RUN(testBitAndArgs(42, 0xffffffffffffffff));
17423 RUN(testBitAndSameArg(43));
17424 RUN(testBitAndSameArg(0));
17425 RUN(testBitAndSameArg(3));
17426 RUN(testBitAndSameArg(0xffffffffffffffff));
17427 RUN(testBitAndImms(43, 43));
17428 RUN(testBitAndImms(43, 0));
17429 RUN(testBitAndImms(10, 3));
17430 RUN(testBitAndImms(42, 0xffffffffffffffff));
17431 RUN(testBitAndArgImm(43, 43));
17432 RUN(testBitAndArgImm(43, 0));
17433 RUN(testBitAndArgImm(10, 3));
17434 RUN(testBitAndArgImm(42, 0xffffffffffffffff));
17435 RUN(testBitAndArgImm(42, 0xff));
17436 RUN(testBitAndArgImm(300, 0xff));
17437 RUN(testBitAndArgImm(-300, 0xff));
17438 RUN(testBitAndArgImm(42, 0xffff));
17439 RUN(testBitAndArgImm(40000, 0xffff));
17440 RUN(testBitAndArgImm(-40000, 0xffff));
17441 RUN(testBitAndImmArg(43, 43));
17442 RUN(testBitAndImmArg(43, 0));
17443 RUN(testBitAndImmArg(10, 3));
17444 RUN(testBitAndImmArg(42, 0xffffffffffffffff));
17445 RUN(testBitAndBitAndArgImmImm(2, 7, 3));
17446 RUN(testBitAndBitAndArgImmImm(1, 6, 6));
17447 RUN(testBitAndBitAndArgImmImm(0xffff, 24, 7));
17448 RUN(testBitAndImmBitAndArgImm(7, 2, 3));
17449 RUN(testBitAndImmBitAndArgImm(6, 1, 6));
17450 RUN(testBitAndImmBitAndArgImm(24, 0xffff, 7));
17451 RUN(testBitAndArgs32(43, 43));
17452 RUN(testBitAndArgs32(43, 0));
17453 RUN(testBitAndArgs32(10, 3));
17454 RUN(testBitAndArgs32(42, 0xffffffff));
17455 RUN(testBitAndSameArg32(43));
17456 RUN(testBitAndSameArg32(0));
17457 RUN(testBitAndSameArg32(3));
17458 RUN(testBitAndSameArg32(0xffffffff));
17459 RUN(testBitAndImms32(43, 43));
17460 RUN(testBitAndImms32(43, 0));
17461 RUN(testBitAndImms32(10, 3));
17462 RUN(testBitAndImms32(42, 0xffffffff));
17463 RUN(testBitAndArgImm32(43, 43));
17464 RUN(testBitAndArgImm32(43, 0));
17465 RUN(testBitAndArgImm32(10, 3));
17466 RUN(testBitAndArgImm32(42, 0xffffffff));
17467 RUN(testBitAndImmArg32(43, 43));
17468 RUN(testBitAndImmArg32(43, 0));
17469 RUN(testBitAndImmArg32(10, 3));
17470 RUN(testBitAndImmArg32(42, 0xffffffff));
17471 RUN(testBitAndImmArg32(42, 0xff));
17472 RUN(testBitAndImmArg32(300, 0xff));
17473 RUN(testBitAndImmArg32(-300, 0xff));
17474 RUN(testBitAndImmArg32(42, 0xffff));
17475 RUN(testBitAndImmArg32(40000, 0xffff));
17476 RUN(testBitAndImmArg32(-40000, 0xffff));
17477 RUN(testBitAndBitAndArgImmImm32(2, 7, 3));
17478 RUN(testBitAndBitAndArgImmImm32(1, 6, 6));
17479 RUN(testBitAndBitAndArgImmImm32(0xffff, 24, 7));
17480 RUN(testBitAndImmBitAndArgImm32(7, 2, 3));
17481 RUN(testBitAndImmBitAndArgImm32(6, 1, 6));
17482 RUN(testBitAndImmBitAndArgImm32(24, 0xffff, 7));
17483 RUN_BINARY(testBitAndWithMaskReturnsBooleans, int64Operands(), int64Operands());
17484 RUN_UNARY(testBitAndArgDouble, floatingPointOperands<double>());
17485 RUN_BINARY(testBitAndArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17486 RUN_BINARY(testBitAndArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17487 RUN_BINARY(testBitAndImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17488 RUN_UNARY(testBitAndArgFloat, floatingPointOperands<float>());
17489 RUN_BINARY(testBitAndArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17490 RUN_BINARY(testBitAndArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17491 RUN_BINARY(testBitAndImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17492 RUN_BINARY(testBitAndArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17493 RUN_BINARY(testBitAndNotNot, int64Operands(), int64Operands());
17494 RUN_BINARY(testBitAndNotImm, int64Operands(), int64Operands());
17495
17496 RUN(testBitOrArgs(43, 43));
17497 RUN(testBitOrArgs(43, 0));
17498 RUN(testBitOrArgs(10, 3));
17499 RUN(testBitOrArgs(42, 0xffffffffffffffff));
17500 RUN(testBitOrSameArg(43));
17501 RUN(testBitOrSameArg(0));
17502 RUN(testBitOrSameArg(3));
17503 RUN(testBitOrSameArg(0xffffffffffffffff));
17504 RUN(testBitOrImms(43, 43));
17505 RUN(testBitOrImms(43, 0));
17506 RUN(testBitOrImms(10, 3));
17507 RUN(testBitOrImms(42, 0xffffffffffffffff));
17508 RUN(testBitOrArgImm(43, 43));
17509 RUN(testBitOrArgImm(43, 0));
17510 RUN(testBitOrArgImm(10, 3));
17511 RUN(testBitOrArgImm(42, 0xffffffffffffffff));
17512 RUN(testBitOrImmArg(43, 43));
17513 RUN(testBitOrImmArg(43, 0));
17514 RUN(testBitOrImmArg(10, 3));
17515 RUN(testBitOrImmArg(42, 0xffffffffffffffff));
17516 RUN(testBitOrBitOrArgImmImm(2, 7, 3));
17517 RUN(testBitOrBitOrArgImmImm(1, 6, 6));
17518 RUN(testBitOrBitOrArgImmImm(0xffff, 24, 7));
17519 RUN(testBitOrImmBitOrArgImm(7, 2, 3));
17520 RUN(testBitOrImmBitOrArgImm(6, 1, 6));
17521 RUN(testBitOrImmBitOrArgImm(24, 0xffff, 7));
17522 RUN(testBitOrArgs32(43, 43));
17523 RUN(testBitOrArgs32(43, 0));
17524 RUN(testBitOrArgs32(10, 3));
17525 RUN(testBitOrArgs32(42, 0xffffffff));
17526 RUN(testBitOrSameArg32(43));
17527 RUN(testBitOrSameArg32(0));
17528 RUN(testBitOrSameArg32(3));
17529 RUN(testBitOrSameArg32(0xffffffff));
17530 RUN(testBitOrImms32(43, 43));
17531 RUN(testBitOrImms32(43, 0));
17532 RUN(testBitOrImms32(10, 3));
17533 RUN(testBitOrImms32(42, 0xffffffff));
17534 RUN(testBitOrArgImm32(43, 43));
17535 RUN(testBitOrArgImm32(43, 0));
17536 RUN(testBitOrArgImm32(10, 3));
17537 RUN(testBitOrArgImm32(42, 0xffffffff));
17538 RUN(testBitOrImmArg32(43, 43));
17539 RUN(testBitOrImmArg32(43, 0));
17540 RUN(testBitOrImmArg32(10, 3));
17541 RUN(testBitOrImmArg32(42, 0xffffffff));
17542 RUN(testBitOrBitOrArgImmImm32(2, 7, 3));
17543 RUN(testBitOrBitOrArgImmImm32(1, 6, 6));
17544 RUN(testBitOrBitOrArgImmImm32(0xffff, 24, 7));
17545 RUN(testBitOrImmBitOrArgImm32(7, 2, 3));
17546 RUN(testBitOrImmBitOrArgImm32(6, 1, 6));
17547 RUN(testBitOrImmBitOrArgImm32(24, 0xffff, 7));
17548 RUN_UNARY(testBitOrArgDouble, floatingPointOperands<double>());
17549 RUN_BINARY(testBitOrArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17550 RUN_BINARY(testBitOrArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17551 RUN_BINARY(testBitOrImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
17552 RUN_UNARY(testBitOrArgFloat, floatingPointOperands<float>());
17553 RUN_BINARY(testBitOrArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17554 RUN_BINARY(testBitOrArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17555 RUN_BINARY(testBitOrImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
17556 RUN_BINARY(testBitOrArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17557 RUN_TERNARY(testBitOrAndAndArgs, int64Operands(), int64Operands(), int64Operands());
17558 RUN_BINARY(testBitOrAndSameArgs, int64Operands(), int64Operands());
17559 RUN_BINARY(testBitOrNotNot, int64Operands(), int64Operands());
17560 RUN_BINARY(testBitOrNotImm, int64Operands(), int64Operands());
17561
17562 RUN_BINARY(testBitXorArgs, int64Operands(), int64Operands());
17563 RUN_UNARY(testBitXorSameArg, int64Operands());
17564 RUN_BINARY(testBitXorImms, int64Operands(), int64Operands());
17565 RUN_BINARY(testBitXorArgImm, int64Operands(), int64Operands());
17566 RUN_BINARY(testBitXorImmArg, int64Operands(), int64Operands());
17567 RUN(testBitXorBitXorArgImmImm(2, 7, 3));
17568 RUN(testBitXorBitXorArgImmImm(1, 6, 6));
17569 RUN(testBitXorBitXorArgImmImm(0xffff, 24, 7));
17570 RUN(testBitXorImmBitXorArgImm(7, 2, 3));
17571 RUN(testBitXorImmBitXorArgImm(6, 1, 6));
17572 RUN(testBitXorImmBitXorArgImm(24, 0xffff, 7));
17573 RUN(testBitXorArgs32(43, 43));
17574 RUN(testBitXorArgs32(43, 0));
17575 RUN(testBitXorArgs32(10, 3));
17576 RUN(testBitXorArgs32(42, 0xffffffff));
17577 RUN(testBitXorSameArg32(43));
17578 RUN(testBitXorSameArg32(0));
17579 RUN(testBitXorSameArg32(3));
17580 RUN(testBitXorSameArg32(0xffffffff));
17581 RUN(testBitXorImms32(43, 43));
17582 RUN(testBitXorImms32(43, 0));
17583 RUN(testBitXorImms32(10, 3));
17584 RUN(testBitXorImms32(42, 0xffffffff));
17585 RUN(testBitXorArgImm32(43, 43));
17586 RUN(testBitXorArgImm32(43, 0));
17587 RUN(testBitXorArgImm32(10, 3));
17588 RUN(testBitXorArgImm32(42, 0xffffffff));
17589 RUN(testBitXorImmArg32(43, 43));
17590 RUN(testBitXorImmArg32(43, 0));
17591 RUN(testBitXorImmArg32(10, 3));
17592 RUN(testBitXorImmArg32(42, 0xffffffff));
17593 RUN(testBitXorBitXorArgImmImm32(2, 7, 3));
17594 RUN(testBitXorBitXorArgImmImm32(1, 6, 6));
17595 RUN(testBitXorBitXorArgImmImm32(0xffff, 24, 7));
17596 RUN(testBitXorImmBitXorArgImm32(7, 2, 3));
17597 RUN(testBitXorImmBitXorArgImm32(6, 1, 6));
17598 RUN(testBitXorImmBitXorArgImm32(24, 0xffff, 7));
17599 RUN_TERNARY(testBitXorAndAndArgs, int64Operands(), int64Operands(), int64Operands());
17600 RUN_BINARY(testBitXorAndSameArgs, int64Operands(), int64Operands());
17601
17602 RUN_UNARY(testBitNotArg, int64Operands());
17603 RUN_UNARY(testBitNotImm, int64Operands());
17604 RUN_UNARY(testBitNotMem, int64Operands());
17605 RUN_UNARY(testBitNotArg32, int32Operands());
17606 RUN_UNARY(testBitNotImm32, int32Operands());
17607 RUN_UNARY(testBitNotMem32, int32Operands());
17608 RUN_BINARY(testNotOnBooleanAndBranch32, int32Operands(), int32Operands());
17609 RUN_BINARY(testBitNotOnBooleanAndBranch32, int32Operands(), int32Operands());
17610
17611 RUN(testShlArgs(1, 0));
17612 RUN(testShlArgs(1, 1));
17613 RUN(testShlArgs(1, 62));
17614 RUN(testShlArgs(0xffffffffffffffff, 0));
17615 RUN(testShlArgs(0xffffffffffffffff, 1));
17616 RUN(testShlArgs(0xffffffffffffffff, 63));
17617 RUN(testShlImms(1, 0));
17618 RUN(testShlImms(1, 1));
17619 RUN(testShlImms(1, 62));
17620 RUN(testShlImms(1, 65));
17621 RUN(testShlImms(0xffffffffffffffff, 0));
17622 RUN(testShlImms(0xffffffffffffffff, 1));
17623 RUN(testShlImms(0xffffffffffffffff, 63));
17624 RUN(testShlArgImm(1, 0));
17625 RUN(testShlArgImm(1, 1));
17626 RUN(testShlArgImm(1, 62));
17627 RUN(testShlArgImm(1, 65));
17628 RUN(testShlArgImm(0xffffffffffffffff, 0));
17629 RUN(testShlArgImm(0xffffffffffffffff, 1));
17630 RUN(testShlArgImm(0xffffffffffffffff, 63));
17631 RUN(testShlSShrArgImm(1, 0));
17632 RUN(testShlSShrArgImm(1, 1));
17633 RUN(testShlSShrArgImm(1, 62));
17634 RUN(testShlSShrArgImm(1, 65));
17635 RUN(testShlSShrArgImm(0xffffffffffffffff, 0));
17636 RUN(testShlSShrArgImm(0xffffffffffffffff, 1));
17637 RUN(testShlSShrArgImm(0xffffffffffffffff, 63));
17638 RUN(testShlArg32(2));
17639 RUN(testShlArgs32(1, 0));
17640 RUN(testShlArgs32(1, 1));
17641 RUN(testShlArgs32(1, 62));
17642 RUN(testShlImms32(1, 33));
17643 RUN(testShlArgs32(0xffffffff, 0));
17644 RUN(testShlArgs32(0xffffffff, 1));
17645 RUN(testShlArgs32(0xffffffff, 63));
17646 RUN(testShlImms32(1, 0));
17647 RUN(testShlImms32(1, 1));
17648 RUN(testShlImms32(1, 62));
17649 RUN(testShlImms32(1, 33));
17650 RUN(testShlImms32(0xffffffff, 0));
17651 RUN(testShlImms32(0xffffffff, 1));
17652 RUN(testShlImms32(0xffffffff, 63));
17653 RUN(testShlArgImm32(1, 0));
17654 RUN(testShlArgImm32(1, 1));
17655 RUN(testShlArgImm32(1, 62));
17656 RUN(testShlArgImm32(1, 33));
17657 RUN(testShlArgImm32(0xffffffff, 0));
17658 RUN(testShlArgImm32(0xffffffff, 1));
17659 RUN(testShlArgImm32(0xffffffff, 63));
17660 RUN(testShlZShrArgImm32(1, 0));
17661 RUN(testShlZShrArgImm32(1, 1));
17662 RUN(testShlZShrArgImm32(1, 62));
17663 RUN(testShlZShrArgImm32(1, 33));
17664 RUN(testShlZShrArgImm32(0xffffffff, 0));
17665 RUN(testShlZShrArgImm32(0xffffffff, 1));
17666 RUN(testShlZShrArgImm32(0xffffffff, 63));
17667
17668 RUN(testSShrArgs(1, 0));
17669 RUN(testSShrArgs(1, 1));
17670 RUN(testSShrArgs(1, 62));
17671 RUN(testSShrArgs(0xffffffffffffffff, 0));
17672 RUN(testSShrArgs(0xffffffffffffffff, 1));
17673 RUN(testSShrArgs(0xffffffffffffffff, 63));
17674 RUN(testSShrImms(1, 0));
17675 RUN(testSShrImms(1, 1));
17676 RUN(testSShrImms(1, 62));
17677 RUN(testSShrImms(1, 65));
17678 RUN(testSShrImms(0xffffffffffffffff, 0));
17679 RUN(testSShrImms(0xffffffffffffffff, 1));
17680 RUN(testSShrImms(0xffffffffffffffff, 63));
17681 RUN(testSShrArgImm(1, 0));
17682 RUN(testSShrArgImm(1, 1));
17683 RUN(testSShrArgImm(1, 62));
17684 RUN(testSShrArgImm(1, 65));
17685 RUN(testSShrArgImm(0xffffffffffffffff, 0));
17686 RUN(testSShrArgImm(0xffffffffffffffff, 1));
17687 RUN(testSShrArgImm(0xffffffffffffffff, 63));
17688 RUN(testSShrArg32(32));
17689 RUN(testSShrArgs32(1, 0));
17690 RUN(testSShrArgs32(1, 1));
17691 RUN(testSShrArgs32(1, 62));
17692 RUN(testSShrArgs32(1, 33));
17693 RUN(testSShrArgs32(0xffffffff, 0));
17694 RUN(testSShrArgs32(0xffffffff, 1));
17695 RUN(testSShrArgs32(0xffffffff, 63));
17696 RUN(testSShrImms32(1, 0));
17697 RUN(testSShrImms32(1, 1));
17698 RUN(testSShrImms32(1, 62));
17699 RUN(testSShrImms32(1, 33));
17700 RUN(testSShrImms32(0xffffffff, 0));
17701 RUN(testSShrImms32(0xffffffff, 1));
17702 RUN(testSShrImms32(0xffffffff, 63));
17703 RUN(testSShrArgImm32(1, 0));
17704 RUN(testSShrArgImm32(1, 1));
17705 RUN(testSShrArgImm32(1, 62));
17706 RUN(testSShrArgImm32(0xffffffff, 0));
17707 RUN(testSShrArgImm32(0xffffffff, 1));
17708 RUN(testSShrArgImm32(0xffffffff, 63));
17709
17710 RUN(testZShrArgs(1, 0));
17711 RUN(testZShrArgs(1, 1));
17712 RUN(testZShrArgs(1, 62));
17713 RUN(testZShrArgs(0xffffffffffffffff, 0));
17714 RUN(testZShrArgs(0xffffffffffffffff, 1));
17715 RUN(testZShrArgs(0xffffffffffffffff, 63));
17716 RUN(testZShrImms(1, 0));
17717 RUN(testZShrImms(1, 1));
17718 RUN(testZShrImms(1, 62));
17719 RUN(testZShrImms(1, 65));
17720 RUN(testZShrImms(0xffffffffffffffff, 0));
17721 RUN(testZShrImms(0xffffffffffffffff, 1));
17722 RUN(testZShrImms(0xffffffffffffffff, 63));
17723 RUN(testZShrArgImm(1, 0));
17724 RUN(testZShrArgImm(1, 1));
17725 RUN(testZShrArgImm(1, 62));
17726 RUN(testZShrArgImm(1, 65));
17727 RUN(testZShrArgImm(0xffffffffffffffff, 0));
17728 RUN(testZShrArgImm(0xffffffffffffffff, 1));
17729 RUN(testZShrArgImm(0xffffffffffffffff, 63));
17730 RUN(testZShrArg32(32));
17731 RUN(testZShrArgs32(1, 0));
17732 RUN(testZShrArgs32(1, 1));
17733 RUN(testZShrArgs32(1, 62));
17734 RUN(testZShrArgs32(1, 33));
17735 RUN(testZShrArgs32(0xffffffff, 0));
17736 RUN(testZShrArgs32(0xffffffff, 1));
17737 RUN(testZShrArgs32(0xffffffff, 63));
17738 RUN(testZShrImms32(1, 0));
17739 RUN(testZShrImms32(1, 1));
17740 RUN(testZShrImms32(1, 62));
17741 RUN(testZShrImms32(1, 33));
17742 RUN(testZShrImms32(0xffffffff, 0));
17743 RUN(testZShrImms32(0xffffffff, 1));
17744 RUN(testZShrImms32(0xffffffff, 63));
17745 RUN(testZShrArgImm32(1, 0));
17746 RUN(testZShrArgImm32(1, 1));
17747 RUN(testZShrArgImm32(1, 62));
17748 RUN(testZShrArgImm32(0xffffffff, 0));
17749 RUN(testZShrArgImm32(0xffffffff, 1));
17750 RUN(testZShrArgImm32(0xffffffff, 63));
17751
17752 RUN_UNARY(testClzArg64, int64Operands());
17753 RUN_UNARY(testClzMem64, int64Operands());
17754 RUN_UNARY(testClzArg32, int32Operands());
17755 RUN_UNARY(testClzMem32, int64Operands());
17756
17757 RUN_UNARY(testAbsArg, floatingPointOperands<double>());
17758 RUN_UNARY(testAbsImm, floatingPointOperands<double>());
17759 RUN_UNARY(testAbsMem, floatingPointOperands<double>());
17760 RUN_UNARY(testAbsAbsArg, floatingPointOperands<double>());
17761 RUN_UNARY(testAbsNegArg, floatingPointOperands<double>());
17762 RUN_UNARY(testAbsBitwiseCastArg, floatingPointOperands<double>());
17763 RUN_UNARY(testBitwiseCastAbsBitwiseCastArg, floatingPointOperands<double>());
17764 RUN_UNARY(testAbsArg, floatingPointOperands<float>());
17765 RUN_UNARY(testAbsImm, floatingPointOperands<float>());
17766 RUN_UNARY(testAbsMem, floatingPointOperands<float>());
17767 RUN_UNARY(testAbsAbsArg, floatingPointOperands<float>());
17768 RUN_UNARY(testAbsNegArg, floatingPointOperands<float>());
17769 RUN_UNARY(testAbsBitwiseCastArg, floatingPointOperands<float>());
17770 RUN_UNARY(testBitwiseCastAbsBitwiseCastArg, floatingPointOperands<float>());
17771 RUN_UNARY(testAbsArgWithUselessDoubleConversion, floatingPointOperands<float>());
17772 RUN_UNARY(testAbsArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
17773
17774 RUN_UNARY(testCeilArg, floatingPointOperands<double>());
17775 RUN_UNARY(testCeilImm, floatingPointOperands<double>());
17776 RUN_UNARY(testCeilMem, floatingPointOperands<double>());
17777 RUN_UNARY(testCeilCeilArg, floatingPointOperands<double>());
17778 RUN_UNARY(testFloorCeilArg, floatingPointOperands<double>());
17779 RUN_UNARY(testCeilIToD64, int64Operands());
17780 RUN_UNARY(testCeilIToD32, int32Operands());
17781 RUN_UNARY(testCeilArg, floatingPointOperands<float>());
17782 RUN_UNARY(testCeilImm, floatingPointOperands<float>());
17783 RUN_UNARY(testCeilMem, floatingPointOperands<float>());
17784 RUN_UNARY(testCeilCeilArg, floatingPointOperands<float>());
17785 RUN_UNARY(testFloorCeilArg, floatingPointOperands<float>());
17786 RUN_UNARY(testCeilArgWithUselessDoubleConversion, floatingPointOperands<float>());
17787 RUN_UNARY(testCeilArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
17788
17789 RUN_UNARY(testFloorArg, floatingPointOperands<double>());
17790 RUN_UNARY(testFloorImm, floatingPointOperands<double>());
17791 RUN_UNARY(testFloorMem, floatingPointOperands<double>());
17792 RUN_UNARY(testFloorFloorArg, floatingPointOperands<double>());
17793 RUN_UNARY(testCeilFloorArg, floatingPointOperands<double>());
17794 RUN_UNARY(testFloorIToD64, int64Operands());
17795 RUN_UNARY(testFloorIToD32, int32Operands());
17796 RUN_UNARY(testFloorArg, floatingPointOperands<float>());
17797 RUN_UNARY(testFloorImm, floatingPointOperands<float>());
17798 RUN_UNARY(testFloorMem, floatingPointOperands<float>());
17799 RUN_UNARY(testFloorFloorArg, floatingPointOperands<float>());
17800 RUN_UNARY(testCeilFloorArg, floatingPointOperands<float>());
17801 RUN_UNARY(testFloorArgWithUselessDoubleConversion, floatingPointOperands<float>());
17802 RUN_UNARY(testFloorArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
17803
17804 RUN_UNARY(testSqrtArg, floatingPointOperands<double>());
17805 RUN_UNARY(testSqrtImm, floatingPointOperands<double>());
17806 RUN_UNARY(testSqrtMem, floatingPointOperands<double>());
17807 RUN_UNARY(testSqrtArg, floatingPointOperands<float>());
17808 RUN_UNARY(testSqrtImm, floatingPointOperands<float>());
17809 RUN_UNARY(testSqrtMem, floatingPointOperands<float>());
17810 RUN_UNARY(testSqrtArgWithUselessDoubleConversion, floatingPointOperands<float>());
17811 RUN_UNARY(testSqrtArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
17812
17813 RUN_BINARY(testCompareTwoFloatToDouble, floatingPointOperands<float>(), floatingPointOperands<float>());
17814 RUN_BINARY(testCompareOneFloatToDouble, floatingPointOperands<float>(), floatingPointOperands<double>());
17815 RUN_BINARY(testCompareFloatToDoubleThroughPhi, floatingPointOperands<float>(), floatingPointOperands<float>());
17816 RUN_UNARY(testDoubleToFloatThroughPhi, floatingPointOperands<float>());
17817 RUN(testReduceFloatToDoubleValidates());
17818 RUN_UNARY(testDoubleProducerPhiToFloatConversion, floatingPointOperands<float>());
17819 RUN_UNARY(testDoubleProducerPhiToFloatConversionWithDoubleConsumer, floatingPointOperands<float>());
17820 RUN_BINARY(testDoubleProducerPhiWithNonFloatConst, floatingPointOperands<float>(), floatingPointOperands<double>());
17821
17822 RUN_UNARY(testDoubleArgToInt64BitwiseCast, floatingPointOperands<double>());
17823 RUN_UNARY(testDoubleImmToInt64BitwiseCast, floatingPointOperands<double>());
17824 RUN_UNARY(testTwoBitwiseCastOnDouble, floatingPointOperands<double>());
17825 RUN_UNARY(testBitwiseCastOnDoubleInMemory, floatingPointOperands<double>());
17826 RUN_UNARY(testBitwiseCastOnDoubleInMemoryIndexed, floatingPointOperands<double>());
17827 RUN_UNARY(testInt64BArgToDoubleBitwiseCast, int64Operands());
17828 RUN_UNARY(testInt64BImmToDoubleBitwiseCast, int64Operands());
17829 RUN_UNARY(testTwoBitwiseCastOnInt64, int64Operands());
17830 RUN_UNARY(testBitwiseCastOnInt64InMemory, int64Operands());
17831 RUN_UNARY(testBitwiseCastOnInt64InMemoryIndexed, int64Operands());
17832 RUN_UNARY(testFloatImmToInt32BitwiseCast, floatingPointOperands<float>());
17833 RUN_UNARY(testBitwiseCastOnFloatInMemory, floatingPointOperands<float>());
17834 RUN_UNARY(testInt32BArgToFloatBitwiseCast, int32Operands());
17835 RUN_UNARY(testInt32BImmToFloatBitwiseCast, int32Operands());
17836 RUN_UNARY(testTwoBitwiseCastOnInt32, int32Operands());
17837 RUN_UNARY(testBitwiseCastOnInt32InMemory, int32Operands());
17838
17839 RUN_UNARY(testConvertDoubleToFloatArg, floatingPointOperands<double>());
17840 RUN_UNARY(testConvertDoubleToFloatImm, floatingPointOperands<double>());
17841 RUN_UNARY(testConvertDoubleToFloatMem, floatingPointOperands<double>());
17842 RUN_UNARY(testConvertFloatToDoubleArg, floatingPointOperands<float>());
17843 RUN_UNARY(testConvertFloatToDoubleImm, floatingPointOperands<float>());
17844 RUN_UNARY(testConvertFloatToDoubleMem, floatingPointOperands<float>());
17845 RUN_UNARY(testConvertDoubleToFloatToDoubleToFloat, floatingPointOperands<double>());
17846 RUN_UNARY(testStoreFloat, floatingPointOperands<double>());
17847 RUN_UNARY(testStoreDoubleConstantAsFloat, floatingPointOperands<double>());
17848 RUN_UNARY(testLoadFloatConvertDoubleConvertFloatStoreFloat, floatingPointOperands<float>());
17849 RUN_UNARY(testFroundArg, floatingPointOperands<double>());
17850 RUN_UNARY(testFroundMem, floatingPointOperands<double>());
17851
17852 RUN(testIToD64Arg());
17853 RUN(testIToF64Arg());
17854 RUN(testIToD32Arg());
17855 RUN(testIToF32Arg());
17856 RUN(testIToD64Mem());
17857 RUN(testIToF64Mem());
17858 RUN(testIToD32Mem());
17859 RUN(testIToF32Mem());
17860 RUN_UNARY(testIToD64Imm, int64Operands());
17861 RUN_UNARY(testIToF64Imm, int64Operands());
17862 RUN_UNARY(testIToD32Imm, int32Operands());
17863 RUN_UNARY(testIToF32Imm, int32Operands());
17864 RUN(testIToDReducedToIToF64Arg());
17865 RUN(testIToDReducedToIToF32Arg());
17866
17867 RUN(testStore32(44));
17868 RUN(testStoreConstant(49));
17869 RUN(testStoreConstantPtr(49));
17870 RUN(testStore8Arg());
17871 RUN(testStore8Imm());
17872 RUN(testStorePartial8BitRegisterOnX86());
17873 RUN(testStore16Arg());
17874 RUN(testStore16Imm());
17875 RUN(testTrunc((static_cast<int64_t>(1) << 40) + 42));
17876 RUN(testAdd1(45));
17877 RUN(testAdd1Ptr(51));
17878 RUN(testAdd1Ptr(static_cast<intptr_t>(0xbaadbeef)));
17879 RUN(testNeg32(52));
17880 RUN(testNegPtr(53));
17881 RUN(testStoreAddLoad32(46));
17882 RUN(testStoreRelAddLoadAcq32(46));
17883 RUN(testStoreAddLoadImm32(46));
17884 RUN(testStoreAddLoad64(4600));
17885 RUN(testStoreRelAddLoadAcq64(4600));
17886 RUN(testStoreAddLoadImm64(4600));
17887 RUN(testStoreAddLoad8(4, Load8Z));
17888 RUN(testStoreRelAddLoadAcq8(4, Load8Z));
17889 RUN(testStoreRelAddFenceLoadAcq8(4, Load8Z));
17890 RUN(testStoreAddLoadImm8(4, Load8Z));
17891 RUN(testStoreAddLoad8(4, Load8S));
17892 RUN(testStoreRelAddLoadAcq8(4, Load8S));
17893 RUN(testStoreAddLoadImm8(4, Load8S));
17894 RUN(testStoreAddLoad16(6, Load16Z));
17895 RUN(testStoreRelAddLoadAcq16(6, Load16Z));
17896 RUN(testStoreAddLoadImm16(6, Load16Z));
17897 RUN(testStoreAddLoad16(6, Load16S));
17898 RUN(testStoreRelAddLoadAcq16(6, Load16S));
17899 RUN(testStoreAddLoadImm16(6, Load16S));
17900 RUN(testStoreAddLoad32Index(46));
17901 RUN(testStoreAddLoadImm32Index(46));
17902 RUN(testStoreAddLoad64Index(4600));
17903 RUN(testStoreAddLoadImm64Index(4600));
17904 RUN(testStoreAddLoad8Index(4, Load8Z));
17905 RUN(testStoreAddLoadImm8Index(4, Load8Z));
17906 RUN(testStoreAddLoad8Index(4, Load8S));
17907 RUN(testStoreAddLoadImm8Index(4, Load8S));
17908 RUN(testStoreAddLoad16Index(6, Load16Z));
17909 RUN(testStoreAddLoadImm16Index(6, Load16Z));
17910 RUN(testStoreAddLoad16Index(6, Load16S));
17911 RUN(testStoreAddLoadImm16Index(6, Load16S));
17912 RUN(testStoreSubLoad(46));
17913 RUN(testStoreAddLoadInterference(52));
17914 RUN(testStoreAddAndLoad(47, 0xffff));
17915 RUN(testStoreAddAndLoad(470000, 0xffff));
17916 RUN(testStoreNegLoad32(54));
17917 RUN(testStoreNegLoadPtr(55));
17918 RUN(testAdd1Uncommuted(48));
17919 RUN(testLoadOffset());
17920 RUN(testLoadOffsetNotConstant());
17921 RUN(testLoadOffsetUsingAdd());
17922 RUN(testLoadOffsetUsingAddInterference());
17923 RUN(testLoadOffsetUsingAddNotConstant());
17924 RUN(testLoadAddrShift(0));
17925 RUN(testLoadAddrShift(1));
17926 RUN(testLoadAddrShift(2));
17927 RUN(testLoadAddrShift(3));
17928 RUN(testFramePointer());
17929 RUN(testOverrideFramePointer());
17930 RUN(testStackSlot());
17931 RUN(testLoadFromFramePointer());
17932 RUN(testStoreLoadStackSlot(50));
17933
17934 RUN(testBranch());
17935 RUN(testBranchPtr());
17936 RUN(testDiamond());
17937 RUN(testBranchNotEqual());
17938 RUN(testBranchNotEqualCommute());
17939 RUN(testBranchNotEqualNotEqual());
17940 RUN(testBranchEqual());
17941 RUN(testBranchEqualEqual());
17942 RUN(testBranchEqualCommute());
17943 RUN(testBranchEqualEqual1());
17944 RUN_BINARY(testBranchEqualOrUnorderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>());
17945 RUN_BINARY(testBranchEqualOrUnorderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>());
17946 RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>());
17947 RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>());
17948 RUN_BINARY(testBranchEqualOrUnorderedDoubleArgImm, floatingPointOperands<double>(), floatingPointOperands<double>());
17949 RUN_BINARY(testBranchEqualOrUnorderedFloatArgImm, floatingPointOperands<float>(), floatingPointOperands<float>());
17950 RUN_BINARY(testBranchEqualOrUnorderedDoubleImms, floatingPointOperands<double>(), floatingPointOperands<double>());
17951 RUN_BINARY(testBranchEqualOrUnorderedFloatImms, floatingPointOperands<float>(), floatingPointOperands<float>());
17952 RUN_BINARY(testBranchEqualOrUnorderedFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
17953 RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>());
17954 RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>());
17955 RUN(testBranchFold(42));
17956 RUN(testBranchFold(0));
17957 RUN(testDiamondFold(42));
17958 RUN(testDiamondFold(0));
17959 RUN(testBranchNotEqualFoldPtr(42));
17960 RUN(testBranchNotEqualFoldPtr(0));
17961 RUN(testBranchEqualFoldPtr(42));
17962 RUN(testBranchEqualFoldPtr(0));
17963 RUN(testBranchLoadPtr());
17964 RUN(testBranchLoad32());
17965 RUN(testBranchLoad8S());
17966 RUN(testBranchLoad8Z());
17967 RUN(testBranchLoad16S());
17968 RUN(testBranchLoad16Z());
17969 RUN(testBranch8WithLoad8ZIndex());
17970
17971 RUN(testComplex(64, 128));
17972 RUN(testComplex(4, 128));
17973 RUN(testComplex(4, 256));
17974 RUN(testComplex(4, 384));
17975
17976 RUN(testSimplePatchpoint());
17977 RUN(testSimplePatchpointWithoutOuputClobbersGPArgs());
17978 RUN(testSimplePatchpointWithOuputClobbersGPArgs());
17979 RUN(testSimplePatchpointWithoutOuputClobbersFPArgs());
17980 RUN(testSimplePatchpointWithOuputClobbersFPArgs());
17981 RUN(testPatchpointWithEarlyClobber());
17982 RUN(testPatchpointCallArg());
17983 RUN(testPatchpointFixedRegister());
17984 RUN(testPatchpointAny(ValueRep::WarmAny));
17985 RUN(testPatchpointAny(ValueRep::ColdAny));
17986 RUN(testPatchpointGPScratch());
17987 RUN(testPatchpointFPScratch());
17988 RUN(testPatchpointLotsOfLateAnys());
17989 RUN(testPatchpointAnyImm(ValueRep::WarmAny));
17990 RUN(testPatchpointAnyImm(ValueRep::ColdAny));
17991 RUN(testPatchpointAnyImm(ValueRep::LateColdAny));
17992 RUN(testPatchpointManyImms());
17993 RUN(testPatchpointWithRegisterResult());
17994 RUN(testPatchpointWithStackArgumentResult());
17995 RUN(testPatchpointWithAnyResult());
17996 RUN(testSimpleCheck());
17997 RUN(testCheckFalse());
17998 RUN(testCheckTrue());
17999 RUN(testCheckLessThan());
18000 RUN(testCheckMegaCombo());
18001 RUN(testCheckTrickyMegaCombo());
18002 RUN(testCheckTwoMegaCombos());
18003 RUN(testCheckTwoNonRedundantMegaCombos());
18004 RUN(testCheckAddImm());
18005 RUN(testCheckAddImmCommute());
18006 RUN(testCheckAddImmSomeRegister());
18007 RUN(testCheckAdd());
18008 RUN(testCheckAdd64());
18009 RUN(testCheckAddFold(100, 200));
18010 RUN(testCheckAddFoldFail(2147483647, 100));
18011 RUN(testCheckAddArgumentAliasing64());
18012 RUN(testCheckAddArgumentAliasing32());
18013 RUN(testCheckAddSelfOverflow64());
18014 RUN(testCheckAddSelfOverflow32());
18015 RUN(testCheckSubImm());
18016 RUN(testCheckSubBadImm());
18017 RUN(testCheckSub());
18018 RUN(testCheckSub64());
18019 RUN(testCheckSubFold(100, 200));
18020 RUN(testCheckSubFoldFail(-2147483647, 100));
18021 RUN(testCheckNeg());
18022 RUN(testCheckNeg64());
18023 RUN(testCheckMul());
18024 RUN(testCheckMulMemory());
18025 RUN(testCheckMul2());
18026 RUN(testCheckMul64());
18027 RUN(testCheckMulFold(100, 200));
18028 RUN(testCheckMulFoldFail(2147483647, 100));
18029 RUN(testCheckMulArgumentAliasing64());
18030 RUN(testCheckMulArgumentAliasing32());
18031
18032 RUN_BINARY([](int32_t a, int32_t b) { testCompare(Equal, a, b); }, int64Operands(), int64Operands());
18033 RUN_BINARY([](int32_t a, int32_t b) { testCompare(NotEqual, a, b); }, int64Operands(), int64Operands());
18034 RUN_BINARY([](int32_t a, int32_t b) { testCompare(LessThan, a, b); }, int64Operands(), int64Operands());
18035 RUN_BINARY([](int32_t a, int32_t b) { testCompare(GreaterThan, a, b); }, int64Operands(), int64Operands());
18036 RUN_BINARY([](int32_t a, int32_t b) { testCompare(LessEqual, a, b); }, int64Operands(), int64Operands());
18037 RUN_BINARY([](int32_t a, int32_t b) { testCompare(GreaterEqual, a, b); }, int64Operands(), int64Operands());
18038 RUN_BINARY([](int32_t a, int32_t b) { testCompare(Below, a, b); }, int64Operands(), int64Operands());
18039 RUN_BINARY([](int32_t a, int32_t b) { testCompare(Above, a, b); }, int64Operands(), int64Operands());
18040 RUN_BINARY([](int32_t a, int32_t b) { testCompare(BelowEqual, a, b); }, int64Operands(), int64Operands());
18041 RUN_BINARY([](int32_t a, int32_t b) { testCompare(AboveEqual, a, b); }, int64Operands(), int64Operands());
18042 RUN_BINARY([](int32_t a, int32_t b) { testCompare(BitAnd, a, b); }, int64Operands(), int64Operands());
18043
18044 RUN(testEqualDouble(42, 42, true));
18045 RUN(testEqualDouble(0, -0, true));
18046 RUN(testEqualDouble(42, 43, false));
18047 RUN(testEqualDouble(PNaN, 42, false));
18048 RUN(testEqualDouble(42, PNaN, false));
18049 RUN(testEqualDouble(PNaN, PNaN, false));
18050
18051 RUN(testLoad<Int32>(60));
18052 RUN(testLoad<Int32>(-60));
18053 RUN(testLoad<Int32>(1000));
18054 RUN(testLoad<Int32>(-1000));
18055 RUN(testLoad<Int32>(1000000));
18056 RUN(testLoad<Int32>(-1000000));
18057 RUN(testLoad<Int32>(1000000000));
18058 RUN(testLoad<Int32>(-1000000000));
18059 RUN_UNARY(testLoad<Int64>, int64Operands());
18060 RUN_UNARY(testLoad<Float>, floatingPointOperands<float>());
18061 RUN_UNARY(testLoad<Double>, floatingPointOperands<double>());
18062
18063 RUN(testLoad<int8_t>(Load8S, 60));
18064 RUN(testLoad<int8_t>(Load8S, -60));
18065 RUN(testLoad<int8_t>(Load8S, 1000));
18066 RUN(testLoad<int8_t>(Load8S, -1000));
18067 RUN(testLoad<int8_t>(Load8S, 1000000));
18068 RUN(testLoad<int8_t>(Load8S, -1000000));
18069 RUN(testLoad<int8_t>(Load8S, 1000000000));
18070 RUN(testLoad<int8_t>(Load8S, -1000000000));
18071
18072 RUN(testLoad<uint8_t>(Load8Z, 60));
18073 RUN(testLoad<uint8_t>(Load8Z, -60));
18074 RUN(testLoad<uint8_t>(Load8Z, 1000));
18075 RUN(testLoad<uint8_t>(Load8Z, -1000));
18076 RUN(testLoad<uint8_t>(Load8Z, 1000000));
18077 RUN(testLoad<uint8_t>(Load8Z, -1000000));
18078 RUN(testLoad<uint8_t>(Load8Z, 1000000000));
18079 RUN(testLoad<uint8_t>(Load8Z, -1000000000));
18080
18081 RUN(testLoad<int16_t>(Load16S, 60));
18082 RUN(testLoad<int16_t>(Load16S, -60));
18083 RUN(testLoad<int16_t>(Load16S, 1000));
18084 RUN(testLoad<int16_t>(Load16S, -1000));
18085 RUN(testLoad<int16_t>(Load16S, 1000000));
18086 RUN(testLoad<int16_t>(Load16S, -1000000));
18087 RUN(testLoad<int16_t>(Load16S, 1000000000));
18088 RUN(testLoad<int16_t>(Load16S, -1000000000));
18089
18090 RUN(testLoad<uint16_t>(Load16Z, 60));
18091 RUN(testLoad<uint16_t>(Load16Z, -60));
18092 RUN(testLoad<uint16_t>(Load16Z, 1000));
18093 RUN(testLoad<uint16_t>(Load16Z, -1000));
18094 RUN(testLoad<uint16_t>(Load16Z, 1000000));
18095 RUN(testLoad<uint16_t>(Load16Z, -1000000));
18096 RUN(testLoad<uint16_t>(Load16Z, 1000000000));
18097 RUN(testLoad<uint16_t>(Load16Z, -1000000000));
18098
18099 RUN(testSpillGP());
18100 RUN(testSpillFP());
18101
18102 RUN(testInt32ToDoublePartialRegisterStall());
18103 RUN(testInt32ToDoublePartialRegisterWithoutStall());
18104
18105 RUN(testCallSimple(1, 2));
18106 RUN(testCallRare(1, 2));
18107 RUN(testCallRareLive(1, 2, 3));
18108 RUN(testCallSimplePure(1, 2));
18109 RUN(testCallFunctionWithHellaArguments());
18110 RUN(testCallFunctionWithHellaArguments2());
18111 RUN(testCallFunctionWithHellaArguments3());
18112
18113 RUN(testReturnDouble(0.0));
18114 RUN(testReturnDouble(negativeZero()));
18115 RUN(testReturnDouble(42.5));
18116 RUN_UNARY(testReturnFloat, floatingPointOperands<float>());
18117
18118 RUN(testCallSimpleDouble(1, 2));
18119 RUN(testCallFunctionWithHellaDoubleArguments());
18120 RUN_BINARY(testCallSimpleFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
18121 RUN(testCallFunctionWithHellaFloatArguments());
18122
18123 RUN(testLinearScanWithCalleeOnStack());
18124
18125 RUN(testChillDiv(4, 2, 2));
18126 RUN(testChillDiv(1, 0, 0));
18127 RUN(testChillDiv(0, 0, 0));
18128 RUN(testChillDiv(1, -1, -1));
18129 RUN(testChillDiv(-2147483647 - 1, 0, 0));
18130 RUN(testChillDiv(-2147483647 - 1, 1, -2147483647 - 1));
18131 RUN(testChillDiv(-2147483647 - 1, -1, -2147483647 - 1));
18132 RUN(testChillDiv(-2147483647 - 1, 2, -1073741824));
18133 RUN(testChillDiv64(4, 2, 2));
18134 RUN(testChillDiv64(1, 0, 0));
18135 RUN(testChillDiv64(0, 0, 0));
18136 RUN(testChillDiv64(1, -1, -1));
18137 RUN(testChillDiv64(-9223372036854775807ll - 1, 0, 0));
18138 RUN(testChillDiv64(-9223372036854775807ll - 1, 1, -9223372036854775807ll - 1));
18139 RUN(testChillDiv64(-9223372036854775807ll - 1, -1, -9223372036854775807ll - 1));
18140 RUN(testChillDiv64(-9223372036854775807ll - 1, 2, -4611686018427387904));
18141 RUN(testChillDivTwice(4, 2, 6, 2, 5));
18142 RUN(testChillDivTwice(4, 0, 6, 2, 3));
18143 RUN(testChillDivTwice(4, 2, 6, 0, 2));
18144
18145 RUN_UNARY(testModArg, int64Operands());
18146 RUN_BINARY(testModArgs, int64Operands(), int64Operands());
18147 RUN_BINARY(testModImms, int64Operands(), int64Operands());
18148 RUN_UNARY(testModArg32, int32Operands());
18149 RUN_BINARY(testModArgs32, int32Operands(), int32Operands());
18150 RUN_BINARY(testModImms32, int32Operands(), int32Operands());
18151 RUN_UNARY(testChillModArg, int64Operands());
18152 RUN_BINARY(testChillModArgs, int64Operands(), int64Operands());
18153 RUN_BINARY(testChillModImms, int64Operands(), int64Operands());
18154 RUN_UNARY(testChillModArg32, int32Operands());
18155 RUN_BINARY(testChillModArgs32, int32Operands(), int32Operands());
18156 RUN_BINARY(testChillModImms32, int32Operands(), int32Operands());
18157
18158 RUN(testSwitch(0, 1));
18159 RUN(testSwitch(1, 1));
18160 RUN(testSwitch(2, 1));
18161 RUN(testSwitch(2, 2));
18162 RUN(testSwitch(10, 1));
18163 RUN(testSwitch(10, 2));
18164 RUN(testSwitch(100, 1));
18165 RUN(testSwitch(100, 100));
18166
18167 RUN(testSwitchSameCaseAsDefault());
18168
18169 RUN(testSwitchChillDiv(0, 1));
18170 RUN(testSwitchChillDiv(1, 1));
18171 RUN(testSwitchChillDiv(2, 1));
18172 RUN(testSwitchChillDiv(2, 2));
18173 RUN(testSwitchChillDiv(10, 1));
18174 RUN(testSwitchChillDiv(10, 2));
18175 RUN(testSwitchChillDiv(100, 1));
18176 RUN(testSwitchChillDiv(100, 100));
18177
18178 RUN(testSwitchTargettingSameBlock());
18179 RUN(testSwitchTargettingSameBlockFoldPathConstant());
18180
18181 RUN(testTrunc(0));
18182 RUN(testTrunc(1));
18183 RUN(testTrunc(-1));
18184 RUN(testTrunc(1000000000000ll));
18185 RUN(testTrunc(-1000000000000ll));
18186 RUN(testTruncFold(0));
18187 RUN(testTruncFold(1));
18188 RUN(testTruncFold(-1));
18189 RUN(testTruncFold(1000000000000ll));
18190 RUN(testTruncFold(-1000000000000ll));
18191
18192 RUN(testZExt32(0));
18193 RUN(testZExt32(1));
18194 RUN(testZExt32(-1));
18195 RUN(testZExt32(1000000000ll));
18196 RUN(testZExt32(-1000000000ll));
18197 RUN(testZExt32Fold(0));
18198 RUN(testZExt32Fold(1));
18199 RUN(testZExt32Fold(-1));
18200 RUN(testZExt32Fold(1000000000ll));
18201 RUN(testZExt32Fold(-1000000000ll));
18202
18203 RUN(testSExt32(0));
18204 RUN(testSExt32(1));
18205 RUN(testSExt32(-1));
18206 RUN(testSExt32(1000000000ll));
18207 RUN(testSExt32(-1000000000ll));
18208 RUN(testSExt32Fold(0));
18209 RUN(testSExt32Fold(1));
18210 RUN(testSExt32Fold(-1));
18211 RUN(testSExt32Fold(1000000000ll));
18212 RUN(testSExt32Fold(-1000000000ll));
18213
18214 RUN(testTruncZExt32(0));
18215 RUN(testTruncZExt32(1));
18216 RUN(testTruncZExt32(-1));
18217 RUN(testTruncZExt32(1000000000ll));
18218 RUN(testTruncZExt32(-1000000000ll));
18219 RUN(testTruncSExt32(0));
18220 RUN(testTruncSExt32(1));
18221 RUN(testTruncSExt32(-1));
18222 RUN(testTruncSExt32(1000000000ll));
18223 RUN(testTruncSExt32(-1000000000ll));
18224
18225 RUN(testSExt8(0));
18226 RUN(testSExt8(1));
18227 RUN(testSExt8(42));
18228 RUN(testSExt8(-1));
18229 RUN(testSExt8(0xff));
18230 RUN(testSExt8(0x100));
18231 RUN(testSExt8Fold(0));
18232 RUN(testSExt8Fold(1));
18233 RUN(testSExt8Fold(42));
18234 RUN(testSExt8Fold(-1));
18235 RUN(testSExt8Fold(0xff));
18236 RUN(testSExt8Fold(0x100));
18237 RUN(testSExt8SExt8(0));
18238 RUN(testSExt8SExt8(1));
18239 RUN(testSExt8SExt8(42));
18240 RUN(testSExt8SExt8(-1));
18241 RUN(testSExt8SExt8(0xff));
18242 RUN(testSExt8SExt8(0x100));
18243 RUN(testSExt8SExt16(0));
18244 RUN(testSExt8SExt16(1));
18245 RUN(testSExt8SExt16(42));
18246 RUN(testSExt8SExt16(-1));
18247 RUN(testSExt8SExt16(0xff));
18248 RUN(testSExt8SExt16(0x100));
18249 RUN(testSExt8SExt16(0xffff));
18250 RUN(testSExt8SExt16(0x10000));
18251 RUN(testSExt8BitAnd(0, 0));
18252 RUN(testSExt8BitAnd(1, 0));
18253 RUN(testSExt8BitAnd(42, 0));
18254 RUN(testSExt8BitAnd(-1, 0));
18255 RUN(testSExt8BitAnd(0xff, 0));
18256 RUN(testSExt8BitAnd(0x100, 0));
18257 RUN(testSExt8BitAnd(0xffff, 0));
18258 RUN(testSExt8BitAnd(0x10000, 0));
18259 RUN(testSExt8BitAnd(0, 0xf));
18260 RUN(testSExt8BitAnd(1, 0xf));
18261 RUN(testSExt8BitAnd(42, 0xf));
18262 RUN(testSExt8BitAnd(-1, 0xf));
18263 RUN(testSExt8BitAnd(0xff, 0xf));
18264 RUN(testSExt8BitAnd(0x100, 0xf));
18265 RUN(testSExt8BitAnd(0xffff, 0xf));
18266 RUN(testSExt8BitAnd(0x10000, 0xf));
18267 RUN(testSExt8BitAnd(0, 0xff));
18268 RUN(testSExt8BitAnd(1, 0xff));
18269 RUN(testSExt8BitAnd(42, 0xff));
18270 RUN(testSExt8BitAnd(-1, 0xff));
18271 RUN(testSExt8BitAnd(0xff, 0xff));
18272 RUN(testSExt8BitAnd(0x100, 0xff));
18273 RUN(testSExt8BitAnd(0xffff, 0xff));
18274 RUN(testSExt8BitAnd(0x10000, 0xff));
18275 RUN(testSExt8BitAnd(0, 0x80));
18276 RUN(testSExt8BitAnd(1, 0x80));
18277 RUN(testSExt8BitAnd(42, 0x80));
18278 RUN(testSExt8BitAnd(-1, 0x80));
18279 RUN(testSExt8BitAnd(0xff, 0x80));
18280 RUN(testSExt8BitAnd(0x100, 0x80));
18281 RUN(testSExt8BitAnd(0xffff, 0x80));
18282 RUN(testSExt8BitAnd(0x10000, 0x80));
18283 RUN(testBitAndSExt8(0, 0xf));
18284 RUN(testBitAndSExt8(1, 0xf));
18285 RUN(testBitAndSExt8(42, 0xf));
18286 RUN(testBitAndSExt8(-1, 0xf));
18287 RUN(testBitAndSExt8(0xff, 0xf));
18288 RUN(testBitAndSExt8(0x100, 0xf));
18289 RUN(testBitAndSExt8(0xffff, 0xf));
18290 RUN(testBitAndSExt8(0x10000, 0xf));
18291 RUN(testBitAndSExt8(0, 0xff));
18292 RUN(testBitAndSExt8(1, 0xff));
18293 RUN(testBitAndSExt8(42, 0xff));
18294 RUN(testBitAndSExt8(-1, 0xff));
18295 RUN(testBitAndSExt8(0xff, 0xff));
18296 RUN(testBitAndSExt8(0x100, 0xff));
18297 RUN(testBitAndSExt8(0xffff, 0xff));
18298 RUN(testBitAndSExt8(0x10000, 0xff));
18299 RUN(testBitAndSExt8(0, 0xfff));
18300 RUN(testBitAndSExt8(1, 0xfff));
18301 RUN(testBitAndSExt8(42, 0xfff));
18302 RUN(testBitAndSExt8(-1, 0xfff));
18303 RUN(testBitAndSExt8(0xff, 0xfff));
18304 RUN(testBitAndSExt8(0x100, 0xfff));
18305 RUN(testBitAndSExt8(0xffff, 0xfff));
18306 RUN(testBitAndSExt8(0x10000, 0xfff));
18307
18308 RUN(testSExt16(0));
18309 RUN(testSExt16(1));
18310 RUN(testSExt16(42));
18311 RUN(testSExt16(-1));
18312 RUN(testSExt16(0xffff));
18313 RUN(testSExt16(0x10000));
18314 RUN(testSExt16Fold(0));
18315 RUN(testSExt16Fold(1));
18316 RUN(testSExt16Fold(42));
18317 RUN(testSExt16Fold(-1));
18318 RUN(testSExt16Fold(0xffff));
18319 RUN(testSExt16Fold(0x10000));
18320 RUN(testSExt16SExt8(0));
18321 RUN(testSExt16SExt8(1));
18322 RUN(testSExt16SExt8(42));
18323 RUN(testSExt16SExt8(-1));
18324 RUN(testSExt16SExt8(0xffff));
18325 RUN(testSExt16SExt8(0x10000));
18326 RUN(testSExt16SExt16(0));
18327 RUN(testSExt16SExt16(1));
18328 RUN(testSExt16SExt16(42));
18329 RUN(testSExt16SExt16(-1));
18330 RUN(testSExt16SExt16(0xffff));
18331 RUN(testSExt16SExt16(0x10000));
18332 RUN(testSExt16SExt16(0xffffff));
18333 RUN(testSExt16SExt16(0x1000000));
18334 RUN(testSExt16BitAnd(0, 0));
18335 RUN(testSExt16BitAnd(1, 0));
18336 RUN(testSExt16BitAnd(42, 0));
18337 RUN(testSExt16BitAnd(-1, 0));
18338 RUN(testSExt16BitAnd(0xffff, 0));
18339 RUN(testSExt16BitAnd(0x10000, 0));
18340 RUN(testSExt16BitAnd(0xffffff, 0));
18341 RUN(testSExt16BitAnd(0x1000000, 0));
18342 RUN(testSExt16BitAnd(0, 0xf));
18343 RUN(testSExt16BitAnd(1, 0xf));
18344 RUN(testSExt16BitAnd(42, 0xf));
18345 RUN(testSExt16BitAnd(-1, 0xf));
18346 RUN(testSExt16BitAnd(0xffff, 0xf));
18347 RUN(testSExt16BitAnd(0x10000, 0xf));
18348 RUN(testSExt16BitAnd(0xffffff, 0xf));
18349 RUN(testSExt16BitAnd(0x1000000, 0xf));
18350 RUN(testSExt16BitAnd(0, 0xffff));
18351 RUN(testSExt16BitAnd(1, 0xffff));
18352 RUN(testSExt16BitAnd(42, 0xffff));
18353 RUN(testSExt16BitAnd(-1, 0xffff));
18354 RUN(testSExt16BitAnd(0xffff, 0xffff));
18355 RUN(testSExt16BitAnd(0x10000, 0xffff));
18356 RUN(testSExt16BitAnd(0xffffff, 0xffff));
18357 RUN(testSExt16BitAnd(0x1000000, 0xffff));
18358 RUN(testSExt16BitAnd(0, 0x8000));
18359 RUN(testSExt16BitAnd(1, 0x8000));
18360 RUN(testSExt16BitAnd(42, 0x8000));
18361 RUN(testSExt16BitAnd(-1, 0x8000));
18362 RUN(testSExt16BitAnd(0xffff, 0x8000));
18363 RUN(testSExt16BitAnd(0x10000, 0x8000));
18364 RUN(testSExt16BitAnd(0xffffff, 0x8000));
18365 RUN(testSExt16BitAnd(0x1000000, 0x8000));
18366 RUN(testBitAndSExt16(0, 0xf));
18367 RUN(testBitAndSExt16(1, 0xf));
18368 RUN(testBitAndSExt16(42, 0xf));
18369 RUN(testBitAndSExt16(-1, 0xf));
18370 RUN(testBitAndSExt16(0xffff, 0xf));
18371 RUN(testBitAndSExt16(0x10000, 0xf));
18372 RUN(testBitAndSExt16(0xffffff, 0xf));
18373 RUN(testBitAndSExt16(0x1000000, 0xf));
18374 RUN(testBitAndSExt16(0, 0xffff));
18375 RUN(testBitAndSExt16(1, 0xffff));
18376 RUN(testBitAndSExt16(42, 0xffff));
18377 RUN(testBitAndSExt16(-1, 0xffff));
18378 RUN(testBitAndSExt16(0xffff, 0xffff));
18379 RUN(testBitAndSExt16(0x10000, 0xffff));
18380 RUN(testBitAndSExt16(0xffffff, 0xffff));
18381 RUN(testBitAndSExt16(0x1000000, 0xffff));
18382 RUN(testBitAndSExt16(0, 0xfffff));
18383 RUN(testBitAndSExt16(1, 0xfffff));
18384 RUN(testBitAndSExt16(42, 0xfffff));
18385 RUN(testBitAndSExt16(-1, 0xfffff));
18386 RUN(testBitAndSExt16(0xffff, 0xfffff));
18387 RUN(testBitAndSExt16(0x10000, 0xfffff));
18388 RUN(testBitAndSExt16(0xffffff, 0xfffff));
18389 RUN(testBitAndSExt16(0x1000000, 0xfffff));
18390
18391 RUN(testSExt32BitAnd(0, 0));
18392 RUN(testSExt32BitAnd(1, 0));
18393 RUN(testSExt32BitAnd(42, 0));
18394 RUN(testSExt32BitAnd(-1, 0));
18395 RUN(testSExt32BitAnd(0x80000000, 0));
18396 RUN(testSExt32BitAnd(0, 0xf));
18397 RUN(testSExt32BitAnd(1, 0xf));
18398 RUN(testSExt32BitAnd(42, 0xf));
18399 RUN(testSExt32BitAnd(-1, 0xf));
18400 RUN(testSExt32BitAnd(0x80000000, 0xf));
18401 RUN(testSExt32BitAnd(0, 0x80000000));
18402 RUN(testSExt32BitAnd(1, 0x80000000));
18403 RUN(testSExt32BitAnd(42, 0x80000000));
18404 RUN(testSExt32BitAnd(-1, 0x80000000));
18405 RUN(testSExt32BitAnd(0x80000000, 0x80000000));
18406 RUN(testBitAndSExt32(0, 0xf));
18407 RUN(testBitAndSExt32(1, 0xf));
18408 RUN(testBitAndSExt32(42, 0xf));
18409 RUN(testBitAndSExt32(-1, 0xf));
18410 RUN(testBitAndSExt32(0xffff, 0xf));
18411 RUN(testBitAndSExt32(0x10000, 0xf));
18412 RUN(testBitAndSExt32(0xffffff, 0xf));
18413 RUN(testBitAndSExt32(0x1000000, 0xf));
18414 RUN(testBitAndSExt32(0, 0xffff00000000llu));
18415 RUN(testBitAndSExt32(1, 0xffff00000000llu));
18416 RUN(testBitAndSExt32(42, 0xffff00000000llu));
18417 RUN(testBitAndSExt32(-1, 0xffff00000000llu));
18418 RUN(testBitAndSExt32(0x80000000, 0xffff00000000llu));
18419
18420 RUN(testBasicSelect());
18421 RUN(testSelectTest());
18422 RUN(testSelectCompareDouble());
18423 RUN_BINARY(testSelectCompareFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
18424 RUN_BINARY(testSelectCompareFloatToDouble, floatingPointOperands<float>(), floatingPointOperands<float>());
18425 RUN(testSelectDouble());
18426 RUN(testSelectDoubleTest());
18427 RUN(testSelectDoubleCompareDouble());
18428 RUN_BINARY(testSelectDoubleCompareFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
18429 RUN_BINARY(testSelectFloatCompareFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
18430 RUN(testSelectDoubleCompareDoubleWithAliasing());
18431 RUN(testSelectFloatCompareFloatWithAliasing());
18432 RUN(testSelectFold(42));
18433 RUN(testSelectFold(43));
18434 RUN(testSelectInvert());
18435 RUN(testCheckSelect());
18436 RUN(testCheckSelectCheckSelect());
18437 RUN(testCheckSelectAndCSE());
18438 RUN_BINARY(testPowDoubleByIntegerLoop, floatingPointOperands<double>(), int64Operands());
18439
18440 RUN(testTruncOrHigh());
18441 RUN(testTruncOrLow());
18442 RUN(testBitAndOrHigh());
18443 RUN(testBitAndOrLow());
18444
18445 RUN(testBranch64Equal(0, 0));
18446 RUN(testBranch64Equal(1, 1));
18447 RUN(testBranch64Equal(-1, -1));
18448 RUN(testBranch64Equal(1, -1));
18449 RUN(testBranch64Equal(-1, 1));
18450 RUN(testBranch64EqualImm(0, 0));
18451 RUN(testBranch64EqualImm(1, 1));
18452 RUN(testBranch64EqualImm(-1, -1));
18453 RUN(testBranch64EqualImm(1, -1));
18454 RUN(testBranch64EqualImm(-1, 1));
18455 RUN(testBranch64EqualMem(0, 0));
18456 RUN(testBranch64EqualMem(1, 1));
18457 RUN(testBranch64EqualMem(-1, -1));
18458 RUN(testBranch64EqualMem(1, -1));
18459 RUN(testBranch64EqualMem(-1, 1));
18460 RUN(testBranch64EqualMemImm(0, 0));
18461 RUN(testBranch64EqualMemImm(1, 1));
18462 RUN(testBranch64EqualMemImm(-1, -1));
18463 RUN(testBranch64EqualMemImm(1, -1));
18464 RUN(testBranch64EqualMemImm(-1, 1));
18465
18466 RUN(testStore8Load8Z(0));
18467 RUN(testStore8Load8Z(123));
18468 RUN(testStore8Load8Z(12345));
18469 RUN(testStore8Load8Z(-123));
18470
18471 RUN(testStore16Load16Z(0));
18472 RUN(testStore16Load16Z(123));
18473 RUN(testStore16Load16Z(12345));
18474 RUN(testStore16Load16Z(12345678));
18475 RUN(testStore16Load16Z(-123));
18476
18477 RUN(testSShrShl32(42, 24, 24));
18478 RUN(testSShrShl32(-42, 24, 24));
18479 RUN(testSShrShl32(4200, 24, 24));
18480 RUN(testSShrShl32(-4200, 24, 24));
18481 RUN(testSShrShl32(4200000, 24, 24));
18482 RUN(testSShrShl32(-4200000, 24, 24));
18483
18484 RUN(testSShrShl32(42, 16, 16));
18485 RUN(testSShrShl32(-42, 16, 16));
18486 RUN(testSShrShl32(4200, 16, 16));
18487 RUN(testSShrShl32(-4200, 16, 16));
18488 RUN(testSShrShl32(4200000, 16, 16));
18489 RUN(testSShrShl32(-4200000, 16, 16));
18490
18491 RUN(testSShrShl32(42, 8, 8));
18492 RUN(testSShrShl32(-42, 8, 8));
18493 RUN(testSShrShl32(4200, 8, 8));
18494 RUN(testSShrShl32(-4200, 8, 8));
18495 RUN(testSShrShl32(4200000, 8, 8));
18496 RUN(testSShrShl32(-4200000, 8, 8));
18497 RUN(testSShrShl32(420000000, 8, 8));
18498 RUN(testSShrShl32(-420000000, 8, 8));
18499
18500 RUN(testSShrShl64(42, 56, 56));
18501 RUN(testSShrShl64(-42, 56, 56));
18502 RUN(testSShrShl64(4200, 56, 56));
18503 RUN(testSShrShl64(-4200, 56, 56));
18504 RUN(testSShrShl64(4200000, 56, 56));
18505 RUN(testSShrShl64(-4200000, 56, 56));
18506 RUN(testSShrShl64(420000000, 56, 56));
18507 RUN(testSShrShl64(-420000000, 56, 56));
18508 RUN(testSShrShl64(42000000000, 56, 56));
18509 RUN(testSShrShl64(-42000000000, 56, 56));
18510
18511 RUN(testSShrShl64(42, 48, 48));
18512 RUN(testSShrShl64(-42, 48, 48));
18513 RUN(testSShrShl64(4200, 48, 48));
18514 RUN(testSShrShl64(-4200, 48, 48));
18515 RUN(testSShrShl64(4200000, 48, 48));
18516 RUN(testSShrShl64(-4200000, 48, 48));
18517 RUN(testSShrShl64(420000000, 48, 48));
18518 RUN(testSShrShl64(-420000000, 48, 48));
18519 RUN(testSShrShl64(42000000000, 48, 48));
18520 RUN(testSShrShl64(-42000000000, 48, 48));
18521
18522 RUN(testSShrShl64(42, 32, 32));
18523 RUN(testSShrShl64(-42, 32, 32));
18524 RUN(testSShrShl64(4200, 32, 32));
18525 RUN(testSShrShl64(-4200, 32, 32));
18526 RUN(testSShrShl64(4200000, 32, 32));
18527 RUN(testSShrShl64(-4200000, 32, 32));
18528 RUN(testSShrShl64(420000000, 32, 32));
18529 RUN(testSShrShl64(-420000000, 32, 32));
18530 RUN(testSShrShl64(42000000000, 32, 32));
18531 RUN(testSShrShl64(-42000000000, 32, 32));
18532
18533 RUN(testSShrShl64(42, 24, 24));
18534 RUN(testSShrShl64(-42, 24, 24));
18535 RUN(testSShrShl64(4200, 24, 24));
18536 RUN(testSShrShl64(-4200, 24, 24));
18537 RUN(testSShrShl64(4200000, 24, 24));
18538 RUN(testSShrShl64(-4200000, 24, 24));
18539 RUN(testSShrShl64(420000000, 24, 24));
18540 RUN(testSShrShl64(-420000000, 24, 24));
18541 RUN(testSShrShl64(42000000000, 24, 24));
18542 RUN(testSShrShl64(-42000000000, 24, 24));
18543
18544 RUN(testSShrShl64(42, 16, 16));
18545 RUN(testSShrShl64(-42, 16, 16));
18546 RUN(testSShrShl64(4200, 16, 16));
18547 RUN(testSShrShl64(-4200, 16, 16));
18548 RUN(testSShrShl64(4200000, 16, 16));
18549 RUN(testSShrShl64(-4200000, 16, 16));
18550 RUN(testSShrShl64(420000000, 16, 16));
18551 RUN(testSShrShl64(-420000000, 16, 16));
18552 RUN(testSShrShl64(42000000000, 16, 16));
18553 RUN(testSShrShl64(-42000000000, 16, 16));
18554
18555 RUN(testSShrShl64(42, 8, 8));
18556 RUN(testSShrShl64(-42, 8, 8));
18557 RUN(testSShrShl64(4200, 8, 8));
18558 RUN(testSShrShl64(-4200, 8, 8));
18559 RUN(testSShrShl64(4200000, 8, 8));
18560 RUN(testSShrShl64(-4200000, 8, 8));
18561 RUN(testSShrShl64(420000000, 8, 8));
18562 RUN(testSShrShl64(-420000000, 8, 8));
18563 RUN(testSShrShl64(42000000000, 8, 8));
18564 RUN(testSShrShl64(-42000000000, 8, 8));
18565
18566 RUN(testCheckMul64SShr());
18567
18568 RUN_BINARY(testRotR, int32Operands(), int32Operands());
18569 RUN_BINARY(testRotR, int64Operands(), int32Operands());
18570 RUN_BINARY(testRotL, int32Operands(), int32Operands());
18571 RUN_BINARY(testRotL, int64Operands(), int32Operands());
18572
18573 RUN_BINARY(testRotRWithImmShift, int32Operands(), int32Operands());
18574 RUN_BINARY(testRotRWithImmShift, int64Operands(), int32Operands());
18575 RUN_BINARY(testRotLWithImmShift, int32Operands(), int32Operands());
18576 RUN_BINARY(testRotLWithImmShift, int64Operands(), int32Operands());
18577
18578 RUN(testComputeDivisionMagic<int32_t>(2, -2147483647, 0));
18579 RUN(testTrivialInfiniteLoop());
18580 RUN(testFoldPathEqual());
18581
18582 RUN(testRShiftSelf32());
18583 RUN(testURShiftSelf32());
18584 RUN(testLShiftSelf32());
18585 RUN(testRShiftSelf64());
18586 RUN(testURShiftSelf64());
18587 RUN(testLShiftSelf64());
18588
18589 RUN(testPatchpointDoubleRegs());
18590 RUN(testSpillDefSmallerThanUse());
18591 RUN(testSpillUseLargerThanDef());
18592 RUN(testLateRegister());
18593 RUN(testInterpreter());
18594 RUN(testReduceStrengthCheckBottomUseInAnotherBlock());
18595 RUN(testResetReachabilityDanglingReference());
18596
18597 RUN(testEntrySwitchSimple());
18598 RUN(testEntrySwitchNoEntrySwitch());
18599 RUN(testEntrySwitchWithCommonPaths());
18600 RUN(testEntrySwitchWithCommonPathsAndNonTrivialEntrypoint());
18601 RUN(testEntrySwitchLoop());
18602
18603 RUN(testSomeEarlyRegister());
18604 RUN(testPatchpointTerminalReturnValue(true));
18605 RUN(testPatchpointTerminalReturnValue(false));
18606 RUN(testTerminalPatchpointThatNeedsToBeSpilled());
18607
18608 RUN(testMemoryFence());
18609 RUN(testStoreFence());
18610 RUN(testLoadFence());
18611 RUN(testTrappingLoad());
18612 RUN(testTrappingStore());
18613 RUN(testTrappingLoadAddStore());
18614 RUN(testTrappingLoadDCE());
18615 RUN(testTrappingStoreElimination());
18616 RUN(testMoveConstants());
18617 RUN(testPCOriginMapDoesntInsertNops());
18618 RUN(testPinRegisters());
18619 RUN(testReduceStrengthReassociation(true));
18620 RUN(testReduceStrengthReassociation(false));
18621 RUN(testAddShl32());
18622 RUN(testAddShl64());
18623 RUN(testAddShl65());
18624 RUN(testLoadBaseIndexShift2());
18625 RUN(testLoadBaseIndexShift32());
18626 RUN(testOptimizeMaterialization());
18627 RUN(testLICMPure());
18628 RUN(testLICMPureSideExits());
18629 RUN(testLICMPureWritesPinned());
18630 RUN(testLICMPureWrites());
18631 RUN(testLICMReadsLocalState());
18632 RUN(testLICMReadsPinned());
18633 RUN(testLICMReads());
18634 RUN(testLICMPureNotBackwardsDominant());
18635 RUN(testLICMPureFoiledByChild());
18636 RUN(testLICMPureNotBackwardsDominantFoiledByChild());
18637 RUN(testLICMExitsSideways());
18638 RUN(testLICMWritesLocalState());
18639 RUN(testLICMWrites());
18640 RUN(testLICMWritesPinned());
18641 RUN(testLICMFence());
18642 RUN(testLICMControlDependent());
18643 RUN(testLICMControlDependentNotBackwardsDominant());
18644 RUN(testLICMControlDependentSideExits());
18645 RUN(testLICMReadsPinnedWritesPinned());
18646 RUN(testLICMReadsWritesDifferentHeaps());
18647 RUN(testLICMReadsWritesOverlappingHeaps());
18648 RUN(testLICMDefaultCall());
18649
18650 RUN(testAtomicWeakCAS<int8_t>());
18651 RUN(testAtomicWeakCAS<int16_t>());
18652 RUN(testAtomicWeakCAS<int32_t>());
18653 RUN(testAtomicWeakCAS<int64_t>());
18654 RUN(testAtomicStrongCAS<int8_t>());
18655 RUN(testAtomicStrongCAS<int16_t>());
18656 RUN(testAtomicStrongCAS<int32_t>());
18657 RUN(testAtomicStrongCAS<int64_t>());
18658 RUN(testAtomicXchg<int8_t>(AtomicXchgAdd));
18659 RUN(testAtomicXchg<int16_t>(AtomicXchgAdd));
18660 RUN(testAtomicXchg<int32_t>(AtomicXchgAdd));
18661 RUN(testAtomicXchg<int64_t>(AtomicXchgAdd));
18662 RUN(testAtomicXchg<int8_t>(AtomicXchgAnd));
18663 RUN(testAtomicXchg<int16_t>(AtomicXchgAnd));
18664 RUN(testAtomicXchg<int32_t>(AtomicXchgAnd));
18665 RUN(testAtomicXchg<int64_t>(AtomicXchgAnd));
18666 RUN(testAtomicXchg<int8_t>(AtomicXchgOr));
18667 RUN(testAtomicXchg<int16_t>(AtomicXchgOr));
18668 RUN(testAtomicXchg<int32_t>(AtomicXchgOr));
18669 RUN(testAtomicXchg<int64_t>(AtomicXchgOr));
18670 RUN(testAtomicXchg<int8_t>(AtomicXchgSub));
18671 RUN(testAtomicXchg<int16_t>(AtomicXchgSub));
18672 RUN(testAtomicXchg<int32_t>(AtomicXchgSub));
18673 RUN(testAtomicXchg<int64_t>(AtomicXchgSub));
18674 RUN(testAtomicXchg<int8_t>(AtomicXchgXor));
18675 RUN(testAtomicXchg<int16_t>(AtomicXchgXor));
18676 RUN(testAtomicXchg<int32_t>(AtomicXchgXor));
18677 RUN(testAtomicXchg<int64_t>(AtomicXchgXor));
18678 RUN(testAtomicXchg<int8_t>(AtomicXchg));
18679 RUN(testAtomicXchg<int16_t>(AtomicXchg));
18680 RUN(testAtomicXchg<int32_t>(AtomicXchg));
18681 RUN(testAtomicXchg<int64_t>(AtomicXchg));
18682 RUN(testDepend32());
18683 RUN(testDepend64());
18684
18685 RUN(testWasmBoundsCheck(0));
18686 RUN(testWasmBoundsCheck(100));
18687 RUN(testWasmBoundsCheck(10000));
18688 RUN(testWasmBoundsCheck(std::numeric_limits<unsigned>::max() - 5));
18689
18690 RUN(testWasmAddress());
18691
18692 RUN(testFastTLSLoad());
18693 RUN(testFastTLSStore());
18694
18695 RUN(testDoubleLiteralComparison(bitwise_cast<double>(0x8000000000000001ull), bitwise_cast<double>(0x0000000000000000ull)));
18696 RUN(testDoubleLiteralComparison(bitwise_cast<double>(0x0000000000000000ull), bitwise_cast<double>(0x8000000000000001ull)));
18697 RUN(testDoubleLiteralComparison(125.3144446948241, 125.3144446948242));
18698 RUN(testDoubleLiteralComparison(125.3144446948242, 125.3144446948241));
18699
18700 RUN(testFloatEqualOrUnorderedFolding());
18701 RUN(testFloatEqualOrUnorderedFoldingNaN());
18702 RUN(testFloatEqualOrUnorderedDontFold());
18703
18704 RUN(testShuffleDoesntTrashCalleeSaves());
18705 RUN(testDemotePatchpointTerminal());
18706
18707 RUN(testLoopWithMultipleHeaderEdges());
18708
18709 RUN(testInfiniteLoopDoesntCauseBadHoisting());
18710
18711 if (isX86()) {
18712 RUN(testBranchBitAndImmFusion(Identity, Int64, 1, Air::BranchTest32, Air::Arg::Tmp));
18713 RUN(testBranchBitAndImmFusion(Identity, Int64, 0xff, Air::BranchTest32, Air::Arg::Tmp));
18714 RUN(testBranchBitAndImmFusion(Trunc, Int32, 1, Air::BranchTest32, Air::Arg::Tmp));
18715 RUN(testBranchBitAndImmFusion(Trunc, Int32, 0xff, Air::BranchTest32, Air::Arg::Tmp));
18716 RUN(testBranchBitAndImmFusion(Load8S, Int32, 1, Air::BranchTest8, Air::Arg::Addr));
18717 RUN(testBranchBitAndImmFusion(Load8Z, Int32, 1, Air::BranchTest8, Air::Arg::Addr));
18718 RUN(testBranchBitAndImmFusion(Load, Int32, 1, Air::BranchTest32, Air::Arg::Addr));
18719 RUN(testBranchBitAndImmFusion(Load, Int64, 1, Air::BranchTest32, Air::Arg::Addr));
18720 RUN(testX86LeaAddAddShlLeft());
18721 RUN(testX86LeaAddAddShlRight());
18722 RUN(testX86LeaAddAdd());
18723 RUN(testX86LeaAddShlRight());
18724 RUN(testX86LeaAddShlLeftScale1());
18725 RUN(testX86LeaAddShlLeftScale2());
18726 RUN(testX86LeaAddShlLeftScale4());
18727 RUN(testX86LeaAddShlLeftScale8());
18728 }
18729
18730 if (isARM64()) {
18731 RUN(testTernarySubInstructionSelection(Identity, Int64, Air::Sub64));
18732 RUN(testTernarySubInstructionSelection(Trunc, Int32, Air::Sub32));
18733 }
18734
18735 RUN(testReportUsedRegistersLateUseFollowedByEarlyDefDoesNotMarkUseAsDead());
18736
18737 if (tasks.isEmpty())
18738 usage();
18739
18740 Lock lock;
18741
18742 Vector<Ref<Thread>> threads;
18743 for (unsigned i = filter ? 1 : WTF::numberOfProcessorCores(); i--;) {
18744 threads.append(
18745 Thread::create(
18746 "testb3 thread",
18747 [&] () {
18748 for (;;) {
18749 RefPtr<SharedTask<void()>> task;
18750 {
18751 LockHolder locker(lock);
18752 if (tasks.isEmpty())
18753 return;
18754 task = tasks.takeFirst();
18755 }
18756
18757 task->run();
18758 }
18759 }));
18760 }
18761
18762 for (auto& thread : threads)
18763 thread->waitForCompletion();
18764 crashLock.lock();
18765 crashLock.unlock();
18766}
18767
18768} // anonymous namespace
18769
18770#else // ENABLE(B3_JIT)
18771
18772static void run(const char*)
18773{
18774 dataLog("B3 JIT is not enabled.\n");
18775}
18776
18777#endif // ENABLE(B3_JIT)
18778
18779int main(int argc, char** argv)
18780{
18781 const char* filter = nullptr;
18782 switch (argc) {
18783 case 1:
18784 break;
18785 case 2:
18786 filter = argv[1];
18787 break;
18788 default:
18789 usage();
18790 break;
18791 }
18792
18793 JSC::initializeThreading();
18794
18795 for (unsigned i = 0; i <= 2; ++i) {
18796 JSC::Options::defaultB3OptLevel() = i;
18797 run(filter);
18798 }
18799
18800 return 0;
18801}
18802
18803#if OS(WINDOWS)
18804extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
18805{
18806 return main(argc, const_cast<char**>(argv));
18807}
18808#endif
18809