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