[CMake] Properly test if compiler supports compiler flags
[WebKit-https.git] / Source / JavaScriptCore / b3 / testb3.cpp
1 /*
2  * Copyright (C) 2015-2017 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 "B3CCallValue.h"
36 #include "B3Compilation.h"
37 #include "B3Compile.h"
38 #include "B3ComputeDivisionMagic.h"
39 #include "B3Const32Value.h"
40 #include "B3ConstPtrValue.h"
41 #include "B3Effects.h"
42 #include "B3FenceValue.h"
43 #include "B3Generate.h"
44 #include "B3LowerToAir.h"
45 #include "B3MathExtras.h"
46 #include "B3MemoryValue.h"
47 #include "B3MoveConstants.h"
48 #include "B3NativeTraits.h"
49 #include "B3Procedure.h"
50 #include "B3ReduceStrength.h"
51 #include "B3SlotBaseValue.h"
52 #include "B3StackSlot.h"
53 #include "B3StackmapGenerationParams.h"
54 #include "B3SwitchValue.h"
55 #include "B3UpsilonValue.h"
56 #include "B3UseCounts.h"
57 #include "B3Validate.h"
58 #include "B3ValueInlines.h"
59 #include "B3VariableValue.h"
60 #include "B3WasmAddressValue.h"
61 #include "B3WasmBoundsCheckValue.h"
62 #include "CCallHelpers.h"
63 #include "FPRInfo.h"
64 #include "GPRInfo.h"
65 #include "InitializeThreading.h"
66 #include "JSCInlines.h"
67 #include "LinkBuffer.h"
68 #include "PureNaN.h"
69 #include <cmath>
70 #include <list>
71 #include <string>
72 #include <wtf/FastTLS.h>
73 #include <wtf/ListDump.h>
74 #include <wtf/Lock.h>
75 #include <wtf/NumberOfCores.h>
76 #include <wtf/Threading.h>
77
78 // We don't have a NO_RETURN_DUE_TO_EXIT, nor should we. That's ridiculous.
79 static bool hiddenTruthBecauseNoReturnIsStupid() { return true; }
80
81 static void usage()
82 {
83     dataLog("Usage: testb3 [<filter>]\n");
84     if (hiddenTruthBecauseNoReturnIsStupid())
85         exit(1);
86 }
87
88 #if ENABLE(B3_JIT)
89
90 using namespace JSC;
91 using namespace JSC::B3;
92
93 namespace {
94
95 bool shouldBeVerbose()
96 {
97     return shouldDumpIR(B3Mode);
98 }
99
100 StaticLock crashLock;
101
102 // Nothing fancy for now; we just use the existing WTF assertion machinery.
103 #define CHECK(x) do {                                                   \
104         if (!!(x))                                                      \
105             break;                                                      \
106         crashLock.lock();                                               \
107         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #x); \
108         CRASH();                                                        \
109     } while (false)
110
111 #define CHECK_EQ(x, y) do { \
112         auto __x = (x); \
113         auto __y = (y); \
114         if (__x == __y) \
115             break; \
116         crashLock.lock(); \
117         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(#x " == " #y, " (" #x " == ", __x, ", " #y " == ", __y, ")").data()); \
118         CRASH(); \
119     } while (false)
120
121 std::unique_ptr<Compilation> compileProc(Procedure& procedure, unsigned optLevel = defaultOptLevel())
122 {
123     procedure.setOptLevel(optLevel);
124     return std::make_unique<Compilation>(B3::compile(procedure));
125 }
126
127 template<typename T, typename... Arguments>
128 T invoke(MacroAssemblerCodePtr ptr, Arguments... arguments)
129 {
130     T (*function)(Arguments...) = bitwise_cast<T(*)(Arguments...)>(ptr.executableAddress());
131     return function(arguments...);
132 }
133
134 template<typename T, typename... Arguments>
135 T invoke(const Compilation& code, Arguments... arguments)
136 {
137     return invoke<T>(code.code(), arguments...);
138 }
139
140 template<typename T, typename... Arguments>
141 T compileAndRun(Procedure& procedure, Arguments... arguments)
142 {
143     return invoke<T>(*compileProc(procedure), arguments...);
144 }
145
146 void lowerToAirForTesting(Procedure& proc)
147 {
148     proc.resetReachability();
149     
150     if (shouldBeVerbose())
151         dataLog("B3 before lowering:\n", proc);
152     
153     validate(proc);
154     lowerToAir(proc);
155     
156     if (shouldBeVerbose())
157         dataLog("Air after lowering:\n", proc.code());
158     
159     Air::validate(proc.code());
160 }
161
162 template<typename Func>
163 void checkDisassembly(Compilation& compilation, const Func& func, CString failText)
164 {
165     CString disassembly = compilation.disassembly();
166     if (func(disassembly.data()))
167         return;
168     
169     crashLock.lock();
170     dataLog("Bad lowering!  ", failText, "\n");
171     dataLog(disassembly);
172     CRASH();
173 }
174
175 void checkUsesInstruction(Compilation& compilation, const char* text)
176 {
177     checkDisassembly(
178         compilation,
179         [&] (const char* disassembly) -> bool {
180             return strstr(disassembly, text);
181         },
182         toCString("Expected to find ", text, " but didnt!"));
183 }
184
185 void checkDoesNotUseInstruction(Compilation& compilation, const char* text)
186 {
187     checkDisassembly(
188         compilation,
189         [&] (const char* disassembly) -> bool {
190             return !strstr(disassembly, text);
191         },
192         toCString("Did not expected to find ", text, " but it's there!"));
193 }
194
195 template<typename Type>
196 struct Operand {
197     const char* name;
198     Type value;
199 };
200
201 typedef Operand<int64_t> Int64Operand;
202 typedef Operand<int32_t> Int32Operand;
203
204 template<typename FloatType>
205 void populateWithInterestingValues(Vector<Operand<FloatType>>& operands)
206 {
207     operands.append({ "0.", static_cast<FloatType>(0.) });
208     operands.append({ "-0.", static_cast<FloatType>(-0.) });
209     operands.append({ "0.4", static_cast<FloatType>(0.5) });
210     operands.append({ "-0.4", static_cast<FloatType>(-0.5) });
211     operands.append({ "0.5", static_cast<FloatType>(0.5) });
212     operands.append({ "-0.5", static_cast<FloatType>(-0.5) });
213     operands.append({ "0.6", static_cast<FloatType>(0.5) });
214     operands.append({ "-0.6", static_cast<FloatType>(-0.5) });
215     operands.append({ "1.", static_cast<FloatType>(1.) });
216     operands.append({ "-1.", static_cast<FloatType>(-1.) });
217     operands.append({ "2.", static_cast<FloatType>(2.) });
218     operands.append({ "-2.", static_cast<FloatType>(-2.) });
219     operands.append({ "M_PI", static_cast<FloatType>(M_PI) });
220     operands.append({ "-M_PI", static_cast<FloatType>(-M_PI) });
221     operands.append({ "min", std::numeric_limits<FloatType>::min() });
222     operands.append({ "max", std::numeric_limits<FloatType>::max() });
223     operands.append({ "lowest", std::numeric_limits<FloatType>::lowest() });
224     operands.append({ "epsilon", std::numeric_limits<FloatType>::epsilon() });
225     operands.append({ "infiniti", std::numeric_limits<FloatType>::infinity() });
226     operands.append({ "-infiniti", - std::numeric_limits<FloatType>::infinity() });
227     operands.append({ "PNaN", static_cast<FloatType>(PNaN) });
228 }
229
230 template<typename FloatType>
231 Vector<Operand<FloatType>> floatingPointOperands()
232 {
233     Vector<Operand<FloatType>> operands;
234     populateWithInterestingValues(operands);
235     return operands;
236 };
237
238 static Vector<Int64Operand> int64Operands()
239 {
240     Vector<Int64Operand> operands;
241     operands.append({ "0", 0 });
242     operands.append({ "1", 1 });
243     operands.append({ "-1", -1 });
244     operands.append({ "42", 42 });
245     operands.append({ "-42", -42 });
246     operands.append({ "int64-max", std::numeric_limits<int64_t>::max() });
247     operands.append({ "int64-min", std::numeric_limits<int64_t>::min() });
248     operands.append({ "int32-max", std::numeric_limits<int32_t>::max() });
249     operands.append({ "int32-min", std::numeric_limits<int32_t>::min() });
250
251     return operands;
252 }
253
254 static Vector<Int32Operand> int32Operands()
255 {
256     Vector<Int32Operand> operands({
257         { "0", 0 },
258         { "1", 1 },
259         { "-1", -1 },
260         { "42", 42 },
261         { "-42", -42 },
262         { "int32-max", std::numeric_limits<int32_t>::max() },
263         { "int32-min", std::numeric_limits<int32_t>::min() }
264     });
265     return operands;
266 }
267
268 void add32(CCallHelpers& jit, GPRReg src1, GPRReg src2, GPRReg dest)
269 {
270     if (src2 == dest)
271         jit.add32(src1, dest);
272     else {
273         jit.move(src1, dest);
274         jit.add32(src2, dest);
275     }
276 }
277
278 void test42()
279 {
280     Procedure proc;
281     BasicBlock* root = proc.addBlock();
282     Value* const42 = root->appendNew<Const32Value>(proc, Origin(), 42);
283     root->appendNewControlValue(proc, Return, Origin(), const42);
284
285     CHECK(compileAndRun<int>(proc) == 42);
286 }
287
288 void testLoad42()
289 {
290     Procedure proc;
291     BasicBlock* root = proc.addBlock();
292     int x = 42;
293     root->appendNewControlValue(
294         proc, Return, Origin(),
295         root->appendNew<MemoryValue>(
296             proc, Load, Int32, Origin(),
297             root->appendNew<ConstPtrValue>(proc, Origin(), &x)));
298
299     CHECK(compileAndRun<int>(proc) == 42);
300 }
301
302 void testLoadAcq42()
303 {
304     Procedure proc;
305     BasicBlock* root = proc.addBlock();
306     int x = 42;
307     root->appendNewControlValue(
308         proc, Return, Origin(),
309         root->appendNew<MemoryValue>(
310             proc, Load, Int32, Origin(),
311             root->appendNew<ConstPtrValue>(proc, Origin(), &x),
312             0, HeapRange(42), HeapRange(42)));
313
314     auto code = compileProc(proc);
315     if (isARM64())
316         checkUsesInstruction(*code, "lda");
317     CHECK(invoke<int>(*code) == 42);
318 }
319
320 void testLoadWithOffsetImpl(int32_t offset64, int32_t offset32)
321 {
322     {
323         Procedure proc;
324         BasicBlock* root = proc.addBlock();
325         int64_t x = -42;
326         Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
327         root->appendNewControlValue(
328             proc, Return, Origin(),
329             root->appendNew<MemoryValue>(
330                 proc, Load, Int64, Origin(),
331                 base,
332                 offset64));
333
334         char* address = reinterpret_cast<char*>(&x) - offset64;
335         CHECK(compileAndRun<int64_t>(proc, address) == -42);
336     }
337     {
338         Procedure proc;
339         BasicBlock* root = proc.addBlock();
340         int32_t x = -42;
341         Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
342         root->appendNewControlValue(
343             proc, Return, Origin(),
344             root->appendNew<MemoryValue>(
345                 proc, Load, Int32, Origin(),
346                 base,
347                 offset32));
348
349         char* address = reinterpret_cast<char*>(&x) - offset32;
350         CHECK(compileAndRun<int32_t>(proc, address) == -42);
351     }
352 }
353
354 void testLoadOffsetImm9Max()
355 {
356     testLoadWithOffsetImpl(255, 255);
357 }
358
359 void testLoadOffsetImm9MaxPlusOne()
360 {
361     testLoadWithOffsetImpl(256, 256);
362 }
363
364 void testLoadOffsetImm9MaxPlusTwo()
365 {
366     testLoadWithOffsetImpl(257, 257);
367 }
368
369 void testLoadOffsetImm9Min()
370 {
371     testLoadWithOffsetImpl(-256, -256);
372 }
373
374 void testLoadOffsetImm9MinMinusOne()
375 {
376     testLoadWithOffsetImpl(-257, -257);
377 }
378
379 void testLoadOffsetScaledUnsignedImm12Max()
380 {
381     testLoadWithOffsetImpl(32760, 16380);
382 }
383
384 void testLoadOffsetScaledUnsignedOverImm12Max()
385 {
386     testLoadWithOffsetImpl(32760, 32760);
387     testLoadWithOffsetImpl(32761, 16381);
388     testLoadWithOffsetImpl(32768, 16384);
389 }
390
391 void testArg(int argument)
392 {
393     Procedure proc;
394     BasicBlock* root = proc.addBlock();
395     root->appendNewControlValue(
396         proc, Return, Origin(),
397         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
398
399     CHECK(compileAndRun<int>(proc, argument) == argument);
400 }
401
402 void testReturnConst64(int64_t value)
403 {
404     Procedure proc;
405     BasicBlock* root = proc.addBlock();
406     root->appendNewControlValue(
407         proc, Return, Origin(),
408         root->appendNew<Const64Value>(proc, Origin(), value));
409
410     CHECK(compileAndRun<int64_t>(proc) == value);
411 }
412
413 void testReturnVoid()
414 {
415     Procedure proc;
416     BasicBlock* root = proc.addBlock();
417     root->appendNewControlValue(proc, Return, Origin());
418     compileAndRun<void>(proc);
419 }
420
421 void testAddArg(int a)
422 {
423     Procedure proc;
424     BasicBlock* root = proc.addBlock();
425     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
426     root->appendNewControlValue(
427         proc, Return, Origin(),
428         root->appendNew<Value>(proc, Add, Origin(), value, value));
429
430     CHECK(compileAndRun<int>(proc, a) == a + a);
431 }
432
433 void testAddArgs(int a, int b)
434 {
435     Procedure proc;
436     BasicBlock* root = proc.addBlock();
437     root->appendNewControlValue(
438         proc, Return, Origin(),
439         root->appendNew<Value>(
440             proc, Add, Origin(),
441             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
442             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
443
444     CHECK(compileAndRun<int>(proc, a, b) == a + b);
445 }
446
447 void testAddArgImm(int a, int b)
448 {
449     Procedure proc;
450     BasicBlock* root = proc.addBlock();
451     root->appendNewControlValue(
452         proc, Return, Origin(),
453         root->appendNew<Value>(
454             proc, Add, Origin(),
455             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
456             root->appendNew<Const64Value>(proc, Origin(), b)));
457
458     CHECK(compileAndRun<int>(proc, a) == a + b);
459 }
460
461 void testAddImmArg(int a, int b)
462 {
463     Procedure proc;
464     BasicBlock* root = proc.addBlock();
465     root->appendNewControlValue(
466         proc, Return, Origin(),
467         root->appendNew<Value>(
468             proc, Add, Origin(),
469             root->appendNew<Const64Value>(proc, Origin(), a),
470             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
471
472     CHECK(compileAndRun<int>(proc, b) == a + b);
473 }
474
475 void testAddArgMem(int64_t a, int64_t b)
476 {
477     Procedure proc;
478     BasicBlock* root = proc.addBlock();
479     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
480     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
481     Value* result = root->appendNew<Value>(proc, Add, Origin(),
482         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
483         load);
484     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
485     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
486
487     int64_t inputOutput = b;
488     CHECK(!compileAndRun<int64_t>(proc, a, &inputOutput));
489     CHECK(inputOutput == a + b);
490 }
491
492 void testAddMemArg(int64_t a, int64_t b)
493 {
494     Procedure proc;
495     BasicBlock* root = proc.addBlock();
496     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
497     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
498     Value* result = root->appendNew<Value>(proc, Add, Origin(),
499         load,
500         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
501     root->appendNewControlValue(proc, Return, Origin(), result);
502
503     CHECK(compileAndRun<int64_t>(proc, &a, b) == a + b);
504 }
505
506 void testAddImmMem(int64_t a, int64_t b)
507 {
508     Procedure proc;
509     BasicBlock* root = proc.addBlock();
510     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
511     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
512     Value* result = root->appendNew<Value>(proc, Add, Origin(),
513         root->appendNew<Const64Value>(proc, Origin(), a),
514         load);
515     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
516     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
517
518     int64_t inputOutput = b;
519     CHECK(!compileAndRun<int>(proc, &inputOutput));
520     CHECK(inputOutput == a + b);
521 }
522
523 void testAddArg32(int a)
524 {
525     Procedure proc;
526     BasicBlock* root = proc.addBlock();
527     Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
528         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
529     root->appendNewControlValue(
530         proc, Return, Origin(),
531         root->appendNew<Value>(proc, Add, Origin(), value, value));
532
533     CHECK(compileAndRun<int>(proc, a) == a + a);
534 }
535
536 void testAddArgs32(int a, int b)
537 {
538     Procedure proc;
539     BasicBlock* root = proc.addBlock();
540     root->appendNewControlValue(
541         proc, Return, Origin(),
542         root->appendNew<Value>(
543             proc, Add, Origin(),
544             root->appendNew<Value>(
545                 proc, Trunc, Origin(),
546                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
547             root->appendNew<Value>(
548                 proc, Trunc, Origin(),
549                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
550
551     CHECK(compileAndRun<int>(proc, a, b) == a + b);
552 }
553
554 void testAddArgMem32(int32_t a, int32_t b)
555 {
556     Procedure proc;
557     BasicBlock* root = proc.addBlock();
558     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
559     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
560     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
561         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
562     Value* result = root->appendNew<Value>(proc, Add, Origin(), argument, load);
563     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
564     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
565
566     int32_t inputOutput = b;
567     CHECK(!compileAndRun<int32_t>(proc, a, &inputOutput));
568     CHECK(inputOutput == a + b);
569 }
570
571 void testAddMemArg32(int32_t a, int32_t b)
572 {
573     Procedure proc;
574     BasicBlock* root = proc.addBlock();
575     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
576     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
577     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
578         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
579     Value* result = root->appendNew<Value>(proc, Add, Origin(), load, argument);
580     root->appendNewControlValue(proc, Return, Origin(), result);
581
582     CHECK(compileAndRun<int32_t>(proc, &a, b) == a + b);
583 }
584
585 void testAddImmMem32(int32_t a, int32_t b)
586 {
587     Procedure proc;
588     BasicBlock* root = proc.addBlock();
589     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
590     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
591     Value* result = root->appendNew<Value>(proc, Add, Origin(),
592         root->appendNew<Const32Value>(proc, Origin(), a),
593         load);
594     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
595     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
596
597     int32_t inputOutput = b;
598     CHECK(!compileAndRun<int>(proc, &inputOutput));
599     CHECK(inputOutput == a + b);
600 }
601
602 void testAddArgZeroImmZDef()
603 {
604     Procedure proc;
605     BasicBlock* root = proc.addBlock();
606     Value* arg = root->appendNew<Value>(
607         proc, Trunc, Origin(),
608         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
609     Value* constZero = root->appendNew<Const32Value>(proc, Origin(), 0);
610     root->appendNewControlValue(
611         proc, Return, Origin(),
612         root->appendNew<Value>(
613             proc, Add, Origin(),
614             arg,
615             constZero));
616
617     auto code = compileProc(proc, 0);
618     CHECK(invoke<int64_t>(*code, 0x0123456789abcdef) == 0x89abcdef);
619 }
620
621 void testAddLoadTwice()
622 {
623     auto test = [&] (unsigned optLevel) {
624         Procedure proc;
625         BasicBlock* root = proc.addBlock();
626         int32_t value = 42;
627         Value* load = root->appendNew<MemoryValue>(
628             proc, Load, Int32, Origin(),
629             root->appendNew<ConstPtrValue>(proc, Origin(), &value));
630         root->appendNewControlValue(
631             proc, Return, Origin(),
632             root->appendNew<Value>(proc, Add, Origin(), load, load));
633
634         auto code = compileProc(proc, optLevel);
635         CHECK(invoke<int32_t>(*code) == 42 * 2);
636     };
637
638     test(0);
639     test(1);
640 }
641
642 void testAddArgDouble(double a)
643 {
644     Procedure proc;
645     BasicBlock* root = proc.addBlock();
646     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
647     root->appendNewControlValue(
648         proc, Return, Origin(),
649         root->appendNew<Value>(proc, Add, Origin(), value, value));
650
651     CHECK(isIdentical(compileAndRun<double>(proc, a), a + a));
652 }
653
654 void testAddArgsDouble(double a, double b)
655 {
656     Procedure proc;
657     BasicBlock* root = proc.addBlock();
658     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
659     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
660     root->appendNewControlValue(
661         proc, Return, Origin(),
662         root->appendNew<Value>(proc, Add, Origin(), valueA, valueB));
663
664     CHECK(isIdentical(compileAndRun<double>(proc, a, b), a + b));
665 }
666
667 void testAddArgImmDouble(double a, double b)
668 {
669     Procedure proc;
670     BasicBlock* root = proc.addBlock();
671     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
672     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
673     root->appendNewControlValue(
674         proc, Return, Origin(),
675         root->appendNew<Value>(proc, Add, Origin(), valueA, valueB));
676
677     CHECK(isIdentical(compileAndRun<double>(proc, a), a + b));
678 }
679
680 void testAddImmArgDouble(double a, double b)
681 {
682     Procedure proc;
683     BasicBlock* root = proc.addBlock();
684     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
685     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
686     root->appendNewControlValue(
687         proc, Return, Origin(),
688         root->appendNew<Value>(proc, Add, Origin(), valueA, valueB));
689
690     CHECK(isIdentical(compileAndRun<double>(proc, b), a + b));
691 }
692
693 void testAddImmsDouble(double a, double b)
694 {
695     Procedure proc;
696     BasicBlock* root = proc.addBlock();
697     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
698     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
699     root->appendNewControlValue(
700         proc, Return, Origin(),
701         root->appendNew<Value>(proc, Add, Origin(), valueA, valueB));
702
703     CHECK(isIdentical(compileAndRun<double>(proc), a + b));
704 }
705
706 void testAddArgFloat(float a)
707 {
708     Procedure proc;
709     BasicBlock* root = proc.addBlock();
710     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
711         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
712     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
713     Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue, floatValue);
714     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
715     root->appendNewControlValue(proc, Return, Origin(), result32);
716
717
718     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + a)));
719 }
720
721 void testAddArgsFloat(float a, float b)
722 {
723     Procedure proc;
724     BasicBlock* root = proc.addBlock();
725     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
726         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
727     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
728         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
729     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
730     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
731     Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue1, floatValue2);
732     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
733     root->appendNewControlValue(proc, Return, Origin(), result32);
734
735     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b)));
736 }
737
738 void testAddFPRArgsFloat(float a, float b)
739 {
740     Procedure proc;
741     BasicBlock* root = proc.addBlock();
742     Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
743         root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
744     Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
745         root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1));
746     Value* result = root->appendNew<Value>(proc, Add, Origin(), argument1, argument2);
747     root->appendNewControlValue(proc, Return, Origin(), result);
748
749     CHECK(isIdentical(compileAndRun<float>(proc, a, b), a + b));
750 }
751
752 void testAddArgImmFloat(float a, float b)
753 {
754     Procedure proc;
755     BasicBlock* root = proc.addBlock();
756     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
757         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
758     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
759     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
760     Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue, constValue);
761     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
762     root->appendNewControlValue(proc, Return, Origin(), result32);
763
764     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + b)));
765 }
766
767 void testAddImmArgFloat(float a, float b)
768 {
769     Procedure proc;
770     BasicBlock* root = proc.addBlock();
771     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
772         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
773     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
774     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
775     Value* result = root->appendNew<Value>(proc, Add, Origin(), constValue, floatValue);
776     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
777     root->appendNewControlValue(proc, Return, Origin(), result32);
778
779     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b)));
780 }
781
782 void testAddImmsFloat(float a, float b)
783 {
784     Procedure proc;
785     BasicBlock* root = proc.addBlock();
786     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
787     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
788     Value* result = root->appendNew<Value>(proc, Add, Origin(), constValue1, constValue2);
789     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
790     root->appendNewControlValue(proc, Return, Origin(), result32);
791
792     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a + b)));
793 }
794
795 void testAddArgFloatWithUselessDoubleConversion(float a)
796 {
797     Procedure proc;
798     BasicBlock* root = proc.addBlock();
799     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
800         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
801     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
802     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
803     Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble, asDouble);
804     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
805     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
806     root->appendNewControlValue(proc, Return, Origin(), result32);
807
808     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + a)));
809 }
810
811 void testAddArgsFloatWithUselessDoubleConversion(float a, float b)
812 {
813     Procedure proc;
814     BasicBlock* root = proc.addBlock();
815     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
816         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
817     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
818         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
819     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
820     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
821     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
822     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
823     Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble1, asDouble2);
824     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
825     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
826     root->appendNewControlValue(proc, Return, Origin(), result32);
827
828     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b)));
829 }
830
831 void testAddArgsFloatWithEffectfulDoubleConversion(float a, float b)
832 {
833     Procedure proc;
834     BasicBlock* root = proc.addBlock();
835     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
836         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
837     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
838         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
839     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
840     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
841     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
842     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
843     Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble1, asDouble2);
844     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
845     Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
846     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
847     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
848     root->appendNewControlValue(proc, Return, Origin(), result32);
849
850     double effect = 0;
851     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a + b)));
852     CHECK(isIdentical(effect, static_cast<double>(a) + static_cast<double>(b)));
853 }
854
855 void testMulArg(int a)
856 {
857     Procedure proc;
858     BasicBlock* root = proc.addBlock();
859     Value* value = root->appendNew<Value>(
860         proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
861     root->appendNewControlValue(
862         proc, Return, Origin(),
863         root->appendNew<Value>(proc, Mul, Origin(), value, value));
864
865     CHECK(compileAndRun<int>(proc, a) == a * a);
866 }
867
868 void testMulArgStore(int a)
869 {
870     Procedure proc;
871     BasicBlock* root = proc.addBlock();
872
873     int mulSlot;
874     int valueSlot;
875     
876     Value* value = root->appendNew<Value>(
877         proc, Trunc, Origin(),
878         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
879     Value* mul = root->appendNew<Value>(proc, Mul, Origin(), value, value);
880
881     root->appendNew<MemoryValue>(
882         proc, Store, Origin(), value,
883         root->appendNew<ConstPtrValue>(proc, Origin(), &valueSlot), 0);
884     root->appendNew<MemoryValue>(
885         proc, Store, Origin(), mul,
886         root->appendNew<ConstPtrValue>(proc, Origin(), &mulSlot), 0);
887
888     root->appendNewControlValue(
889         proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
890
891     CHECK(!compileAndRun<int>(proc, a));
892     CHECK(mulSlot == a * a);
893     CHECK(valueSlot == a);
894 }
895
896 void testMulAddArg(int a)
897 {
898     Procedure proc;
899     BasicBlock* root = proc.addBlock();
900     Value* value = root->appendNew<Value>(
901         proc, Trunc, Origin(),
902         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
903     root->appendNewControlValue(
904         proc, Return, Origin(),
905         root->appendNew<Value>(
906             proc, Add, Origin(),
907             root->appendNew<Value>(proc, Mul, Origin(), value, value),
908             value));
909
910     CHECK(compileAndRun<int>(proc, a) == a * a + a);
911 }
912
913 void testMulArgs(int a, int b)
914 {
915     Procedure proc;
916     BasicBlock* root = proc.addBlock();
917     root->appendNewControlValue(
918         proc, Return, Origin(),
919         root->appendNew<Value>(
920             proc, Mul, Origin(),
921             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
922             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
923
924     CHECK(compileAndRun<int>(proc, a, b) == a * b);
925 }
926
927 void testMulArgImm(int64_t a, int64_t b)
928 {
929     Procedure proc;
930     BasicBlock* root = proc.addBlock();
931     root->appendNewControlValue(
932         proc, Return, Origin(),
933         root->appendNew<Value>(
934             proc, Mul, Origin(),
935             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
936             root->appendNew<Const64Value>(proc, Origin(), b)));
937
938     CHECK(compileAndRun<int64_t>(proc, a) == a * b);
939 }
940
941 void testMulImmArg(int a, int b)
942 {
943     Procedure proc;
944     BasicBlock* root = proc.addBlock();
945     root->appendNewControlValue(
946         proc, Return, Origin(),
947         root->appendNew<Value>(
948             proc, Mul, Origin(),
949             root->appendNew<Const64Value>(proc, Origin(), a),
950             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
951
952     CHECK(compileAndRun<int>(proc, b) == a * b);
953 }
954
955 void testMulArgs32(int a, int b)
956 {
957     Procedure proc;
958     BasicBlock* root = proc.addBlock();
959     root->appendNewControlValue(
960         proc, Return, Origin(),
961         root->appendNew<Value>(
962             proc, Mul, Origin(),
963             root->appendNew<Value>(
964                 proc, Trunc, Origin(),
965                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
966             root->appendNew<Value>(
967                 proc, Trunc, Origin(),
968                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
969
970     CHECK(compileAndRun<int>(proc, a, b) == a * b);
971 }
972
973 void testMulLoadTwice()
974 {
975     auto test = [&] (unsigned optLevel) {
976         Procedure proc;
977         BasicBlock* root = proc.addBlock();
978         int32_t value = 42;
979         Value* load = root->appendNew<MemoryValue>(
980             proc, Load, Int32, Origin(),
981             root->appendNew<ConstPtrValue>(proc, Origin(), &value));
982         root->appendNewControlValue(
983             proc, Return, Origin(),
984             root->appendNew<Value>(proc, Mul, Origin(), load, load));
985
986         auto code = compileProc(proc, optLevel);
987         CHECK(invoke<int32_t>(*code) == 42 * 42);
988     };
989
990     test(0);
991     test(1);
992     test(2);
993 }
994
995 void testMulAddArgsLeft()
996 {
997     Procedure proc;
998     BasicBlock* root = proc.addBlock();
999
1000     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1001     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1002     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1003     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1004     Value* added = root->appendNew<Value>(proc, Add, Origin(), multiplied, arg2);
1005     root->appendNewControlValue(proc, Return, Origin(), added);
1006
1007     auto code = compileProc(proc);
1008
1009     auto testValues = int64Operands();
1010     for (auto a : testValues) {
1011         for (auto b : testValues) {
1012             for (auto c : testValues) {
1013                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value);
1014             }
1015         }
1016     }
1017 }
1018
1019 void testMulAddArgsRight()
1020 {
1021     Procedure proc;
1022     BasicBlock* root = proc.addBlock();
1023
1024     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1025     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1026     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1027     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1028     Value* added = root->appendNew<Value>(proc, Add, Origin(), arg0, multiplied);
1029     root->appendNewControlValue(proc, Return, Origin(), added);
1030
1031     auto code = compileProc(proc);
1032
1033     auto testValues = int64Operands();
1034     for (auto a : testValues) {
1035         for (auto b : testValues) {
1036             for (auto c : testValues) {
1037                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value);
1038             }
1039         }
1040     }
1041 }
1042
1043 void testMulAddArgsLeft32()
1044 {
1045     Procedure proc;
1046     BasicBlock* root = proc.addBlock();
1047
1048     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1049         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1050     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1051         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1052     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1053         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1054     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1055     Value* added = root->appendNew<Value>(proc, Add, Origin(), multiplied, arg2);
1056     root->appendNewControlValue(proc, Return, Origin(), added);
1057
1058     auto code = compileProc(proc);
1059
1060     auto testValues = int32Operands();
1061     for (auto a : testValues) {
1062         for (auto b : testValues) {
1063             for (auto c : testValues) {
1064                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value);
1065             }
1066         }
1067     }
1068 }
1069
1070 void testMulAddArgsRight32()
1071 {
1072     Procedure proc;
1073     BasicBlock* root = proc.addBlock();
1074
1075     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1076         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1077     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1078         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1079     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1080         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1081     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1082     Value* added = root->appendNew<Value>(proc, Add, Origin(), arg0, multiplied);
1083     root->appendNewControlValue(proc, Return, Origin(), added);
1084
1085     auto code = compileProc(proc);
1086
1087     auto testValues = int32Operands();
1088     for (auto a : testValues) {
1089         for (auto b : testValues) {
1090             for (auto c : testValues) {
1091                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value);
1092             }
1093         }
1094     }
1095 }
1096
1097 void testMulSubArgsLeft()
1098 {
1099     Procedure proc;
1100     BasicBlock* root = proc.addBlock();
1101
1102     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1103     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1104     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1105     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1106     Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
1107     root->appendNewControlValue(proc, Return, Origin(), added);
1108
1109     auto code = compileProc(proc);
1110
1111     auto testValues = int64Operands();
1112     for (auto a : testValues) {
1113         for (auto b : testValues) {
1114             for (auto c : testValues) {
1115                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
1116             }
1117         }
1118     }
1119 }
1120
1121 void testMulSubArgsRight()
1122 {
1123     Procedure proc;
1124     BasicBlock* root = proc.addBlock();
1125
1126     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1127     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1128     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1129     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1130     Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
1131     root->appendNewControlValue(proc, Return, Origin(), added);
1132
1133     auto code = compileProc(proc);
1134
1135     auto testValues = int64Operands();
1136     for (auto a : testValues) {
1137         for (auto b : testValues) {
1138             for (auto c : testValues) {
1139                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
1140             }
1141         }
1142     }
1143 }
1144
1145 void testMulSubArgsLeft32()
1146 {
1147     Procedure proc;
1148     BasicBlock* root = proc.addBlock();
1149
1150     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1151         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1152     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1153         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1154     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1155         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1156     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1157     Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
1158     root->appendNewControlValue(proc, Return, Origin(), added);
1159
1160     auto code = compileProc(proc);
1161
1162     auto testValues = int32Operands();
1163     for (auto a : testValues) {
1164         for (auto b : testValues) {
1165             for (auto c : testValues) {
1166                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
1167             }
1168         }
1169     }
1170 }
1171
1172 void testMulSubArgsRight32()
1173 {
1174     Procedure proc;
1175     BasicBlock* root = proc.addBlock();
1176
1177     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1178         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1179     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1180         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1181     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
1182         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
1183     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
1184     Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
1185     root->appendNewControlValue(proc, Return, Origin(), added);
1186
1187     auto code = compileProc(proc);
1188
1189     auto testValues = int32Operands();
1190     for (auto a : testValues) {
1191         for (auto b : testValues) {
1192             for (auto c : testValues) {
1193                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
1194             }
1195         }
1196     }
1197 }
1198
1199 void testMulNegArgs()
1200 {
1201     Procedure proc;
1202     BasicBlock* root = proc.addBlock();
1203
1204     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1205     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1206     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1207     Value* zero = root->appendNew<Const64Value>(proc, Origin(), 0);
1208     Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied);
1209     root->appendNewControlValue(proc, Return, Origin(), added);
1210
1211     auto code = compileProc(proc);
1212
1213     auto testValues = int64Operands();
1214     for (auto a : testValues) {
1215         for (auto b : testValues) {
1216             CHECK(invoke<int64_t>(*code, a.value, b.value) == -(a.value * b.value));
1217         }
1218     }
1219 }
1220
1221 void testMulNegArgs32()
1222 {
1223     Procedure proc;
1224     BasicBlock* root = proc.addBlock();
1225
1226     Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
1227         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1228     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
1229         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1230     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
1231     Value* zero = root->appendNew<Const32Value>(proc, Origin(), 0);
1232     Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied);
1233     root->appendNewControlValue(proc, Return, Origin(), added);
1234
1235     auto code = compileProc(proc);
1236
1237     auto testValues = int32Operands();
1238     for (auto a : testValues) {
1239         for (auto b : testValues) {
1240             CHECK(invoke<int32_t>(*code, a.value, b.value) == -(a.value * b.value));
1241         }
1242     }
1243 }
1244
1245 void testMulArgDouble(double a)
1246 {
1247     Procedure proc;
1248     BasicBlock* root = proc.addBlock();
1249     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1250     root->appendNewControlValue(
1251         proc, Return, Origin(),
1252         root->appendNew<Value>(proc, Mul, Origin(), value, value));
1253
1254     CHECK(isIdentical(compileAndRun<double>(proc, a), a * a));
1255 }
1256
1257 void testMulArgsDouble(double a, double b)
1258 {
1259     Procedure proc;
1260     BasicBlock* root = proc.addBlock();
1261     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1262     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1263     root->appendNewControlValue(
1264         proc, Return, Origin(),
1265         root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1266
1267     CHECK(isIdentical(compileAndRun<double>(proc, a, b), a * b));
1268 }
1269
1270 void testMulArgImmDouble(double a, double b)
1271 {
1272     Procedure proc;
1273     BasicBlock* root = proc.addBlock();
1274     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1275     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1276     root->appendNewControlValue(
1277         proc, Return, Origin(),
1278         root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1279
1280     CHECK(isIdentical(compileAndRun<double>(proc, a), a * b));
1281 }
1282
1283 void testMulImmArgDouble(double a, double b)
1284 {
1285     Procedure proc;
1286     BasicBlock* root = proc.addBlock();
1287     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1288     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1289     root->appendNewControlValue(
1290         proc, Return, Origin(),
1291         root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1292
1293     CHECK(isIdentical(compileAndRun<double>(proc, b), a * b));
1294 }
1295
1296 void testMulImmsDouble(double a, double b)
1297 {
1298     Procedure proc;
1299     BasicBlock* root = proc.addBlock();
1300     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1301     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1302     root->appendNewControlValue(
1303         proc, Return, Origin(),
1304         root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB));
1305
1306     CHECK(isIdentical(compileAndRun<double>(proc), a * b));
1307 }
1308
1309 void testMulArgFloat(float a)
1310 {
1311     Procedure proc;
1312     BasicBlock* root = proc.addBlock();
1313     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1314         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1315     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1316     Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue, floatValue);
1317     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1318     root->appendNewControlValue(proc, Return, Origin(), result32);
1319
1320
1321     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * a)));
1322 }
1323
1324 void testMulArgsFloat(float a, float b)
1325 {
1326     Procedure proc;
1327     BasicBlock* root = proc.addBlock();
1328     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1329         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1330     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1331         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1332     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1333     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1334     Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue1, floatValue2);
1335     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1336     root->appendNewControlValue(proc, Return, Origin(), result32);
1337
1338     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1339 }
1340
1341 void testMulArgImmFloat(float a, float b)
1342 {
1343     Procedure proc;
1344     BasicBlock* root = proc.addBlock();
1345     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1346         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1347     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1348     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1349     Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue, constValue);
1350     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1351     root->appendNewControlValue(proc, Return, Origin(), result32);
1352
1353     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * b)));
1354 }
1355
1356 void testMulImmArgFloat(float a, float b)
1357 {
1358     Procedure proc;
1359     BasicBlock* root = proc.addBlock();
1360     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1361         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1362     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1363     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1364     Value* result = root->appendNew<Value>(proc, Mul, Origin(), constValue, floatValue);
1365     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1366     root->appendNewControlValue(proc, Return, Origin(), result32);
1367
1368     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1369 }
1370
1371 void testMulImmsFloat(float a, float b)
1372 {
1373     Procedure proc;
1374     BasicBlock* root = proc.addBlock();
1375     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1376     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1377     Value* result = root->appendNew<Value>(proc, Mul, Origin(), constValue1, constValue2);
1378     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1379     root->appendNewControlValue(proc, Return, Origin(), result32);
1380
1381     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a * b)));
1382 }
1383
1384 void testMulArgFloatWithUselessDoubleConversion(float a)
1385 {
1386     Procedure proc;
1387     BasicBlock* root = proc.addBlock();
1388     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1389         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1390     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
1391     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1392     Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble, asDouble);
1393     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1394     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1395     root->appendNewControlValue(proc, Return, Origin(), result32);
1396
1397     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * a)));
1398 }
1399
1400 void testMulArgsFloatWithUselessDoubleConversion(float a, float b)
1401 {
1402     Procedure proc;
1403     BasicBlock* root = proc.addBlock();
1404     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1405         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1406     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1407         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1408     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1409     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1410     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1411     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1412     Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble1, asDouble2);
1413     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1414     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1415     root->appendNewControlValue(proc, Return, Origin(), result32);
1416
1417     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b)));
1418 }
1419
1420 void testMulArgsFloatWithEffectfulDoubleConversion(float a, float b)
1421 {
1422     Procedure proc;
1423     BasicBlock* root = proc.addBlock();
1424     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1425         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1426     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1427         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1428     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1429     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1430     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1431     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1432     Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble1, asDouble2);
1433     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1434     Value* doubleMulress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1435     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleMulress);
1436     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1437     root->appendNewControlValue(proc, Return, Origin(), result32);
1438
1439     double effect = 0;
1440     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a * b)));
1441     CHECK(isIdentical(effect, static_cast<double>(a) * static_cast<double>(b)));
1442 }
1443
1444 void testDivArgDouble(double a)
1445 {
1446     Procedure proc;
1447     BasicBlock* root = proc.addBlock();
1448     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1449     root->appendNewControlValue(
1450         proc, Return, Origin(),
1451         root->appendNew<Value>(proc, Div, Origin(), value, value));
1452
1453     CHECK(isIdentical(compileAndRun<double>(proc, a), a / a));
1454 }
1455
1456 void testDivArgsDouble(double a, double b)
1457 {
1458     Procedure proc;
1459     BasicBlock* root = proc.addBlock();
1460     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1461     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1462     root->appendNewControlValue(
1463         proc, Return, Origin(),
1464         root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1465
1466     CHECK(isIdentical(compileAndRun<double>(proc, a, b), a / b));
1467 }
1468
1469 void testDivArgImmDouble(double a, double b)
1470 {
1471     Procedure proc;
1472     BasicBlock* root = proc.addBlock();
1473     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1474     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1475     root->appendNewControlValue(
1476         proc, Return, Origin(),
1477         root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1478
1479     CHECK(isIdentical(compileAndRun<double>(proc, a), a / b));
1480 }
1481
1482 void testDivImmArgDouble(double a, double b)
1483 {
1484     Procedure proc;
1485     BasicBlock* root = proc.addBlock();
1486     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1487     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1488     root->appendNewControlValue(
1489         proc, Return, Origin(),
1490         root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1491
1492     CHECK(isIdentical(compileAndRun<double>(proc, b), a / b));
1493 }
1494
1495 void testDivImmsDouble(double a, double b)
1496 {
1497     Procedure proc;
1498     BasicBlock* root = proc.addBlock();
1499     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1500     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1501     root->appendNewControlValue(
1502         proc, Return, Origin(),
1503         root->appendNew<Value>(proc, Div, Origin(), valueA, valueB));
1504
1505     CHECK(isIdentical(compileAndRun<double>(proc), a / b));
1506 }
1507
1508 void testDivArgFloat(float a)
1509 {
1510     Procedure proc;
1511     BasicBlock* root = proc.addBlock();
1512     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1513         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1514     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1515     Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue, floatValue);
1516     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1517     root->appendNewControlValue(proc, Return, Origin(), result32);
1518
1519
1520     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a)));
1521 }
1522
1523 void testDivArgsFloat(float a, float b)
1524 {
1525     Procedure proc;
1526     BasicBlock* root = proc.addBlock();
1527     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1528         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1529     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1530         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1531     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1532     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1533     Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue1, floatValue2);
1534     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1535     root->appendNewControlValue(proc, Return, Origin(), result32);
1536
1537     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1538 }
1539
1540 void testDivArgImmFloat(float a, float b)
1541 {
1542     Procedure proc;
1543     BasicBlock* root = proc.addBlock();
1544     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1545         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1546     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1547     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1548     Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue, constValue);
1549     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1550     root->appendNewControlValue(proc, Return, Origin(), result32);
1551
1552     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / b)));
1553 }
1554
1555 void testDivImmArgFloat(float a, float b)
1556 {
1557     Procedure proc;
1558     BasicBlock* root = proc.addBlock();
1559     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1560         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1561     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1562     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1563     Value* result = root->appendNew<Value>(proc, Div, Origin(), constValue, floatValue);
1564     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1565     root->appendNewControlValue(proc, Return, Origin(), result32);
1566
1567     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1568 }
1569
1570 void testDivImmsFloat(float a, float b)
1571 {
1572     Procedure proc;
1573     BasicBlock* root = proc.addBlock();
1574     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1575     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1576     Value* result = root->appendNew<Value>(proc, Div, Origin(), constValue1, constValue2);
1577     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1578     root->appendNewControlValue(proc, Return, Origin(), result32);
1579
1580     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a / b)));
1581 }
1582
1583 void testModArgDouble(double a)
1584 {
1585     Procedure proc;
1586     BasicBlock* root = proc.addBlock();
1587     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1588     root->appendNewControlValue(
1589         proc, Return, Origin(),
1590         root->appendNew<Value>(proc, Mod, Origin(), value, value));
1591
1592     CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, a)));
1593 }
1594
1595 void testModArgsDouble(double a, double b)
1596 {
1597     Procedure proc;
1598     BasicBlock* root = proc.addBlock();
1599     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1600     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
1601     root->appendNewControlValue(
1602         proc, Return, Origin(),
1603         root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1604
1605     CHECK(isIdentical(compileAndRun<double>(proc, a, b), fmod(a, b)));
1606 }
1607
1608 void testModArgImmDouble(double a, double b)
1609 {
1610     Procedure proc;
1611     BasicBlock* root = proc.addBlock();
1612     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1613     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1614     root->appendNewControlValue(
1615         proc, Return, Origin(),
1616         root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1617
1618     CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, b)));
1619 }
1620
1621 void testModImmArgDouble(double a, double b)
1622 {
1623     Procedure proc;
1624     BasicBlock* root = proc.addBlock();
1625     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1626     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
1627     root->appendNewControlValue(
1628         proc, Return, Origin(),
1629         root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1630
1631     CHECK(isIdentical(compileAndRun<double>(proc, b), fmod(a, b)));
1632 }
1633
1634 void testModImmsDouble(double a, double b)
1635 {
1636     Procedure proc;
1637     BasicBlock* root = proc.addBlock();
1638     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
1639     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
1640     root->appendNewControlValue(
1641         proc, Return, Origin(),
1642         root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
1643
1644     CHECK(isIdentical(compileAndRun<double>(proc), fmod(a, b)));
1645 }
1646
1647 void testModArgFloat(float a)
1648 {
1649     Procedure proc;
1650     BasicBlock* root = proc.addBlock();
1651     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1652         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1653     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1654     Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, floatValue);
1655     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1656     root->appendNewControlValue(proc, Return, Origin(), result32);
1657
1658
1659     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, a)))));
1660 }
1661
1662 void testModArgsFloat(float a, float b)
1663 {
1664     Procedure proc;
1665     BasicBlock* root = proc.addBlock();
1666     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1667         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1668     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1669         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1670     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1671     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1672     Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue1, floatValue2);
1673     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1674     root->appendNewControlValue(proc, Return, Origin(), result32);
1675
1676     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)))));
1677 }
1678
1679 void testModArgImmFloat(float a, float b)
1680 {
1681     Procedure proc;
1682     BasicBlock* root = proc.addBlock();
1683     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1684         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1685     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1686     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1687     Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, constValue);
1688     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1689     root->appendNewControlValue(proc, Return, Origin(), result32);
1690
1691     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1692 }
1693
1694 void testModImmArgFloat(float a, float b)
1695 {
1696     Procedure proc;
1697     BasicBlock* root = proc.addBlock();
1698     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
1699         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1700     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
1701     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1702     Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue, floatValue);
1703     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1704     root->appendNewControlValue(proc, Return, Origin(), result32);
1705
1706     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1707 }
1708
1709 void testModImmsFloat(float a, float b)
1710 {
1711     Procedure proc;
1712     BasicBlock* root = proc.addBlock();
1713     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
1714     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
1715     Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue1, constValue2);
1716     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
1717     root->appendNewControlValue(proc, Return, Origin(), result32);
1718
1719     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
1720 }
1721
1722 void testDivArgFloatWithUselessDoubleConversion(float a)
1723 {
1724     Procedure proc;
1725     BasicBlock* root = proc.addBlock();
1726     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
1727         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1728     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
1729     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
1730     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble, asDouble);
1731     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1732     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1733     root->appendNewControlValue(proc, Return, Origin(), result32);
1734
1735     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a)));
1736 }
1737
1738 void testDivArgsFloatWithUselessDoubleConversion(float a, float b)
1739 {
1740     Procedure proc;
1741     BasicBlock* root = proc.addBlock();
1742     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1743         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1744     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1745         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1746     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1747     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1748     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1749     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1750     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2);
1751     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1752     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1753     root->appendNewControlValue(proc, Return, Origin(), result32);
1754
1755     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b)));
1756 }
1757
1758 void testDivArgsFloatWithEffectfulDoubleConversion(float a, float b)
1759 {
1760     Procedure proc;
1761     BasicBlock* root = proc.addBlock();
1762     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1763         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1764     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
1765         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1766     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
1767     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
1768     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
1769     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
1770     Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2);
1771     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
1772     Value* doubleDivress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
1773     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleDivress);
1774     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
1775     root->appendNewControlValue(proc, Return, Origin(), result32);
1776
1777     double effect = 0;
1778     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a / b)));
1779     CHECK(isIdentical(effect, static_cast<double>(a) / static_cast<double>(b)));
1780 }
1781
1782 void testUDivArgsInt32(uint32_t a, uint32_t b)
1783 {
1784     // UDiv with denominator == 0 is invalid.
1785     if (!b)
1786         return;
1787
1788     Procedure proc;
1789     BasicBlock* root = proc.addBlock();
1790     Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
1791         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1792     Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
1793         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1794     Value* result = root->appendNew<Value>(proc, UDiv, Origin(), argument1, argument2);
1795     root->appendNew<Value>(proc, Return, Origin(), result);
1796
1797     CHECK_EQ(compileAndRun<uint32_t>(proc, a, b), a / b);
1798 }
1799
1800 void testUDivArgsInt64(uint64_t a, uint64_t b)
1801 {
1802     // UDiv with denominator == 0 is invalid.
1803     if (!b)
1804         return;
1805
1806     Procedure proc;
1807     BasicBlock* root = proc.addBlock();
1808     Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1809     Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1810     Value* result = root->appendNew<Value>(proc, UDiv, Origin(), argument1, argument2);
1811     root->appendNew<Value>(proc, Return, Origin(), result);
1812
1813     CHECK_EQ(compileAndRun<uint64_t>(proc, a, b), a / b);
1814 }
1815
1816 void testUModArgsInt32(uint32_t a, uint32_t b)
1817 {
1818     // UMod with denominator == 0 is invalid.
1819     if (!b)
1820         return;
1821
1822     Procedure proc;
1823     BasicBlock* root = proc.addBlock();
1824     Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
1825         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
1826     Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
1827         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1828     Value* result = root->appendNew<Value>(proc, UMod, Origin(), argument1, argument2);
1829     root->appendNew<Value>(proc, Return, Origin(), result);
1830
1831     CHECK_EQ(compileAndRun<uint32_t>(proc, a, b), a % b);
1832 }
1833
1834 void testUModArgsInt64(uint64_t a, uint64_t b)
1835 {
1836     // UMod with denominator == 0 is invalid.
1837     if (!b)
1838         return;
1839
1840     Procedure proc;
1841     BasicBlock* root = proc.addBlock();
1842     Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1843     Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1844     Value* result = root->appendNew<Value>(proc, UMod, Origin(), argument1, argument2);
1845     root->appendNew<Value>(proc, Return, Origin(), result);
1846     
1847     CHECK_EQ(compileAndRun<uint64_t>(proc, a, b), a % b);
1848 }
1849
1850 void testSubArg(int a)
1851 {
1852     Procedure proc;
1853     BasicBlock* root = proc.addBlock();
1854     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1855     root->appendNewControlValue(
1856         proc, Return, Origin(),
1857         root->appendNew<Value>(proc, Sub, Origin(), value, value));
1858
1859     CHECK(!compileAndRun<int>(proc, a));
1860 }
1861
1862 void testSubArgs(int a, int b)
1863 {
1864     Procedure proc;
1865     BasicBlock* root = proc.addBlock();
1866     root->appendNewControlValue(
1867         proc, Return, Origin(),
1868         root->appendNew<Value>(
1869             proc, Sub, Origin(),
1870             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1871             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
1872
1873     CHECK(compileAndRun<int>(proc, a, b) == a - b);
1874 }
1875
1876 void testSubArgImm(int64_t a, int64_t b)
1877 {
1878     Procedure proc;
1879     BasicBlock* root = proc.addBlock();
1880     root->appendNewControlValue(
1881         proc, Return, Origin(),
1882         root->appendNew<Value>(
1883             proc, Sub, Origin(),
1884             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1885             root->appendNew<Const64Value>(proc, Origin(), b)));
1886
1887     CHECK(compileAndRun<int64_t>(proc, a) == a - b);
1888 }
1889
1890 void testNegValueSubOne(int a)
1891 {
1892     Procedure proc;
1893     BasicBlock* root = proc.addBlock();
1894     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1895     Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
1896         root->appendNew<Const64Value>(proc, Origin(), 0),
1897         argument);
1898     Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
1899         negArgument,
1900         root->appendNew<Const64Value>(proc, Origin(), 1));
1901     root->appendNewControlValue(proc, Return, Origin(), negArgumentMinusOne);
1902     CHECK(compileAndRun<int>(proc, a) == -a - 1);
1903 }
1904
1905 void testSubImmArg(int a, int b)
1906 {
1907     Procedure proc;
1908     BasicBlock* root = proc.addBlock();
1909     root->appendNewControlValue(
1910         proc, Return, Origin(),
1911         root->appendNew<Value>(
1912             proc, Sub, Origin(),
1913             root->appendNew<Const64Value>(proc, Origin(), a),
1914             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
1915
1916     CHECK(compileAndRun<int>(proc, b) == a - b);
1917 }
1918
1919 void testSubArgMem(int64_t a, int64_t b)
1920 {
1921     Procedure proc;
1922     BasicBlock* root = proc.addBlock();
1923     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
1924     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1925     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1926         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
1927         load);
1928     root->appendNewControlValue(proc, Return, Origin(), result);
1929
1930     CHECK(compileAndRun<int64_t>(proc, a, &b) == a - b);
1931 }
1932
1933 void testSubMemArg(int64_t a, int64_t b)
1934 {
1935     Procedure proc;
1936     BasicBlock* root = proc.addBlock();
1937     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1938     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1939     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1940         load,
1941         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
1942     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1943     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1944
1945     int64_t inputOutput = a;
1946     CHECK(!compileAndRun<int64_t>(proc, &inputOutput, b));
1947     CHECK(inputOutput == a - b);
1948 }
1949
1950 void testSubImmMem(int64_t a, int64_t b)
1951 {
1952     Procedure proc;
1953     BasicBlock* root = proc.addBlock();
1954     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1955     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1956     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1957         root->appendNew<Const64Value>(proc, Origin(), a),
1958         load);
1959     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1960     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1961
1962     int64_t inputOutput = b;
1963     CHECK(!compileAndRun<int>(proc, &inputOutput));
1964     CHECK(inputOutput == a - b);
1965 }
1966
1967 void testSubMemImm(int64_t a, int64_t b)
1968 {
1969     Procedure proc;
1970     BasicBlock* root = proc.addBlock();
1971     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
1972     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
1973     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
1974         load,
1975         root->appendNew<Const64Value>(proc, Origin(), b));
1976     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
1977     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
1978
1979     int64_t inputOutput = a;
1980     CHECK(!compileAndRun<int>(proc, &inputOutput));
1981     CHECK(inputOutput == a - b);
1982 }
1983
1984
1985 void testSubArgs32(int a, int b)
1986 {
1987     Procedure proc;
1988     BasicBlock* root = proc.addBlock();
1989     root->appendNewControlValue(
1990         proc, Return, Origin(),
1991         root->appendNew<Value>(
1992             proc, Sub, Origin(),
1993             root->appendNew<Value>(
1994                 proc, Trunc, Origin(),
1995                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
1996             root->appendNew<Value>(
1997                 proc, Trunc, Origin(),
1998                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
1999
2000     CHECK(compileAndRun<int>(proc, a, b) == a - b);
2001 }
2002
2003 void testSubArgImm32(int a, int b)
2004 {
2005     Procedure proc;
2006     BasicBlock* root = proc.addBlock();
2007     root->appendNewControlValue(
2008         proc, Return, Origin(),
2009         root->appendNew<Value>(
2010             proc, Sub, Origin(),
2011             root->appendNew<Value>(
2012                 proc, Trunc, Origin(),
2013                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2014             root->appendNew<Const32Value>(proc, Origin(), b)));
2015
2016     CHECK(compileAndRun<int>(proc, a) == a - b);
2017 }
2018
2019 void testSubImmArg32(int a, int b)
2020 {
2021     Procedure proc;
2022     BasicBlock* root = proc.addBlock();
2023     root->appendNewControlValue(
2024         proc, Return, Origin(),
2025         root->appendNew<Value>(
2026             proc, Sub, Origin(),
2027             root->appendNew<Const32Value>(proc, Origin(), a),
2028             root->appendNew<Value>(
2029                 proc, Trunc, Origin(),
2030                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2031
2032     CHECK(compileAndRun<int>(proc, b) == a - b);
2033 }
2034
2035 void testSubMemArg32(int32_t a, int32_t b)
2036 {
2037     Procedure proc;
2038     BasicBlock* root = proc.addBlock();
2039     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2040     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2041     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2042         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2043     Value* result = root->appendNew<Value>(proc, Sub, Origin(), load, argument);
2044     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2045     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2046
2047     int32_t inputOutput = a;
2048     CHECK(!compileAndRun<int32_t>(proc, &inputOutput, b));
2049     CHECK(inputOutput == a - b);
2050 }
2051
2052 void testSubArgMem32(int32_t a, int32_t b)
2053 {
2054     Procedure proc;
2055     BasicBlock* root = proc.addBlock();
2056     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2057     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2058     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2059         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2060     Value* result = root->appendNew<Value>(proc, Sub, Origin(), argument, load);
2061     root->appendNewControlValue(proc, Return, Origin(), result);
2062
2063     CHECK(compileAndRun<int32_t>(proc, a, &b) == a - b);
2064 }
2065
2066 void testSubImmMem32(int32_t a, int32_t b)
2067 {
2068     Procedure proc;
2069     BasicBlock* root = proc.addBlock();
2070     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2071     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2072     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2073         root->appendNew<Const32Value>(proc, Origin(), a),
2074         load);
2075     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2076     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2077
2078     int32_t inputOutput = b;
2079     CHECK(!compileAndRun<int>(proc, &inputOutput));
2080     CHECK(inputOutput == a - b);
2081 }
2082
2083 void testSubMemImm32(int32_t a, int32_t b)
2084 {
2085     Procedure proc;
2086     BasicBlock* root = proc.addBlock();
2087     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2088     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
2089     Value* result = root->appendNew<Value>(proc, Sub, Origin(),
2090         load,
2091         root->appendNew<Const32Value>(proc, Origin(), b));
2092     root->appendNew<MemoryValue>(proc, Store, Origin(), result, address);
2093     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
2094
2095     int32_t inputOutput = a;
2096     CHECK(!compileAndRun<int>(proc, &inputOutput));
2097     CHECK(inputOutput == a - b);
2098 }
2099
2100 void testNegValueSubOne32(int a)
2101 {
2102     Procedure proc;
2103     BasicBlock* root = proc.addBlock();
2104     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2105         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2106     Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(),
2107         root->appendNew<Const32Value>(proc, Origin(), 0),
2108         argument);
2109     Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(),
2110         negArgument,
2111         root->appendNew<Const32Value>(proc, Origin(), 1));
2112     root->appendNewControlValue(proc, Return, Origin(), negArgumentMinusOne);
2113     CHECK(compileAndRun<int>(proc, a) == -a - 1);
2114 }
2115
2116 void testSubArgDouble(double a)
2117 {
2118     Procedure proc;
2119     BasicBlock* root = proc.addBlock();
2120     Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2121     root->appendNewControlValue(
2122         proc, Return, Origin(),
2123         root->appendNew<Value>(proc, Sub, Origin(), value, value));
2124
2125     CHECK(isIdentical(compileAndRun<double>(proc, a), a - a));
2126 }
2127
2128 void testSubArgsDouble(double a, double b)
2129 {
2130     Procedure proc;
2131     BasicBlock* root = proc.addBlock();
2132     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2133     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2134     root->appendNewControlValue(
2135         proc, Return, Origin(),
2136         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2137
2138     CHECK(isIdentical(compileAndRun<double>(proc, a, b), a - b));
2139 }
2140
2141 void testSubArgImmDouble(double a, double b)
2142 {
2143     Procedure proc;
2144     BasicBlock* root = proc.addBlock();
2145     Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2146     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2147     root->appendNewControlValue(
2148         proc, Return, Origin(),
2149         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2150
2151     CHECK(isIdentical(compileAndRun<double>(proc, a), a - b));
2152 }
2153
2154 void testSubImmArgDouble(double a, double b)
2155 {
2156     Procedure proc;
2157     BasicBlock* root = proc.addBlock();
2158     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2159     Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2160     root->appendNewControlValue(
2161         proc, Return, Origin(),
2162         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2163
2164     CHECK(isIdentical(compileAndRun<double>(proc, b), a - b));
2165 }
2166
2167 void testSubImmsDouble(double a, double b)
2168 {
2169     Procedure proc;
2170     BasicBlock* root = proc.addBlock();
2171     Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2172     Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2173     root->appendNewControlValue(
2174         proc, Return, Origin(),
2175         root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB));
2176     
2177     CHECK(isIdentical(compileAndRun<double>(proc), a - b));
2178 }
2179
2180 void testSubArgFloat(float a)
2181 {
2182     Procedure proc;
2183     BasicBlock* root = proc.addBlock();
2184     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2185         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2186     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2187     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, floatValue);
2188     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2189     root->appendNewControlValue(proc, Return, Origin(), result32);
2190
2191
2192     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a)));
2193 }
2194
2195 void testSubArgsFloat(float a, float b)
2196 {
2197     Procedure proc;
2198     BasicBlock* root = proc.addBlock();
2199     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2200         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2201     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2202         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2203     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2204     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2205     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue1, floatValue2);
2206     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2207     root->appendNewControlValue(proc, Return, Origin(), result32);
2208
2209     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2210 }
2211
2212 void testSubArgImmFloat(float a, float b)
2213 {
2214     Procedure proc;
2215     BasicBlock* root = proc.addBlock();
2216     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2217         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2218     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2219     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2220     Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, constValue);
2221     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2222     root->appendNewControlValue(proc, Return, Origin(), result32);
2223
2224     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - b)));
2225 }
2226
2227 void testSubImmArgFloat(float a, float b)
2228 {
2229     Procedure proc;
2230     BasicBlock* root = proc.addBlock();
2231     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2232         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2233     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2234     Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2235     Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue, floatValue);
2236     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2237     root->appendNewControlValue(proc, Return, Origin(), result32);
2238
2239     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2240 }
2241
2242 void testSubImmsFloat(float a, float b)
2243 {
2244     Procedure proc;
2245     BasicBlock* root = proc.addBlock();
2246     Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2247     Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2248     Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue1, constValue2);
2249     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
2250     root->appendNewControlValue(proc, Return, Origin(), result32);
2251
2252     CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a - b)));
2253 }
2254
2255 void testSubArgFloatWithUselessDoubleConversion(float a)
2256 {
2257     Procedure proc;
2258     BasicBlock* root = proc.addBlock();
2259     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
2260         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2261     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
2262     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2263     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble, asDouble);
2264     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2265     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2266     root->appendNewControlValue(proc, Return, Origin(), result32);
2267
2268     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a)));
2269 }
2270
2271 void testSubArgsFloatWithUselessDoubleConversion(float a, float b)
2272 {
2273     Procedure proc;
2274     BasicBlock* root = proc.addBlock();
2275     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2276         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2277     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2278         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2279     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2280     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2281     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
2282     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
2283     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2);
2284     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2285     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2286     root->appendNewControlValue(proc, Return, Origin(), result32);
2287
2288     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b)));
2289 }
2290
2291 void testSubArgsFloatWithEffectfulDoubleConversion(float a, float b)
2292 {
2293     Procedure proc;
2294     BasicBlock* root = proc.addBlock();
2295     Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2296         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2297     Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
2298         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
2299     Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
2300     Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
2301     Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1);
2302     Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2);
2303     Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2);
2304     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2305     Value* doubleSubress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
2306     root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleSubress);
2307     Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
2308     root->appendNewControlValue(proc, Return, Origin(), result32);
2309
2310     double effect = 0;
2311     CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a - b)));
2312     CHECK(isIdentical(effect, static_cast<double>(a) - static_cast<double>(b)));
2313 }
2314
2315 void testTernarySubInstructionSelection(B3::Opcode valueModifier, Type valueType, Air::Opcode expectedOpcode)
2316 {
2317     Procedure proc;
2318     BasicBlock* root = proc.addBlock();
2319
2320     Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2321     Value* right = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2322
2323     if (valueModifier == Trunc) {
2324         left = root->appendNew<Value>(proc, valueModifier, valueType, Origin(), left);
2325         right = root->appendNew<Value>(proc, valueModifier, valueType, Origin(), right);
2326     }
2327
2328     root->appendNewControlValue(
2329         proc, Return, Origin(),
2330         root->appendNew<Value>(proc, Sub, Origin(), left, right));
2331
2332     lowerToAirForTesting(proc);
2333
2334     auto block = proc.code()[0];
2335     unsigned numberOfSubInstructions = 0;
2336     for (auto instruction : *block) {
2337         if (instruction.kind.opcode == expectedOpcode) {
2338             CHECK_EQ(instruction.args.size(), 3ul);
2339             CHECK_EQ(instruction.args[0].kind(), Air::Arg::Tmp);
2340             CHECK_EQ(instruction.args[1].kind(), Air::Arg::Tmp);
2341             CHECK_EQ(instruction.args[2].kind(), Air::Arg::Tmp);
2342             numberOfSubInstructions++;
2343         }
2344     }
2345     CHECK_EQ(numberOfSubInstructions, 1ul);
2346 }
2347
2348 void testNegDouble(double a)
2349 {
2350     Procedure proc;
2351     BasicBlock* root = proc.addBlock();
2352     root->appendNewControlValue(
2353         proc, Return, Origin(),
2354         root->appendNew<Value>(
2355             proc, Neg, Origin(),
2356             root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
2357
2358     CHECK(isIdentical(compileAndRun<double>(proc, a), -a));
2359 }
2360
2361 void testNegFloat(float a)
2362 {
2363     Procedure proc;
2364     BasicBlock* root = proc.addBlock();
2365     Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
2366         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2367     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
2368     root->appendNewControlValue(
2369         proc, Return, Origin(),
2370         root->appendNew<Value>(proc, Neg, Origin(), floatValue));
2371
2372     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), -a));
2373 }
2374
2375 void testNegFloatWithUselessDoubleConversion(float a)
2376 {
2377     Procedure proc;
2378     BasicBlock* root = proc.addBlock();
2379     Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
2380         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2381     Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32);
2382     Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
2383     Value* result = root->appendNew<Value>(proc, Neg, Origin(), asDouble);
2384     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
2385     root->appendNewControlValue(proc, Return, Origin(), floatResult);
2386
2387     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), -a));
2388 }
2389
2390 void testBitAndArgs(int64_t a, int64_t b)
2391 {
2392     Procedure proc;
2393     BasicBlock* root = proc.addBlock();
2394     root->appendNewControlValue(
2395         proc, Return, Origin(),
2396         root->appendNew<Value>(
2397             proc, BitAnd, Origin(),
2398             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2399             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2400
2401     CHECK(compileAndRun<int64_t>(proc, a, b) == (a & b));
2402 }
2403
2404 void testBitAndSameArg(int64_t a)
2405 {
2406     Procedure proc;
2407     BasicBlock* root = proc.addBlock();
2408     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2409     root->appendNewControlValue(
2410         proc, Return, Origin(),
2411         root->appendNew<Value>(
2412             proc, BitAnd, Origin(),
2413             argument,
2414             argument));
2415
2416     CHECK(compileAndRun<int64_t>(proc, a) == a);
2417 }
2418
2419 void testBitAndImms(int64_t a, int64_t b)
2420 {
2421     Procedure proc;
2422     BasicBlock* root = proc.addBlock();
2423     root->appendNewControlValue(
2424         proc, Return, Origin(),
2425         root->appendNew<Value>(
2426             proc, BitAnd, Origin(),
2427             root->appendNew<Const64Value>(proc, Origin(), a),
2428             root->appendNew<Const64Value>(proc, Origin(), b)));
2429
2430     CHECK(compileAndRun<int64_t>(proc) == (a & b));
2431 }
2432
2433 void testBitAndArgImm(int64_t a, int64_t b)
2434 {
2435     Procedure proc;
2436     BasicBlock* root = proc.addBlock();
2437     root->appendNewControlValue(
2438         proc, Return, Origin(),
2439         root->appendNew<Value>(
2440             proc, BitAnd, Origin(),
2441             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2442             root->appendNew<Const64Value>(proc, Origin(), b)));
2443
2444     CHECK(compileAndRun<int64_t>(proc, a) == (a & b));
2445 }
2446
2447 void testBitAndImmArg(int64_t a, int64_t b)
2448 {
2449     Procedure proc;
2450     BasicBlock* root = proc.addBlock();
2451     root->appendNewControlValue(
2452         proc, Return, Origin(),
2453         root->appendNew<Value>(
2454             proc, BitAnd, Origin(),
2455             root->appendNew<Const64Value>(proc, Origin(), a),
2456             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2457
2458     CHECK(compileAndRun<int64_t>(proc, b) == (a & b));
2459 }
2460
2461 void testBitAndBitAndArgImmImm(int64_t a, int64_t b, int64_t c)
2462 {
2463     Procedure proc;
2464     BasicBlock* root = proc.addBlock();
2465     Value* innerBitAnd = root->appendNew<Value>(
2466         proc, BitAnd, Origin(),
2467         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2468         root->appendNew<Const64Value>(proc, Origin(), b));
2469     root->appendNewControlValue(
2470         proc, Return, Origin(),
2471         root->appendNew<Value>(
2472             proc, BitAnd, Origin(),
2473             innerBitAnd,
2474             root->appendNew<Const64Value>(proc, Origin(), c)));
2475
2476     CHECK(compileAndRun<int64_t>(proc, a) == ((a & b) & c));
2477 }
2478
2479 void testBitAndImmBitAndArgImm(int64_t a, int64_t b, int64_t c)
2480 {
2481     Procedure proc;
2482     BasicBlock* root = proc.addBlock();
2483     Value* innerBitAnd = root->appendNew<Value>(
2484         proc, BitAnd, Origin(),
2485         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2486         root->appendNew<Const64Value>(proc, Origin(), c));
2487     root->appendNewControlValue(
2488         proc, Return, Origin(),
2489         root->appendNew<Value>(
2490             proc, BitAnd, Origin(),
2491             root->appendNew<Const64Value>(proc, Origin(), a),
2492             innerBitAnd));
2493
2494     CHECK(compileAndRun<int64_t>(proc, b) == (a & (b & c)));
2495 }
2496
2497 void testBitAndArgs32(int a, int b)
2498 {
2499     Procedure proc;
2500     BasicBlock* root = proc.addBlock();
2501     root->appendNewControlValue(
2502         proc, Return, Origin(),
2503         root->appendNew<Value>(
2504             proc, BitAnd, Origin(),
2505             root->appendNew<Value>(
2506                 proc, Trunc, Origin(),
2507                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2508             root->appendNew<Value>(
2509                 proc, Trunc, Origin(),
2510                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2511
2512     CHECK(compileAndRun<int>(proc, a, b) == (a & b));
2513 }
2514
2515 void testBitAndSameArg32(int a)
2516 {
2517     Procedure proc;
2518     BasicBlock* root = proc.addBlock();
2519     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
2520         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2521     root->appendNewControlValue(
2522         proc, Return, Origin(),
2523         root->appendNew<Value>(
2524             proc, BitAnd, Origin(),
2525             argument,
2526             argument));
2527
2528     CHECK(compileAndRun<int>(proc, a) == a);
2529 }
2530
2531 void testBitAndImms32(int a, int b)
2532 {
2533     Procedure proc;
2534     BasicBlock* root = proc.addBlock();
2535     root->appendNewControlValue(
2536         proc, Return, Origin(),
2537         root->appendNew<Value>(
2538             proc, BitAnd, Origin(),
2539             root->appendNew<Const32Value>(proc, Origin(), a),
2540             root->appendNew<Const32Value>(proc, Origin(), b)));
2541
2542     CHECK(compileAndRun<int>(proc) == (a & b));
2543 }
2544
2545 void testBitAndArgImm32(int a, int b)
2546 {
2547     Procedure proc;
2548     BasicBlock* root = proc.addBlock();
2549     root->appendNewControlValue(
2550         proc, Return, Origin(),
2551         root->appendNew<Value>(
2552             proc, BitAnd, Origin(),
2553             root->appendNew<Value>(
2554                 proc, Trunc, Origin(),
2555                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2556             root->appendNew<Const32Value>(proc, Origin(), b)));
2557
2558     CHECK(compileAndRun<int>(proc, a) == (a & b));
2559 }
2560
2561 void testBitAndImmArg32(int a, int b)
2562 {
2563     Procedure proc;
2564     BasicBlock* root = proc.addBlock();
2565     root->appendNewControlValue(
2566         proc, Return, Origin(),
2567         root->appendNew<Value>(
2568             proc, BitAnd, Origin(),
2569             root->appendNew<Const32Value>(proc, Origin(), a),
2570             root->appendNew<Value>(
2571                 proc, Trunc, Origin(),
2572                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2573
2574     CHECK(compileAndRun<int>(proc, b) == (a & b));
2575 }
2576
2577 void testBitAndBitAndArgImmImm32(int a, int b, int c)
2578 {
2579     Procedure proc;
2580     BasicBlock* root = proc.addBlock();
2581     Value* innerBitAnd = root->appendNew<Value>(
2582         proc, BitAnd, Origin(),
2583         root->appendNew<Value>(
2584             proc, Trunc, Origin(),
2585             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2586         root->appendNew<Const32Value>(proc, Origin(), b));
2587     root->appendNewControlValue(
2588         proc, Return, Origin(),
2589         root->appendNew<Value>(
2590             proc, BitAnd, Origin(),
2591             innerBitAnd,
2592             root->appendNew<Const32Value>(proc, Origin(), c)));
2593
2594     CHECK(compileAndRun<int>(proc, a) == ((a & b) & c));
2595 }
2596
2597 void testBitAndImmBitAndArgImm32(int a, int b, int c)
2598 {
2599     Procedure proc;
2600     BasicBlock* root = proc.addBlock();
2601     Value* innerBitAnd = root->appendNew<Value>(
2602         proc, BitAnd, Origin(),
2603         root->appendNew<Value>(
2604             proc, Trunc, Origin(),
2605             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2606         root->appendNew<Const32Value>(proc, Origin(), c));
2607     root->appendNewControlValue(
2608         proc, Return, Origin(),
2609         root->appendNew<Value>(
2610             proc, BitAnd, Origin(),
2611             root->appendNew<Const32Value>(proc, Origin(), a),
2612             innerBitAnd));
2613
2614     CHECK(compileAndRun<int>(proc, b) == (a & (b & c)));
2615 }
2616
2617 void testBitAndWithMaskReturnsBooleans(int64_t a, int64_t b)
2618 {
2619     Procedure proc;
2620     BasicBlock* root = proc.addBlock();
2621     Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2622     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
2623     Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg0, arg1);
2624     Value* maskedEqual = root->appendNew<Value>(proc, BitAnd, Origin(),
2625         root->appendNew<Const32Value>(proc, Origin(), 0x5),
2626         equal);
2627     Value* inverted = root->appendNew<Value>(proc, BitXor, Origin(),
2628         root->appendNew<Const32Value>(proc, Origin(), 0x1),
2629         maskedEqual);
2630     Value* select = root->appendNew<Value>(proc, Select, Origin(), inverted,
2631         root->appendNew<Const64Value>(proc, Origin(), 42),
2632         root->appendNew<Const64Value>(proc, Origin(), -5));
2633
2634     root->appendNewControlValue(proc, Return, Origin(), select);
2635
2636     int64_t expected = (a == b) ? -5 : 42;
2637     CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
2638 }
2639
2640 double bitAndDouble(double a, double b)
2641 {
2642     return bitwise_cast<double>(bitwise_cast<uint64_t>(a) & bitwise_cast<uint64_t>(b));
2643 }
2644
2645 void testBitAndArgDouble(double a)
2646 {
2647     Procedure proc;
2648     BasicBlock* root = proc.addBlock();
2649     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2650     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2651     root->appendNewControlValue(proc, Return, Origin(), result);
2652
2653     CHECK(isIdentical(compileAndRun<double>(proc, a), bitAndDouble(a, a)));
2654 }
2655
2656 void testBitAndArgsDouble(double a, double b)
2657 {
2658     Procedure proc;
2659     BasicBlock* root = proc.addBlock();
2660     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2661     Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
2662     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2663     root->appendNewControlValue(proc, Return, Origin(), result);
2664
2665     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2666 }
2667
2668 void testBitAndArgImmDouble(double a, double b)
2669 {
2670     Procedure proc;
2671     BasicBlock* root = proc.addBlock();
2672     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
2673     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2674     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2675     root->appendNewControlValue(proc, Return, Origin(), result);
2676
2677     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
2678 }
2679
2680 void testBitAndImmsDouble(double a, double b)
2681 {
2682     Procedure proc;
2683     BasicBlock* root = proc.addBlock();
2684     Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
2685     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
2686     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2687     root->appendNewControlValue(proc, Return, Origin(), result);
2688
2689     CHECK(isIdentical(compileAndRun<double>(proc), bitAndDouble(a, b)));
2690 }
2691
2692 float bitAndFloat(float a, float b)
2693 {
2694     return bitwise_cast<float>(bitwise_cast<uint32_t>(a) & bitwise_cast<uint32_t>(b));
2695 }
2696
2697 void testBitAndArgFloat(float a)
2698 {
2699     Procedure proc;
2700     BasicBlock* root = proc.addBlock();
2701     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2702         root->appendNew<Value>(proc, Trunc, Origin(),
2703             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2704     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
2705     root->appendNewControlValue(proc, Return, Origin(), result);
2706
2707     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitAndFloat(a, a)));
2708 }
2709
2710 void testBitAndArgsFloat(float a, float b)
2711 {
2712     Procedure proc;
2713     BasicBlock* root = proc.addBlock();
2714     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2715         root->appendNew<Value>(proc, Trunc, Origin(),
2716             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2717     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2718         root->appendNew<Value>(proc, Trunc, Origin(),
2719             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2720     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2721     root->appendNewControlValue(proc, Return, Origin(), result);
2722
2723     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
2724 }
2725
2726 void testBitAndArgImmFloat(float a, float b)
2727 {
2728     Procedure proc;
2729     BasicBlock* root = proc.addBlock();
2730     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2731         root->appendNew<Value>(proc, Trunc, Origin(),
2732             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2733     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2734     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2735     root->appendNewControlValue(proc, Return, Origin(), result);
2736
2737     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
2738 }
2739
2740 void testBitAndImmsFloat(float a, float b)
2741 {
2742     Procedure proc;
2743     BasicBlock* root = proc.addBlock();
2744     Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
2745     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
2746     Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
2747     root->appendNewControlValue(proc, Return, Origin(), result);
2748
2749     CHECK(isIdentical(compileAndRun<float>(proc), bitAndFloat(a, b)));
2750 }
2751
2752 void testBitAndArgsFloatWithUselessDoubleConversion(float a, float b)
2753 {
2754     Procedure proc;
2755     BasicBlock* root = proc.addBlock();
2756     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2757         root->appendNew<Value>(proc, Trunc, Origin(),
2758             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2759     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
2760         root->appendNew<Value>(proc, Trunc, Origin(),
2761             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2762     Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
2763     Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
2764     Value* doubleResult = root->appendNew<Value>(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble);
2765     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
2766     root->appendNewControlValue(proc, Return, Origin(), floatResult);
2767
2768     double doubleA = a;
2769     double doubleB = b;
2770     float expected = static_cast<float>(bitAndDouble(doubleA, doubleB));
2771     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
2772 }
2773
2774 void testBitOrArgs(int64_t a, int64_t b)
2775 {
2776     Procedure proc;
2777     BasicBlock* root = proc.addBlock();
2778     root->appendNewControlValue(
2779         proc, Return, Origin(),
2780         root->appendNew<Value>(
2781             proc, BitOr, Origin(),
2782             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2783             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
2784
2785     CHECK(compileAndRun<int64_t>(proc, a, b) == (a | b));
2786 }
2787
2788 void testBitOrSameArg(int64_t a)
2789 {
2790     Procedure proc;
2791     BasicBlock* root = proc.addBlock();
2792     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
2793     root->appendNewControlValue(
2794         proc, Return, Origin(),
2795         root->appendNew<Value>(
2796             proc, BitOr, Origin(),
2797             argument,
2798             argument));
2799
2800     CHECK(compileAndRun<int64_t>(proc, a) == a);
2801 }
2802
2803 void testBitOrImms(int64_t a, int64_t b)
2804 {
2805     Procedure proc;
2806     BasicBlock* root = proc.addBlock();
2807     root->appendNewControlValue(
2808         proc, Return, Origin(),
2809         root->appendNew<Value>(
2810             proc, BitOr, Origin(),
2811             root->appendNew<Const64Value>(proc, Origin(), a),
2812             root->appendNew<Const64Value>(proc, Origin(), b)));
2813
2814     CHECK(compileAndRun<int64_t>(proc) == (a | b));
2815 }
2816
2817 void testBitOrArgImm(int64_t a, int64_t b)
2818 {
2819     Procedure proc;
2820     BasicBlock* root = proc.addBlock();
2821     root->appendNewControlValue(
2822         proc, Return, Origin(),
2823         root->appendNew<Value>(
2824             proc, BitOr, Origin(),
2825             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2826             root->appendNew<Const64Value>(proc, Origin(), b)));
2827
2828     CHECK(compileAndRun<int64_t>(proc, a) == (a | b));
2829 }
2830
2831 void testBitOrImmArg(int64_t a, int64_t b)
2832 {
2833     Procedure proc;
2834     BasicBlock* root = proc.addBlock();
2835     root->appendNewControlValue(
2836         proc, Return, Origin(),
2837         root->appendNew<Value>(
2838             proc, BitOr, Origin(),
2839             root->appendNew<Const64Value>(proc, Origin(), a),
2840             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
2841
2842     CHECK(compileAndRun<int64_t>(proc, b) == (a | b));
2843 }
2844
2845 void testBitOrBitOrArgImmImm(int64_t a, int64_t b, int64_t c)
2846 {
2847     Procedure proc;
2848     BasicBlock* root = proc.addBlock();
2849     Value* innerBitOr = root->appendNew<Value>(
2850         proc, BitOr, Origin(),
2851         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2852         root->appendNew<Const64Value>(proc, Origin(), b));
2853     root->appendNewControlValue(
2854         proc, Return, Origin(),
2855         root->appendNew<Value>(
2856             proc, BitOr, Origin(),
2857             innerBitOr,
2858             root->appendNew<Const64Value>(proc, Origin(), c)));
2859
2860     CHECK(compileAndRun<int64_t>(proc, a) == ((a | b) | c));
2861 }
2862
2863 void testBitOrImmBitOrArgImm(int64_t a, int64_t b, int64_t c)
2864 {
2865     Procedure proc;
2866     BasicBlock* root = proc.addBlock();
2867     Value* innerBitOr = root->appendNew<Value>(
2868         proc, BitOr, Origin(),
2869         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
2870         root->appendNew<Const64Value>(proc, Origin(), c));
2871     root->appendNewControlValue(
2872         proc, Return, Origin(),
2873         root->appendNew<Value>(
2874             proc, BitOr, Origin(),
2875             root->appendNew<Const64Value>(proc, Origin(), a),
2876             innerBitOr));
2877
2878     CHECK(compileAndRun<int64_t>(proc, b) == (a | (b | c)));
2879 }
2880
2881 void testBitOrArgs32(int a, int b)
2882 {
2883     Procedure proc;
2884     BasicBlock* root = proc.addBlock();
2885     root->appendNewControlValue(
2886         proc, Return, Origin(),
2887         root->appendNew<Value>(
2888             proc, BitOr, Origin(),
2889             root->appendNew<Value>(
2890                 proc, Trunc, Origin(),
2891                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2892             root->appendNew<Value>(
2893                 proc, Trunc, Origin(),
2894                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
2895
2896     CHECK(compileAndRun<int>(proc, a, b) == (a | b));
2897 }
2898
2899 void testBitOrSameArg32(int a)
2900 {
2901     Procedure proc;
2902     BasicBlock* root = proc.addBlock();
2903     Value* argument = root->appendNew<Value>(
2904         proc, Trunc, Origin(),
2905             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
2906     root->appendNewControlValue(
2907         proc, Return, Origin(),
2908         root->appendNew<Value>(
2909             proc, BitOr, Origin(),
2910             argument,
2911             argument));
2912
2913     CHECK(compileAndRun<int>(proc, a) == a);
2914 }
2915
2916 void testBitOrImms32(int a, int b)
2917 {
2918     Procedure proc;
2919     BasicBlock* root = proc.addBlock();
2920     root->appendNewControlValue(
2921         proc, Return, Origin(),
2922         root->appendNew<Value>(
2923             proc, BitOr, Origin(),
2924             root->appendNew<Const32Value>(proc, Origin(), a),
2925             root->appendNew<Const32Value>(proc, Origin(), b)));
2926
2927     CHECK(compileAndRun<int>(proc) == (a | b));
2928 }
2929
2930 void testBitOrArgImm32(int a, int b)
2931 {
2932     Procedure proc;
2933     BasicBlock* root = proc.addBlock();
2934     root->appendNewControlValue(
2935         proc, Return, Origin(),
2936         root->appendNew<Value>(
2937             proc, BitOr, Origin(),
2938             root->appendNew<Value>(
2939                 proc, Trunc, Origin(),
2940                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2941             root->appendNew<Const32Value>(proc, Origin(), b)));
2942
2943     CHECK(compileAndRun<int>(proc, a) == (a | b));
2944 }
2945
2946 void testBitOrImmArg32(int a, int b)
2947 {
2948     Procedure proc;
2949     BasicBlock* root = proc.addBlock();
2950     root->appendNewControlValue(
2951         proc, Return, Origin(),
2952         root->appendNew<Value>(
2953             proc, BitOr, Origin(),
2954             root->appendNew<Const32Value>(proc, Origin(), a),
2955             root->appendNew<Value>(
2956                 proc, Trunc, Origin(),
2957                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
2958
2959     CHECK(compileAndRun<int>(proc, b) == (a | b));
2960 }
2961
2962 void testBitOrBitOrArgImmImm32(int a, int b, int c)
2963 {
2964     Procedure proc;
2965     BasicBlock* root = proc.addBlock();
2966     Value* innerBitOr = root->appendNew<Value>(
2967         proc, BitOr, Origin(),
2968         root->appendNew<Value>(
2969             proc, Trunc, Origin(),
2970             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2971         root->appendNew<Const32Value>(proc, Origin(), b));
2972     root->appendNewControlValue(
2973         proc, Return, Origin(),
2974         root->appendNew<Value>(
2975             proc, BitOr, Origin(),
2976             innerBitOr,
2977             root->appendNew<Const32Value>(proc, Origin(), c)));
2978
2979     CHECK(compileAndRun<int>(proc, a) == ((a | b) | c));
2980 }
2981
2982 void testBitOrImmBitOrArgImm32(int a, int b, int c)
2983 {
2984     Procedure proc;
2985     BasicBlock* root = proc.addBlock();
2986     Value* innerBitOr = root->appendNew<Value>(
2987         proc, BitOr, Origin(),
2988         root->appendNew<Value>(
2989             proc, Trunc, Origin(),
2990             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
2991         root->appendNew<Const32Value>(proc, Origin(), c));
2992     root->appendNewControlValue(
2993         proc, Return, Origin(),
2994         root->appendNew<Value>(
2995             proc, BitOr, Origin(),
2996             root->appendNew<Const32Value>(proc, Origin(), a),
2997             innerBitOr));
2998
2999     CHECK(compileAndRun<int>(proc, b) == (a | (b | c)));
3000 }
3001
3002 double bitOrDouble(double a, double b)
3003 {
3004     return bitwise_cast<double>(bitwise_cast<uint64_t>(a) | bitwise_cast<uint64_t>(b));
3005 }
3006
3007 void testBitOrArgDouble(double a)
3008 {
3009     Procedure proc;
3010     BasicBlock* root = proc.addBlock();
3011     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3012     Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argument, argument);
3013     root->appendNewControlValue(proc, Return, Origin(), result);
3014
3015     CHECK(isIdentical(compileAndRun<double>(proc, a), bitOrDouble(a, a)));
3016 }
3017
3018 void testBitOrArgsDouble(double a, double b)
3019 {
3020     Procedure proc;
3021     BasicBlock* root = proc.addBlock();
3022     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3023     Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
3024     Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3025     root->appendNewControlValue(proc, Return, Origin(), result);
3026
3027     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b)));
3028 }
3029
3030 void testBitOrArgImmDouble(double a, double b)
3031 {
3032     Procedure proc;
3033     BasicBlock* root = proc.addBlock();
3034     Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
3035     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
3036     Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3037     root->appendNewControlValue(proc, Return, Origin(), result);
3038
3039     CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b)));
3040 }
3041
3042 void testBitOrImmsDouble(double a, double b)
3043 {
3044     Procedure proc;
3045     BasicBlock* root = proc.addBlock();
3046     Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
3047     Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
3048     Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3049     root->appendNewControlValue(proc, Return, Origin(), result);
3050     
3051     CHECK(isIdentical(compileAndRun<double>(proc), bitOrDouble(a, b)));
3052 }
3053
3054 float bitOrFloat(float a, float b)
3055 {
3056     return bitwise_cast<float>(bitwise_cast<uint32_t>(a) | bitwise_cast<uint32_t>(b));
3057 }
3058
3059 void testBitOrArgFloat(float a)
3060 {
3061     Procedure proc;
3062     BasicBlock* root = proc.addBlock();
3063     Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3064         root->appendNew<Value>(proc, Trunc, Origin(),
3065             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3066     Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argument, argument);
3067     root->appendNewControlValue(proc, Return, Origin(), result);
3068
3069     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitOrFloat(a, a)));
3070 }
3071
3072 void testBitOrArgsFloat(float a, float b)
3073 {
3074     Procedure proc;
3075     BasicBlock* root = proc.addBlock();
3076     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3077         root->appendNew<Value>(proc, Trunc, Origin(),
3078             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3079     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3080         root->appendNew<Value>(proc, Trunc, Origin(),
3081             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3082     Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3083     root->appendNewControlValue(proc, Return, Origin(), result);
3084
3085     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b)));
3086 }
3087
3088 void testBitOrArgImmFloat(float a, float b)
3089 {
3090     Procedure proc;
3091     BasicBlock* root = proc.addBlock();
3092     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3093         root->appendNew<Value>(proc, Trunc, Origin(),
3094             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3095     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
3096     Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3097     root->appendNewControlValue(proc, Return, Origin(), result);
3098
3099     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b)));
3100 }
3101
3102 void testBitOrImmsFloat(float a, float b)
3103 {
3104     Procedure proc;
3105     BasicBlock* root = proc.addBlock();
3106     Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
3107     Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
3108     Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argumentA, argumentB);
3109     root->appendNewControlValue(proc, Return, Origin(), result);
3110
3111     CHECK(isIdentical(compileAndRun<float>(proc), bitOrFloat(a, b)));
3112 }
3113
3114 void testBitOrArgsFloatWithUselessDoubleConversion(float a, float b)
3115 {
3116     Procedure proc;
3117     BasicBlock* root = proc.addBlock();
3118     Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3119         root->appendNew<Value>(proc, Trunc, Origin(),
3120             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3121     Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
3122         root->appendNew<Value>(proc, Trunc, Origin(),
3123             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3124     Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
3125     Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
3126     Value* doubleResult = root->appendNew<Value>(proc, BitOr, Origin(), argumentAasDouble, argumentBasDouble);
3127     Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
3128     root->appendNewControlValue(proc, Return, Origin(), floatResult);
3129     
3130     double doubleA = a;
3131     double doubleB = b;
3132     float expected = static_cast<float>(bitOrDouble(doubleA, doubleB));
3133     CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
3134 }
3135
3136 void testBitXorArgs(int64_t a, int64_t b)
3137 {
3138     Procedure proc;
3139     BasicBlock* root = proc.addBlock();
3140     root->appendNewControlValue(
3141         proc, Return, Origin(),
3142         root->appendNew<Value>(
3143             proc, BitXor, Origin(),
3144             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3145             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
3146
3147     CHECK(compileAndRun<int64_t>(proc, a, b) == (a ^ b));
3148 }
3149
3150 void testBitXorSameArg(int64_t a)
3151 {
3152     Procedure proc;
3153     BasicBlock* root = proc.addBlock();
3154     Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3155     root->appendNewControlValue(
3156         proc, Return, Origin(),
3157         root->appendNew<Value>(
3158             proc, BitXor, Origin(),
3159             argument,
3160             argument));
3161
3162     CHECK(!compileAndRun<int64_t>(proc, a));
3163 }
3164
3165 void testBitXorImms(int64_t a, int64_t b)
3166 {
3167     Procedure proc;
3168     BasicBlock* root = proc.addBlock();
3169     root->appendNewControlValue(
3170         proc, Return, Origin(),
3171         root->appendNew<Value>(
3172             proc, BitXor, Origin(),
3173             root->appendNew<Const64Value>(proc, Origin(), a),
3174             root->appendNew<Const64Value>(proc, Origin(), b)));
3175
3176     CHECK(compileAndRun<int64_t>(proc) == (a ^ b));
3177 }
3178
3179 void testBitXorArgImm(int64_t a, int64_t b)
3180 {
3181     Procedure proc;
3182     BasicBlock* root = proc.addBlock();
3183     root->appendNewControlValue(
3184         proc, Return, Origin(),
3185         root->appendNew<Value>(
3186             proc, BitXor, Origin(),
3187             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3188             root->appendNew<Const64Value>(proc, Origin(), b)));
3189
3190     CHECK(compileAndRun<int64_t>(proc, a) == (a ^ b));
3191 }
3192
3193 void testBitXorImmArg(int64_t a, int64_t b)
3194 {
3195     Procedure proc;
3196     BasicBlock* root = proc.addBlock();
3197     root->appendNewControlValue(
3198         proc, Return, Origin(),
3199         root->appendNew<Value>(
3200             proc, BitXor, Origin(),
3201             root->appendNew<Const64Value>(proc, Origin(), a),
3202             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3203
3204     CHECK(compileAndRun<int64_t>(proc, b) == (a ^ b));
3205 }
3206
3207 void testBitXorBitXorArgImmImm(int64_t a, int64_t b, int64_t c)
3208 {
3209     Procedure proc;
3210     BasicBlock* root = proc.addBlock();
3211     Value* innerBitXor = root->appendNew<Value>(
3212         proc, BitXor, Origin(),
3213         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3214         root->appendNew<Const64Value>(proc, Origin(), b));
3215     root->appendNewControlValue(
3216         proc, Return, Origin(),
3217         root->appendNew<Value>(
3218             proc, BitXor, Origin(),
3219             innerBitXor,
3220             root->appendNew<Const64Value>(proc, Origin(), c)));
3221
3222     CHECK(compileAndRun<int64_t>(proc, a) == ((a ^ b) ^ c));
3223 }
3224
3225 void testBitXorImmBitXorArgImm(int64_t a, int64_t b, int64_t c)
3226 {
3227     Procedure proc;
3228     BasicBlock* root = proc.addBlock();
3229     Value* innerBitXor = root->appendNew<Value>(
3230         proc, BitXor, Origin(),
3231         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
3232         root->appendNew<Const64Value>(proc, Origin(), c));
3233     root->appendNewControlValue(
3234         proc, Return, Origin(),
3235         root->appendNew<Value>(
3236             proc, BitXor, Origin(),
3237             root->appendNew<Const64Value>(proc, Origin(), a),
3238             innerBitXor));
3239
3240     CHECK(compileAndRun<int64_t>(proc, b) == (a ^ (b ^ c)));
3241 }
3242
3243 void testBitXorArgs32(int a, int b)
3244 {
3245     Procedure proc;
3246     BasicBlock* root = proc.addBlock();
3247     root->appendNewControlValue(
3248         proc, Return, Origin(),
3249         root->appendNew<Value>(
3250             proc, BitXor, Origin(),
3251             root->appendNew<Value>(
3252                 proc, Trunc, Origin(),
3253                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3254             root->appendNew<Value>(
3255                 proc, Trunc, Origin(),
3256                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))));
3257
3258     CHECK(compileAndRun<int>(proc, a, b) == (a ^ b));
3259 }
3260
3261 void testBitXorSameArg32(int a)
3262 {
3263     Procedure proc;
3264     BasicBlock* root = proc.addBlock();
3265     Value* argument = root->appendNew<Value>(
3266         proc, Trunc, Origin(),
3267             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3268     root->appendNewControlValue(
3269         proc, Return, Origin(),
3270         root->appendNew<Value>(
3271             proc, BitXor, Origin(),
3272             argument,
3273             argument));
3274
3275     CHECK(!compileAndRun<int>(proc, a));
3276 }
3277
3278 void testBitXorImms32(int a, int b)
3279 {
3280     Procedure proc;
3281     BasicBlock* root = proc.addBlock();
3282     root->appendNewControlValue(
3283         proc, Return, Origin(),
3284         root->appendNew<Value>(
3285             proc, BitXor, Origin(),
3286             root->appendNew<Const32Value>(proc, Origin(), a),
3287             root->appendNew<Const32Value>(proc, Origin(), b)));
3288
3289     CHECK(compileAndRun<int>(proc) == (a ^ b));
3290 }
3291
3292 void testBitXorArgImm32(int a, int b)
3293 {
3294     Procedure proc;
3295     BasicBlock* root = proc.addBlock();
3296     root->appendNewControlValue(
3297         proc, Return, Origin(),
3298         root->appendNew<Value>(
3299             proc, BitXor, Origin(),
3300             root->appendNew<Value>(
3301                 proc, Trunc, Origin(),
3302                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3303             root->appendNew<Const32Value>(proc, Origin(), b)));
3304
3305     CHECK(compileAndRun<int>(proc, a) == (a ^ b));
3306 }
3307
3308 void testBitXorImmArg32(int a, int b)
3309 {
3310     Procedure proc;
3311     BasicBlock* root = proc.addBlock();
3312     root->appendNewControlValue(
3313         proc, Return, Origin(),
3314         root->appendNew<Value>(
3315             proc, BitXor, Origin(),
3316             root->appendNew<Const32Value>(proc, Origin(), a),
3317             root->appendNew<Value>(
3318                 proc, Trunc, Origin(),
3319                 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))));
3320
3321     CHECK(compileAndRun<int>(proc, b) == (a ^ b));
3322 }
3323
3324 void testBitXorBitXorArgImmImm32(int a, int b, int c)
3325 {
3326     Procedure proc;
3327     BasicBlock* root = proc.addBlock();
3328     Value* innerBitXor = root->appendNew<Value>(
3329         proc, BitXor, Origin(),
3330         root->appendNew<Value>(
3331             proc, Trunc, Origin(),
3332             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3333         root->appendNew<Const32Value>(proc, Origin(), b));
3334     root->appendNewControlValue(
3335         proc, Return, Origin(),
3336         root->appendNew<Value>(
3337             proc, BitXor, Origin(),
3338             innerBitXor,
3339             root->appendNew<Const32Value>(proc, Origin(), c)));
3340
3341     CHECK(compileAndRun<int>(proc, a) == ((a ^ b) ^ c));
3342 }
3343
3344 void testBitXorImmBitXorArgImm32(int a, int b, int c)
3345 {
3346     Procedure proc;
3347     BasicBlock* root = proc.addBlock();
3348     Value* innerBitXor = root->appendNew<Value>(
3349         proc, BitXor, Origin(),
3350         root->appendNew<Value>(
3351             proc, Trunc, Origin(),
3352             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
3353         root->appendNew<Const32Value>(proc, Origin(), c));
3354     root->appendNewControlValue(
3355         proc, Return, Origin(),
3356         root->appendNew<Value>(
3357             proc, BitXor, Origin(),
3358             root->appendNew<Const32Value>(proc, Origin(), a),
3359             innerBitXor));
3360
3361     CHECK(compileAndRun<int>(proc, b) == (a ^ (b ^ c)));
3362 }
3363
3364 void testBitNotArg(int64_t a)
3365 {
3366     Procedure proc;
3367     BasicBlock* root = proc.addBlock();
3368     root->appendNewControlValue(
3369         proc, Return, Origin(),
3370         root->appendNew<Value>(
3371             proc, BitXor, Origin(),
3372             root->appendNew<Const64Value>(proc, Origin(), -1),
3373             root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
3374
3375     CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3376 }
3377
3378 void testBitNotImm(int64_t a)
3379 {
3380     Procedure proc;
3381     BasicBlock* root = proc.addBlock();
3382     root->appendNewControlValue(
3383         proc, Return, Origin(),
3384         root->appendNew<Value>(
3385             proc, BitXor, Origin(),
3386             root->appendNew<Const64Value>(proc, Origin(), -1),
3387             root->appendNew<Const64Value>(proc, Origin(), a)));
3388
3389     CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3390 }
3391
3392 void testBitNotMem(int64_t a)
3393 {
3394     Procedure proc;
3395     BasicBlock* root = proc.addBlock();
3396     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3397     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
3398     Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
3399         root->appendNew<Const64Value>(proc, Origin(), -1),
3400         load);
3401     root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
3402     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3403
3404     int64_t input = a;
3405     compileAndRun<int32_t>(proc, &input);
3406     CHECK(isIdentical(input, static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff))));
3407 }
3408
3409 void testBitNotArg32(int32_t a)
3410 {
3411     Procedure proc;
3412     BasicBlock* root = proc.addBlock();
3413     Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
3414         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3415     root->appendNewControlValue(
3416         proc, Return, Origin(),
3417         root->appendNew<Value>(proc, BitXor, Origin(),
3418             root->appendNew<Const32Value>(proc, Origin(), -1),
3419             argument));
3420     CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3421 }
3422
3423 void testBitNotImm32(int32_t a)
3424 {
3425     Procedure proc;
3426     BasicBlock* root = proc.addBlock();
3427     root->appendNewControlValue(
3428         proc, Return, Origin(),
3429         root->appendNew<Value>(
3430             proc, BitXor, Origin(),
3431             root->appendNew<Const32Value>(proc, Origin(), -1),
3432             root->appendNew<Const32Value>(proc, Origin(), a)));
3433
3434     CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3435 }
3436
3437 void testBitNotMem32(int32_t a)
3438 {
3439     Procedure proc;
3440     BasicBlock* root = proc.addBlock();
3441     Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
3442     MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
3443     Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(),
3444         root->appendNew<Const32Value>(proc, Origin(), -1),
3445         load);
3446     root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address);
3447     root->appendNewControlValue(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
3448
3449     int32_t input = a;
3450     compileAndRun<int32_t>(proc, &input);
3451     CHECK(isIdentical(input, static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff))));
3452 }
3453
3454 void testBitNotOnBooleanAndBranch32(int64_t a, int64_t b)
3455 {
3456     Procedure proc;
3457     BasicBlock* root = proc.addBlock();
3458     BasicBlock* thenCase = proc.addBlock();
3459     BasicBlock* elseCase = proc.addBlock();
3460
3461     Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
3462         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
3463     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
3464         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
3465     Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2);
3466     Value* argsAreNotEqual = root->appendNew<Value>(proc, BitXor, Origin(),
3467         root->appendNew<Const32Value>(proc, Origin(), -1),
3468         argsAreEqual);
3469
3470     root->appendNewControlValue(
3471         proc, Branch, Origin(),
3472         argsAreNotEqual,
3473         FrequentedBlock(thenCase), FrequentedBlock(elseCase));
3474
3475     thenCase->appendNewControlValue(