diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/b3/testb3.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/b3/testb3.cpp')
-rw-r--r-- | Source/JavaScriptCore/b3/testb3.cpp | 12845 |
1 files changed, 0 insertions, 12845 deletions
diff --git a/Source/JavaScriptCore/b3/testb3.cpp b/Source/JavaScriptCore/b3/testb3.cpp deleted file mode 100644 index c9313cb03..000000000 --- a/Source/JavaScriptCore/b3/testb3.cpp +++ /dev/null @@ -1,12845 +0,0 @@ -/* - * Copyright (C) 2015-2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "AllowMacroScratchRegisterUsage.h" -#include "B3ArgumentRegValue.h" -#include "B3BasicBlockInlines.h" -#include "B3CCallValue.h" -#include "B3Compilation.h" -#include "B3ComputeDivisionMagic.h" -#include "B3Const32Value.h" -#include "B3ConstPtrValue.h" -#include "B3ControlValue.h" -#include "B3Effects.h" -#include "B3MathExtras.h" -#include "B3MemoryValue.h" -#include "B3Procedure.h" -#include "B3SlotBaseValue.h" -#include "B3StackSlot.h" -#include "B3StackmapGenerationParams.h" -#include "B3SwitchValue.h" -#include "B3UpsilonValue.h" -#include "B3ValueInlines.h" -#include "CCallHelpers.h" -#include "InitializeThreading.h" -#include "JSCInlines.h" -#include "LinkBuffer.h" -#include "PureNaN.h" -#include "VM.h" -#include <cmath> -#include <string> -#include <wtf/Lock.h> -#include <wtf/NumberOfCores.h> -#include <wtf/Threading.h> - -// We don't have a NO_RETURN_DUE_TO_EXIT, nor should we. That's ridiculous. -static bool hiddenTruthBecauseNoReturnIsStupid() { return true; } - -static void usage() -{ - dataLog("Usage: testb3 [<filter>]\n"); - if (hiddenTruthBecauseNoReturnIsStupid()) - exit(1); -} - -#if ENABLE(B3_JIT) - -using namespace JSC; -using namespace JSC::B3; - -namespace { - -StaticLock crashLock; - -// Nothing fancy for now; we just use the existing WTF assertion machinery. -#define CHECK(x) do { \ - if (!!(x)) \ - break; \ - crashLock.lock(); \ - WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #x); \ - CRASH(); \ - } while (false) - -VM* vm; - -std::unique_ptr<Compilation> compile(Procedure& procedure, unsigned optLevel = 1) -{ - return std::make_unique<Compilation>(*vm, procedure, optLevel); -} - -template<typename T, typename... Arguments> -T invoke(const Compilation& code, Arguments... arguments) -{ - T (*function)(Arguments...) = bitwise_cast<T(*)(Arguments...)>(code.code().executableAddress()); - return function(arguments...); -} - -template<typename T, typename... Arguments> -T compileAndRun(Procedure& procedure, Arguments... arguments) -{ - return invoke<T>(*compile(procedure), arguments...); -} - -template<typename Type> -struct Operand { - const char* name; - Type value; -}; - -typedef Operand<int64_t> Int64Operand; -typedef Operand<int32_t> Int32Operand; - -template<typename FloatType> -void populateWithInterestingValues(Vector<Operand<FloatType>>& operands) -{ - operands.append({ "0.", static_cast<FloatType>(0.) }); - operands.append({ "-0.", static_cast<FloatType>(-0.) }); - operands.append({ "0.4", static_cast<FloatType>(0.5) }); - operands.append({ "-0.4", static_cast<FloatType>(-0.5) }); - operands.append({ "0.5", static_cast<FloatType>(0.5) }); - operands.append({ "-0.5", static_cast<FloatType>(-0.5) }); - operands.append({ "0.6", static_cast<FloatType>(0.5) }); - operands.append({ "-0.6", static_cast<FloatType>(-0.5) }); - operands.append({ "1.", static_cast<FloatType>(1.) }); - operands.append({ "-1.", static_cast<FloatType>(-1.) }); - operands.append({ "2.", static_cast<FloatType>(2.) }); - operands.append({ "-2.", static_cast<FloatType>(-2.) }); - operands.append({ "M_PI", static_cast<FloatType>(M_PI) }); - operands.append({ "-M_PI", static_cast<FloatType>(-M_PI) }); - operands.append({ "min", std::numeric_limits<FloatType>::min() }); - operands.append({ "max", std::numeric_limits<FloatType>::max() }); - operands.append({ "lowest", std::numeric_limits<FloatType>::lowest() }); - operands.append({ "epsilon", std::numeric_limits<FloatType>::epsilon() }); - operands.append({ "infiniti", std::numeric_limits<FloatType>::infinity() }); - operands.append({ "-infiniti", - std::numeric_limits<FloatType>::infinity() }); - operands.append({ "PNaN", static_cast<FloatType>(PNaN) }); -} - -template<typename FloatType> -Vector<Operand<FloatType>> floatingPointOperands() -{ - Vector<Operand<FloatType>> operands; - populateWithInterestingValues(operands); - return operands; -}; - -static Vector<Int64Operand> int64Operands() -{ - Vector<Int64Operand> operands; - operands.append({ "1", 1 }); - operands.append({ "-1", -1 }); - operands.append({ "42", 42 }); - operands.append({ "-42", -42 }); - operands.append({ "int64-max", std::numeric_limits<int64_t>::max() }); - operands.append({ "int64-min", std::numeric_limits<int64_t>::min() }); - operands.append({ "int32-max", std::numeric_limits<int32_t>::max() }); - operands.append({ "int32-min", std::numeric_limits<int32_t>::min() }); - - return operands; -} - -static Vector<Int32Operand> int32Operands() -{ - Vector<Int32Operand> operands({ - { "0", 0 }, - { "1", 1 }, - { "-1", -1 }, - { "42", 42 }, - { "-42", -42 }, - { "int32-max", std::numeric_limits<int32_t>::max() }, - { "int32-min", std::numeric_limits<int32_t>::min() } - }); - return operands; -} - -void add32(CCallHelpers& jit, GPRReg src1, GPRReg src2, GPRReg dest) -{ - if (src2 == dest) - jit.add32(src1, dest); - else { - jit.move(src1, dest); - jit.add32(src2, dest); - } -} - -void test42() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* const42 = root->appendNew<Const32Value>(proc, Origin(), 42); - root->appendNew<ControlValue>(proc, Return, Origin(), const42); - - CHECK(compileAndRun<int>(proc) == 42); -} - -void testLoad42() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int x = 42; - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &x))); - - CHECK(compileAndRun<int>(proc) == 42); -} - -void testLoadWithOffsetImpl(int32_t offset64, int32_t offset32) -{ - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - int64_t x = -42; - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, Load, Int64, Origin(), - base, - offset64)); - - char* address = reinterpret_cast<char*>(&x) - offset64; - CHECK(compileAndRun<int64_t>(proc, address) == -42); - } - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - int32_t x = -42; - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - base, - offset32)); - - char* address = reinterpret_cast<char*>(&x) - offset32; - CHECK(compileAndRun<int32_t>(proc, address) == -42); - } -} - -void testLoadOffsetImm9Max() -{ - testLoadWithOffsetImpl(255, 255); -} - -void testLoadOffsetImm9MaxPlusOne() -{ - testLoadWithOffsetImpl(256, 256); -} - -void testLoadOffsetImm9MaxPlusTwo() -{ - testLoadWithOffsetImpl(257, 257); -} - -void testLoadOffsetImm9Min() -{ - testLoadWithOffsetImpl(-256, -256); -} - -void testLoadOffsetImm9MinMinusOne() -{ - testLoadWithOffsetImpl(-257, -257); -} - -void testLoadOffsetScaledUnsignedImm12Max() -{ - testLoadWithOffsetImpl(32760, 16380); -} - -void testLoadOffsetScaledUnsignedOverImm12Max() -{ - testLoadWithOffsetImpl(32760, 32760); - testLoadWithOffsetImpl(32761, 16381); - testLoadWithOffsetImpl(32768, 16384); -} - -void testArg(int argument) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - - CHECK(compileAndRun<int>(proc, argument) == argument); -} - -void testReturnConst64(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const64Value>(proc, Origin(), value)); - - CHECK(compileAndRun<int64_t>(proc) == value); -} - -void testAddArg(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Add, Origin(), value, value)); - - CHECK(compileAndRun<int>(proc, a) == a + a); -} - -void testAddArgs(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int>(proc, a, b) == a + b); -} - -void testAddArgImm(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int>(proc, a) == a + b); -} - -void testAddImmArg(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(compileAndRun<int>(proc, b) == a + b); -} - -void testAddArgMem(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* result = root->appendNew<Value>(proc, Add, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - load); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int64_t inputOutput = b; - CHECK(!compileAndRun<int64_t>(proc, a, &inputOutput)); - CHECK(inputOutput == a + b); -} - -void testAddMemArg(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* result = root->appendNew<Value>(proc, Add, Origin(), - load, - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int64_t>(proc, &a, b) == a + b); -} - -void testAddImmMem(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* result = root->appendNew<Value>(proc, Add, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - load); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int64_t inputOutput = b; - CHECK(!compileAndRun<int>(proc, &inputOutput)); - CHECK(inputOutput == a + b); -} - -void testAddArg32(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Add, Origin(), value, value)); - - CHECK(compileAndRun<int>(proc, a) == a + a); -} - -void testAddArgs32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int>(proc, a, b) == a + b); -} - -void testAddArgMem32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* result = root->appendNew<Value>(proc, Add, Origin(), argument, load); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int32_t inputOutput = b; - CHECK(!compileAndRun<int32_t>(proc, a, &inputOutput)); - CHECK(inputOutput == a + b); -} - -void testAddMemArg32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* result = root->appendNew<Value>(proc, Add, Origin(), load, argument); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int32_t>(proc, &a, b) == a + b); -} - -void testAddImmMem32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* result = root->appendNew<Value>(proc, Add, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - load); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int32_t inputOutput = b; - CHECK(!compileAndRun<int>(proc, &inputOutput)); - CHECK(inputOutput == a + b); -} - -void testAddArgZeroImmZDef() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* constZero = root->appendNew<Const32Value>(proc, Origin(), 0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - arg, - constZero)); - - auto code = compile(proc, 0); - CHECK(invoke<int64_t>(*code, 0x0123456789abcdef) == 0x89abcdef); -} - -void testAddLoadTwice() -{ - auto test = [&] (unsigned optLevel) { - Procedure proc; - BasicBlock* root = proc.addBlock(); - int32_t value = 42; - Value* load = root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &value)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Add, Origin(), load, load)); - - auto code = compile(proc, optLevel); - CHECK(invoke<int32_t>(*code) == 42 * 2); - }; - - test(0); - test(1); -} - -void testAddArgDouble(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Add, Origin(), value, value)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), a + a)); -} - -void testAddArgsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Add, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a, b), a + b)); -} - -void testAddArgImmDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Add, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), a + b)); -} - -void testAddImmArgDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Add, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, b), a + b)); -} - -void testAddImmsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Add, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc), a + b)); -} - -void testAddArgFloat(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + a))); -} - -void testAddArgsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue1, floatValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b))); -} - -void testAddArgImmFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Add, Origin(), floatValue, constValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + b))); -} - -void testAddImmArgFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Add, Origin(), constValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b))); -} - -void testAddImmsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Add, Origin(), constValue1, constValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a + b))); -} - -void testAddArgFloatWithUselessDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble, asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a + a))); -} - -void testAddArgsFloatWithUselessDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble1, asDouble2); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a + b))); -} - -void testAddArgsFloatWithEffectfulDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - Value* result = root->appendNew<Value>(proc, Add, Origin(), asDouble1, asDouble2); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - double effect = 0; - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a + b))); - CHECK(isIdentical(effect, static_cast<double>(a) + static_cast<double>(b))); -} - -void testMulArg(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<Value>( - proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mul, Origin(), value, value)); - - CHECK(compileAndRun<int>(proc, a) == a * a); -} - -void testMulArgStore(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - int mulSlot; - int valueSlot; - - Value* value = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* mul = root->appendNew<Value>(proc, Mul, Origin(), value, value); - - root->appendNew<MemoryValue>( - proc, Store, Origin(), value, - root->appendNew<ConstPtrValue>(proc, Origin(), &valueSlot)); - root->appendNew<MemoryValue>( - proc, Store, Origin(), mul, - root->appendNew<ConstPtrValue>(proc, Origin(), &mulSlot)); - - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, a)); - CHECK(mulSlot == a * a); - CHECK(valueSlot == a); -} - -void testMulAddArg(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>(proc, Mul, Origin(), value, value), - value)); - - CHECK(compileAndRun<int>(proc, a) == a * a + a); -} - -void testMulArgs(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Mul, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int>(proc, a, b) == a * b); -} - -void testMulArgImm(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Mul, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc, a) == a * b); -} - -void testMulImmArg(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Mul, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(compileAndRun<int>(proc, b) == a * b); -} - -void testMulArgs32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Mul, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int>(proc, a, b) == a * b); -} - -void testMulLoadTwice() -{ - auto test = [&] (unsigned optLevel) { - Procedure proc; - BasicBlock* root = proc.addBlock(); - int32_t value = 42; - Value* load = root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &value)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mul, Origin(), load, load)); - - auto code = compile(proc, optLevel); - CHECK(invoke<int32_t>(*code) == 42 * 42); - }; - - test(0); - test(1); -} - -void testMulAddArgsLeft() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1); - Value* added = root->appendNew<Value>(proc, Add, Origin(), multiplied, arg2); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int64Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - for (auto c : testValues) { - CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value); - } - } - } -} - -void testMulAddArgsRight() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2); - Value* added = root->appendNew<Value>(proc, Add, Origin(), arg0, multiplied); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int64Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - for (auto c : testValues) { - CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value); - } - } - } -} - -void testMulAddArgsLeft32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1); - Value* added = root->appendNew<Value>(proc, Add, Origin(), multiplied, arg2); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int32Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - for (auto c : testValues) { - CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value); - } - } - } -} - -void testMulAddArgsRight32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2); - Value* added = root->appendNew<Value>(proc, Add, Origin(), arg0, multiplied); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int32Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - for (auto c : testValues) { - CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value); - } - } - } -} - -void testMulSubArgsLeft() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1); - Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int64Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - for (auto c : testValues) { - CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value); - } - } - } -} - -void testMulSubArgsRight() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2); - Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int64Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - for (auto c : testValues) { - CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value); - } - } - } -} - -void testMulSubArgsLeft32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1); - Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int32Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - for (auto c : testValues) { - CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value); - } - } - } -} - -void testMulSubArgsRight32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2); - Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int32Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - for (auto c : testValues) { - CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value); - } - } - } -} - -void testMulNegArgs() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1); - Value* zero = root->appendNew<Const64Value>(proc, Origin(), 0); - Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int64Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - CHECK(invoke<int64_t>(*code, a.value, b.value) == -(a.value * b.value)); - } - } -} - -void testMulNegArgs32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1); - Value* zero = root->appendNew<Const32Value>(proc, Origin(), 0); - Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied); - root->appendNew<ControlValue>(proc, Return, Origin(), added); - - auto code = compile(proc); - - auto testValues = int32Operands(); - for (auto a : testValues) { - for (auto b : testValues) { - CHECK(invoke<int32_t>(*code, a.value, b.value) == -(a.value * b.value)); - } - } -} - -void testMulArgDouble(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mul, Origin(), value, value)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), a * a)); -} - -void testMulArgsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a, b), a * b)); -} - -void testMulArgImmDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), a * b)); -} - -void testMulImmArgDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, b), a * b)); -} - -void testMulImmsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mul, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc), a * b)); -} - -void testMulArgFloat(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * a))); -} - -void testMulArgsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue1, floatValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b))); -} - -void testMulArgImmFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Mul, Origin(), floatValue, constValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * b))); -} - -void testMulImmArgFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Mul, Origin(), constValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b))); -} - -void testMulImmsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Mul, Origin(), constValue1, constValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a * b))); -} - -void testMulArgFloatWithUselessDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble, asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a * a))); -} - -void testMulArgsFloatWithUselessDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble1, asDouble2); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a * b))); -} - -void testMulArgsFloatWithEffectfulDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - Value* result = root->appendNew<Value>(proc, Mul, Origin(), asDouble1, asDouble2); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* doubleMulress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleMulress); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - double effect = 0; - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a * b))); - CHECK(isIdentical(effect, static_cast<double>(a) * static_cast<double>(b))); -} - -void testDivArgDouble(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Div, Origin(), value, value)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), a / a)); -} - -void testDivArgsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Div, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a, b), a / b)); -} - -void testDivArgImmDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Div, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), a / b)); -} - -void testDivImmArgDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Div, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, b), a / b)); -} - -void testDivImmsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Div, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc), a / b)); -} - -void testDivArgFloat(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a))); -} - -void testDivArgsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue1, floatValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b))); -} - -void testDivArgImmFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Div, Origin(), floatValue, constValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / b))); -} - -void testDivImmArgFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Div, Origin(), constValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b))); -} - -void testDivImmsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Div, Origin(), constValue1, constValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a / b))); -} - -void testModArgDouble(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mod, Origin(), value, value)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, a))); -} - -void testModArgsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a, b), fmod(a, b))); -} - -void testModArgImmDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, b))); -} - -void testModImmArgDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, b), fmod(a, b))); -} - -void testModImmsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc), fmod(a, b))); -} - -void testModArgFloat(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, a))))); -} - -void testModArgsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue1, floatValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - 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))))); -} - -void testModArgImmFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, constValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b))))); -} - -void testModImmArgFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b))))); -} - -void testModImmsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue1, constValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b))))); -} - -void testDivArgFloatWithUselessDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble, asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a / a))); -} - -void testDivArgsFloatWithUselessDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a / b))); -} - -void testDivArgsFloatWithEffectfulDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - Value* result = root->appendNew<Value>(proc, Div, Origin(), asDouble1, asDouble2); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* doubleDivress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleDivress); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - double effect = 0; - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a / b))); - CHECK(isIdentical(effect, static_cast<double>(a) / static_cast<double>(b))); -} - -void testSubArg(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Sub, Origin(), value, value)); - - CHECK(!compileAndRun<int>(proc, a)); -} - -void testSubArgs(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int>(proc, a, b) == a - b); -} - -void testSubArgImm(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc, a) == a - b); -} - -void testNegValueSubOne(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(), - root->appendNew<Const64Value>(proc, Origin(), 0), - argument); - Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(), - negArgument, - root->appendNew<Const64Value>(proc, Origin(), 1)); - root->appendNew<ControlValue>(proc, Return, Origin(), negArgumentMinusOne); - CHECK(compileAndRun<int>(proc, a) == -a - 1); -} - -void testSubImmArg(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(compileAndRun<int>(proc, b) == a - b); -} - -void testSubArgMem(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - load); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int64_t>(proc, a, &b) == a - b); -} - -void testSubMemArg(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), - load, - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int64_t inputOutput = a; - CHECK(!compileAndRun<int64_t>(proc, &inputOutput, b)); - CHECK(inputOutput == a - b); -} - -void testSubImmMem(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - load); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int64_t inputOutput = b; - CHECK(!compileAndRun<int>(proc, &inputOutput)); - CHECK(inputOutput == a - b); -} - -void testSubMemImm(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), - load, - root->appendNew<Const64Value>(proc, Origin(), b)); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int64_t inputOutput = a; - CHECK(!compileAndRun<int>(proc, &inputOutput)); - CHECK(inputOutput == a - b); -} - - -void testSubArgs32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int>(proc, a, b) == a - b); -} - -void testSubArgImm32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int>(proc, a) == a - b); -} - -void testSubImmArg32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int>(proc, b) == a - b); -} - -void testSubMemArg32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), load, argument); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int32_t inputOutput = a; - CHECK(!compileAndRun<int32_t>(proc, &inputOutput, b)); - CHECK(inputOutput == a - b); -} - -void testSubArgMem32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), argument, load); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int32_t>(proc, a, &b) == a - b); -} - -void testSubImmMem32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - load); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int32_t inputOutput = b; - CHECK(!compileAndRun<int>(proc, &inputOutput)); - CHECK(inputOutput == a - b); -} - -void testSubMemImm32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), - load, - root->appendNew<Const32Value>(proc, Origin(), b)); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int32_t inputOutput = a; - CHECK(!compileAndRun<int>(proc, &inputOutput)); - CHECK(inputOutput == a - b); -} - -void testNegValueSubOne32(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* negArgument = root->appendNew<Value>(proc, Sub, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0), - argument); - Value* negArgumentMinusOne = root->appendNew<Value>(proc, Sub, Origin(), - negArgument, - root->appendNew<Const32Value>(proc, Origin(), 1)); - root->appendNew<ControlValue>(proc, Return, Origin(), negArgumentMinusOne); - CHECK(compileAndRun<int>(proc, a) == -a - 1); -} - -void testSubArgDouble(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Sub, Origin(), value, value)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), a - a)); -} - -void testSubArgsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a, b), a - b)); -} - -void testSubArgImmDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), a - b)); -} - -void testSubImmArgDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc, b), a - b)); -} - -void testSubImmsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Sub, Origin(), valueA, valueB)); - - CHECK(isIdentical(compileAndRun<double>(proc), a - b)); -} - -void testSubArgFloat(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a))); -} - -void testSubArgsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue1, floatValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b))); -} - -void testSubArgImmFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), floatValue, constValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - b))); -} - -void testSubImmArgFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue, floatValue); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b))); -} - -void testSubImmsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), constValue1, constValue2); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a - b))); -} - -void testSubArgFloatWithUselessDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentInt32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentInt32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble, asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(a - a))); -} - -void testSubArgsFloatWithUselessDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(a - b))); -} - -void testSubArgsFloatWithEffectfulDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* asDouble1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* asDouble2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), asDouble1, asDouble2); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* doubleSubress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleSubress); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - double effect = 0; - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), &effect), bitwise_cast<int32_t>(a - b))); - CHECK(isIdentical(effect, static_cast<double>(a) - static_cast<double>(b))); -} - -void testBitAndArgs(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int64_t>(proc, a, b) == (a & b)); -} - -void testBitAndSameArg(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - argument, - argument)); - - CHECK(compileAndRun<int64_t>(proc, a) == a); -} - -void testBitAndImms(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc) == (a & b)); -} - -void testBitAndArgImm(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc, a) == (a & b)); -} - -void testBitAndImmArg(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(compileAndRun<int64_t>(proc, b) == (a & b)); -} - -void testBitAndBitAndArgImmImm(int64_t a, int64_t b, int64_t c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitAnd = root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - innerBitAnd, - root->appendNew<Const64Value>(proc, Origin(), c))); - - CHECK(compileAndRun<int64_t>(proc, a) == ((a & b) & c)); -} - -void testBitAndImmBitAndArgImm(int64_t a, int64_t b, int64_t c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitAnd = root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), c)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - innerBitAnd)); - - CHECK(compileAndRun<int64_t>(proc, b) == (a & (b & c))); -} - -void testBitAndArgs32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int>(proc, a, b) == (a & b)); -} - -void testBitAndSameArg32(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - argument, - argument)); - - CHECK(compileAndRun<int>(proc, a) == a); -} - -void testBitAndImms32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int>(proc) == (a & b)); -} - -void testBitAndArgImm32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int>(proc, a) == (a & b)); -} - -void testBitAndImmArg32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int>(proc, b) == (a & b)); -} - -void testBitAndBitAndArgImmImm32(int a, int b, int c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitAnd = root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - innerBitAnd, - root->appendNew<Const32Value>(proc, Origin(), c))); - - CHECK(compileAndRun<int>(proc, a) == ((a & b) & c)); -} - -void testBitAndImmBitAndArgImm32(int a, int b, int c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitAnd = root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), c)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - innerBitAnd)); - - CHECK(compileAndRun<int>(proc, b) == (a & (b & c))); -} - -void testBitAndWithMaskReturnsBooleans(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg0, arg1); - Value* maskedEqual = root->appendNew<Value>(proc, BitAnd, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0x5), - equal); - Value* inverted = root->appendNew<Value>(proc, BitXor, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0x1), - maskedEqual); - Value* select = root->appendNew<Value>(proc, Select, Origin(), inverted, - root->appendNew<Const64Value>(proc, Origin(), 42), - root->appendNew<Const64Value>(proc, Origin(), -5)); - - root->appendNew<ControlValue>(proc, Return, Origin(), select); - - int64_t expected = (a == b) ? -5 : 42; - CHECK(compileAndRun<int64_t>(proc, a, b) == expected); -} - -double bitAndDouble(double a, double b) -{ - return bitwise_cast<double>(bitwise_cast<uint64_t>(a) & bitwise_cast<uint64_t>(b)); -} - -void testBitAndArgDouble(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(isIdentical(compileAndRun<double>(proc, a), bitAndDouble(a, a))); -} - -void testBitAndArgsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b))); -} - -void testBitAndArgImmDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b))); -} - -void testBitAndImmsDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(isIdentical(compileAndRun<double>(proc), bitAndDouble(a, b))); -} - -float bitAndFloat(float a, float b) -{ - return bitwise_cast<float>(bitwise_cast<uint32_t>(a) & bitwise_cast<uint32_t>(b)); -} - -void testBitAndArgFloat(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitAndFloat(a, a))); -} - -void testBitAndArgsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b))); -} - -void testBitAndArgImmFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b))); -} - -void testBitAndImmsFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b); - Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(isIdentical(compileAndRun<float>(proc), bitAndFloat(a, b))); -} - -void testBitAndArgsFloatWithUselessDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA); - Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB); - Value* doubleResult = root->appendNew<Value>(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult); - root->appendNew<ControlValue>(proc, Return, Origin(), floatResult); - - double doubleA = a; - double doubleB = b; - float expected = static_cast<float>(bitAndDouble(doubleA, doubleB)); - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected)); -} - -void testBitOrArgs(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int64_t>(proc, a, b) == (a | b)); -} - -void testBitOrSameArg(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - argument, - argument)); - - CHECK(compileAndRun<int64_t>(proc, a) == a); -} - -void testBitOrImms(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc) == (a | b)); -} - -void testBitOrArgImm(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc, a) == (a | b)); -} - -void testBitOrImmArg(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(compileAndRun<int64_t>(proc, b) == (a | b)); -} - -void testBitOrBitOrArgImmImm(int64_t a, int64_t b, int64_t c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitOr = root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - innerBitOr, - root->appendNew<Const64Value>(proc, Origin(), c))); - - CHECK(compileAndRun<int64_t>(proc, a) == ((a | b) | c)); -} - -void testBitOrImmBitOrArgImm(int64_t a, int64_t b, int64_t c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitOr = root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), c)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - innerBitOr)); - - CHECK(compileAndRun<int64_t>(proc, b) == (a | (b | c))); -} - -void testBitOrArgs32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int>(proc, a, b) == (a | b)); -} - -void testBitOrSameArg32(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - argument, - argument)); - - CHECK(compileAndRun<int>(proc, a) == a); -} - -void testBitOrImms32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int>(proc) == (a | b)); -} - -void testBitOrArgImm32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int>(proc, a) == (a | b)); -} - -void testBitOrImmArg32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int>(proc, b) == (a | b)); -} - -void testBitOrBitOrArgImmImm32(int a, int b, int c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitOr = root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - innerBitOr, - root->appendNew<Const32Value>(proc, Origin(), c))); - - CHECK(compileAndRun<int>(proc, a) == ((a | b) | c)); -} - -void testBitOrImmBitOrArgImm32(int a, int b, int c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitOr = root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), c)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - innerBitOr)); - - CHECK(compileAndRun<int>(proc, b) == (a | (b | c))); -} - -void testBitXorArgs(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int64_t>(proc, a, b) == (a ^ b)); -} - -void testBitXorSameArg(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - argument, - argument)); - - CHECK(!compileAndRun<int64_t>(proc, a)); -} - -void testBitXorImms(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc) == (a ^ b)); -} - -void testBitXorArgImm(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc, a) == (a ^ b)); -} - -void testBitXorImmArg(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(compileAndRun<int64_t>(proc, b) == (a ^ b)); -} - -void testBitXorBitXorArgImmImm(int64_t a, int64_t b, int64_t c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitXor = root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), b)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - innerBitXor, - root->appendNew<Const64Value>(proc, Origin(), c))); - - CHECK(compileAndRun<int64_t>(proc, a) == ((a ^ b) ^ c)); -} - -void testBitXorImmBitXorArgImm(int64_t a, int64_t b, int64_t c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitXor = root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), c)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - innerBitXor)); - - CHECK(compileAndRun<int64_t>(proc, b) == (a ^ (b ^ c))); -} - -void testBitXorArgs32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int>(proc, a, b) == (a ^ b)); -} - -void testBitXorSameArg32(int a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - argument, - argument)); - - CHECK(!compileAndRun<int>(proc, a)); -} - -void testBitXorImms32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int>(proc) == (a ^ b)); -} - -void testBitXorArgImm32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int>(proc, a) == (a ^ b)); -} - -void testBitXorImmArg32(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int>(proc, b) == (a ^ b)); -} - -void testBitXorBitXorArgImmImm32(int a, int b, int c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitXor = root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - innerBitXor, - root->appendNew<Const32Value>(proc, Origin(), c))); - - CHECK(compileAndRun<int>(proc, a) == ((a ^ b) ^ c)); -} - -void testBitXorImmBitXorArgImm32(int a, int b, int c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* innerBitXor = root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), c)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - innerBitXor)); - - CHECK(compileAndRun<int>(proc, b) == (a ^ (b ^ c))); -} - -void testBitNotArg(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const64Value>(proc, Origin(), -1), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff)))); -} - -void testBitNotImm(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const64Value>(proc, Origin(), -1), - root->appendNew<Const64Value>(proc, Origin(), a))); - - CHECK(isIdentical(compileAndRun<int64_t>(proc, a), static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff)))); -} - -void testBitNotMem(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(), - root->appendNew<Const64Value>(proc, Origin(), -1), - load); - root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int64_t input = a; - compileAndRun<int32_t>(proc, &input); - CHECK(isIdentical(input, static_cast<int64_t>((static_cast<uint64_t>(a) ^ 0xffffffffffffffff)))); -} - -void testBitNotArg32(int32_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, BitXor, Origin(), - root->appendNew<Const32Value>(proc, Origin(), -1), - argument)); - CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff)))); -} - -void testBitNotImm32(int32_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitXor, Origin(), - root->appendNew<Const32Value>(proc, Origin(), -1), - root->appendNew<Const32Value>(proc, Origin(), a))); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, a), static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff)))); -} - -void testBitNotMem32(int32_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* notLoad = root->appendNew<Value>(proc, BitXor, Origin(), - root->appendNew<Const32Value>(proc, Origin(), -1), - load); - root->appendNew<MemoryValue>(proc, Store, Origin(), notLoad, address); - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - int32_t input = a; - compileAndRun<int32_t>(proc, &input); - CHECK(isIdentical(input, static_cast<int32_t>((static_cast<uint32_t>(a) ^ 0xffffffff)))); -} - -void testBitNotOnBooleanAndBranch32(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* argsAreEqual = root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2); - Value* argsAreNotEqual = root->appendNew<Value>(proc, BitXor, Origin(), - root->appendNew<Const32Value>(proc, Origin(), -1), - argsAreEqual); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - argsAreNotEqual, - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -42)); - - int32_t expectedValue = (a != b) ? 42 : -42; - CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue); -} - -void testShlArgs(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int64_t>(proc, a, b) == (a << b)); -} - -void testShlImms(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc) == (a << b)); -} - -void testShlArgImm(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc, a) == (a << b)); -} - -void testShlArg32(int32_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Shl, Origin(), value, value)); - - CHECK(compileAndRun<int32_t>(proc, a) == (a << a)); -} - -void testShlArgs32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int32_t>(proc, a, b) == (a << b)); -} - -void testShlImms32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int32_t>(proc) == (a << b)); -} - -void testShlArgImm32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int32_t>(proc, a) == (a << b)); -} - -void testSShrArgs(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int64_t>(proc, a, b) == (a >> b)); -} - -void testSShrImms(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc) == (a >> b)); -} - -void testSShrArgImm(int64_t a, int64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int64_t>(proc, a) == (a >> b)); -} - -void testSShrArg32(int32_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, SShr, Origin(), value, value)); - - CHECK(compileAndRun<int32_t>(proc, a) == (a >> (a & 31))); -} - -void testSShrArgs32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int32_t>(proc, a, b) == (a >> b)); -} - -void testSShrImms32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int32_t>(proc) == (a >> b)); -} - -void testSShrArgImm32(int32_t a, int32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<int32_t>(proc, a) == (a >> b)); -} - -void testZShrArgs(uint64_t a, uint64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZShr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<uint64_t>(proc, a, b) == (a >> b)); -} - -void testZShrImms(uint64_t a, uint64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZShr, Origin(), - root->appendNew<Const64Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<uint64_t>(proc) == (a >> b)); -} - -void testZShrArgImm(uint64_t a, uint64_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZShr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<uint64_t>(proc, a) == (a >> b)); -} - -void testZShrArg32(uint32_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* value = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, ZShr, Origin(), value, value)); - - CHECK(compileAndRun<uint32_t>(proc, a) == (a >> (a & 31))); -} - -void testZShrArgs32(uint32_t a, uint32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZShr, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<uint32_t>(proc, a, b) == (a >> b)); -} - -void testZShrImms32(uint32_t a, uint32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZShr, Origin(), - root->appendNew<Const32Value>(proc, Origin(), a), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<uint32_t>(proc) == (a >> b)); -} - -void testZShrArgImm32(uint32_t a, uint32_t b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZShr, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), b))); - - CHECK(compileAndRun<uint32_t>(proc, a) == (a >> b)); -} - -template<typename IntegerType> -static unsigned countLeadingZero(IntegerType value) -{ - unsigned bitCount = sizeof(IntegerType) * 8; - if (!value) - return bitCount; - - unsigned counter = 0; - while (!(static_cast<uint64_t>(value) & (1l << (bitCount - 1)))) { - value <<= 1; - ++counter; - } - return counter; -} - -void testClzArg64(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument); - root->appendNew<ControlValue>(proc, Return, Origin(), clzValue); - CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a)); -} - -void testClzMem64(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value); - root->appendNew<ControlValue>(proc, Return, Origin(), clzValue); - CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a)); -} - -void testClzArg32(int32_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), argument); - root->appendNew<ControlValue>(proc, Return, Origin(), clzValue); - CHECK(compileAndRun<unsigned>(proc, a) == countLeadingZero(a)); -} - -void testClzMem32(int32_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* value = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* clzValue = root->appendNew<Value>(proc, Clz, Origin(), value); - root->appendNew<ControlValue>(proc, Return, Origin(), clzValue); - CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a)); -} - -void testAbsArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Abs, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0))); - - CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(a))); -} - -void testAbsImm(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Abs, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<double>(proc), fabs(a))); -} - -void testAbsMem(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Abs, Origin(), loadDouble)); - - CHECK(isIdentical(compileAndRun<double>(proc, &a), fabs(a))); -} - -void testAbsAbsArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)); - Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs); - root->appendNew<ControlValue>(proc, Return, Origin(), secondAbs); - - CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(a))); -} - -void testAbsBitwiseCastArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64); - Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble); - root->appendNew<ControlValue>(proc, Return, Origin(), absValue); - - CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int64_t>(a)), fabs(a))); -} - -void testBitwiseCastAbsBitwiseCastArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64); - Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble); - Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue); - - root->appendNew<ControlValue>(proc, Return, Origin(), resultAsInt64); - - int64_t expectedResult = bitwise_cast<int64_t>(fabs(a)); - CHECK(isIdentical(compileAndRun<int64_t>(proc, bitwise_cast<int64_t>(a)), expectedResult)); -} - -void testAbsArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a))))); -} - -void testAbsImm(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a))))); -} - -void testAbsMem(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address); - Value* result = root->appendNew<Value>(proc, Abs, Origin(), loadFloat); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(fabs(a))))); -} - -void testAbsAbsArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(), argument); - Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs); - root->appendNew<ControlValue>(proc, Return, Origin(), secondAbs); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(a)))); -} - -void testAbsBitwiseCastArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32); - Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat); - root->appendNew<ControlValue>(proc, Return, Origin(), absValue); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(a)))); -} - -void testBitwiseCastAbsBitwiseCastArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32); - Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat); - Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue); - - root->appendNew<ControlValue>(proc, Return, Origin(), resultAsInt64); - - int32_t expectedResult = bitwise_cast<int32_t>(static_cast<float>(fabs(a))); - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), expectedResult)); -} - -void testAbsArgWithUselessDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a))))); -} - -void testAbsArgWithEffectfulDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - double effect = 0; - int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect); - CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(static_cast<float>(fabs(a))))); - CHECK(isIdentical(effect, fabs(a))); -} - -void testCeilArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Ceil, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0))); - - CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a))); -} - -void testCeilImm(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Ceil, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<double>(proc), ceil(a))); -} - -void testCeilMem(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Ceil, Origin(), loadDouble)); - - CHECK(isIdentical(compileAndRun<double>(proc, &a), ceil(a))); -} - -void testCeilCeilArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)); - Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil); - root->appendNew<ControlValue>(proc, Return, Origin(), secondCeil); - - CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a))); -} - -void testFloorCeilArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)); - Value* wrappingFloor = root->appendNew<Value>(proc, Floor, Origin(), firstCeil); - root->appendNew<ControlValue>(proc, Return, Origin(), wrappingFloor); - - CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a))); -} - -void testCeilIToD64(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a)))); -} - -void testCeilIToD32(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a)))); -} - -void testCeilArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a)))); -} - -void testCeilImm(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a)))); -} - -void testCeilMem(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address); - Value* result = root->appendNew<Value>(proc, Ceil, Origin(), loadFloat); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(ceilf(a)))); -} - -void testCeilCeilArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument); - Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil); - root->appendNew<ControlValue>(proc, Return, Origin(), secondCeil); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a))); -} - -void testFloorCeilArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument); - Value* wrappingFloor = root->appendNew<Value>(proc, Floor, Origin(), firstCeil); - root->appendNew<ControlValue>(proc, Return, Origin(), wrappingFloor); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a))); -} - -void testCeilArgWithUselessDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a)))); -} - -void testCeilArgWithEffectfulDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - double effect = 0; - int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect); - CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(ceilf(a)))); - CHECK(isIdentical(effect, ceilf(a))); -} - -void testFloorArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Floor, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0))); - - CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a))); -} - -void testFloorImm(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Floor, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<double>(proc), floor(a))); -} - -void testFloorMem(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Floor, Origin(), loadDouble)); - - CHECK(isIdentical(compileAndRun<double>(proc, &a), floor(a))); -} - -void testFloorFloorArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)); - Value* secondFloor = root->appendNew<Value>(proc, Floor, Origin(), firstFloor); - root->appendNew<ControlValue>(proc, Return, Origin(), secondFloor); - - CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a))); -} - -void testCeilFloorArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)); - Value* wrappingCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstFloor); - root->appendNew<ControlValue>(proc, Return, Origin(), wrappingCeil); - - CHECK(isIdentical(compileAndRun<double>(proc, a), floor(a))); -} - -void testFloorIToD64(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Floor, Origin(), argumentAsDouble)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), floor(static_cast<double>(a)))); -} - -void testFloorIToD32(int64_t a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Floor, Origin(), argumentAsDouble)); - - CHECK(isIdentical(compileAndRun<double>(proc, a), floor(static_cast<double>(a)))); -} - -void testFloorArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Floor, Origin(), argument); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a)))); -} - -void testFloorImm(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Floor, Origin(), argument); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a)))); -} - -void testFloorMem(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address); - Value* result = root->appendNew<Value>(proc, Floor, Origin(), loadFloat); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(floorf(a)))); -} - -void testFloorFloorArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(), argument); - Value* secondFloor = root->appendNew<Value>(proc, Floor, Origin(), firstFloor); - root->appendNew<ControlValue>(proc, Return, Origin(), secondFloor); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), floorf(a))); -} - -void testCeilFloorArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* firstFloor = root->appendNew<Value>(proc, Floor, Origin(), argument); - Value* wrappingCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstFloor); - root->appendNew<ControlValue>(proc, Return, Origin(), wrappingCeil); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), floorf(a))); -} - -void testFloorArgWithUselessDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Floor, Origin(), asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(floorf(a)))); -} - -void testFloorArgWithEffectfulDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Floor, Origin(), asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - double effect = 0; - int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect); - CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(floorf(a)))); - CHECK(isIdentical(effect, floorf(a))); -} - -void testSqrtArg(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sqrt, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0))); - - CHECK(isIdentical(compileAndRun<double>(proc, a), sqrt(a))); -} - -void testSqrtImm(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Sqrt, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<double>(proc), sqrt(a))); -} - -void testSqrtMem(double a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Sqrt, Origin(), loadDouble)); - - CHECK(isIdentical(compileAndRun<double>(proc, &a), sqrt(a))); -} - -void testSqrtArg(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), argument); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(sqrt(a))))); -} - -void testSqrtImm(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), argument); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(sqrt(a))))); -} - -void testSqrtMem(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address); - Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), loadFloat); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(sqrt(a))))); -} - -void testSqrtArgWithUselessDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(sqrt(a))))); -} - -void testSqrtArgWithEffectfulDoubleConversion(float a) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - Value* result = root->appendNew<Value>(proc, Sqrt, Origin(), asDouble); - Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result); - Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult); - Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress); - root->appendNew<ControlValue>(proc, Return, Origin(), result32); - - double effect = 0; - int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect); - CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(static_cast<float>(sqrt(a))))); - CHECK(isIdentical(effect, sqrt(a))); -} - -void testDoubleArgToInt64BitwiseCast(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitwiseCast, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<int64_t>(proc, value), bitwise_cast<int64_t>(value))); -} - -void testDoubleImmToInt64BitwiseCast(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitwiseCast, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<int64_t>(proc), bitwise_cast<int64_t>(value))); -} - -void testTwoBitwiseCastOnDouble(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument); - Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first); - root->appendNew<ControlValue>(proc, Return, Origin(), second); - - CHECK(isIdentical(compileAndRun<double>(proc, value), value)); -} - -void testBitwiseCastOnDoubleInMemory(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address); - Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble); - root->appendNew<ControlValue>(proc, Return, Origin(), cast); - - CHECK(isIdentical(compileAndRun<int64_t>(proc, &value), bitwise_cast<int64_t>(value))); -} - -void testBitwiseCastOnDoubleInMemoryIndexed(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* scaledOffset = root->appendNew<Value>(proc, Shl, Origin(), - offset, - root->appendNew<Const32Value>(proc, Origin(), 3)); - Value* address = root->appendNew<Value>(proc, Add, Origin(), base, scaledOffset); - MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address); - Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble); - root->appendNew<ControlValue>(proc, Return, Origin(), cast); - - CHECK(isIdentical(compileAndRun<int64_t>(proc, &value, 0), bitwise_cast<int64_t>(value))); -} - -void testInt64BArgToDoubleBitwiseCast(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitwiseCast, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<double>(proc, value), bitwise_cast<double>(value))); -} - -void testInt64BImmToDoubleBitwiseCast(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Const64Value>(proc, Origin(), value); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitwiseCast, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<double>(proc), bitwise_cast<double>(value))); -} - -void testTwoBitwiseCastOnInt64(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument); - Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first); - root->appendNew<ControlValue>(proc, Return, Origin(), second); - - CHECK(isIdentical(compileAndRun<int64_t>(proc, value), value)); -} - -void testBitwiseCastOnInt64InMemory(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble); - root->appendNew<ControlValue>(proc, Return, Origin(), cast); - - CHECK(isIdentical(compileAndRun<double>(proc, &value), bitwise_cast<double>(value))); -} - -void testBitwiseCastOnInt64InMemoryIndexed(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* scaledOffset = root->appendNew<Value>(proc, Shl, Origin(), - offset, - root->appendNew<Const32Value>(proc, Origin(), 3)); - Value* address = root->appendNew<Value>(proc, Add, Origin(), base, scaledOffset); - MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); - Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadDouble); - root->appendNew<ControlValue>(proc, Return, Origin(), cast); - - CHECK(isIdentical(compileAndRun<double>(proc, &value, 0), bitwise_cast<double>(value))); -} - -void testFloatImmToInt32BitwiseCast(float value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), value); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitwiseCast, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(value))); -} - -void testBitwiseCastOnFloatInMemory(float value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address); - Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadFloat); - root->appendNew<ControlValue>(proc, Return, Origin(), cast); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, &value), bitwise_cast<int32_t>(value))); -} - -void testInt32BArgToFloatBitwiseCast(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitwiseCast, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<float>(proc, value), bitwise_cast<float>(value))); -} - -void testInt32BImmToFloatBitwiseCast(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<Const64Value>(proc, Origin(), value); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitwiseCast, Origin(), argument)); - - CHECK(isIdentical(compileAndRun<float>(proc), bitwise_cast<float>(value))); -} - -void testTwoBitwiseCastOnInt32(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* first = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument); - Value* second = root->appendNew<Value>(proc, BitwiseCast, Origin(), first); - root->appendNew<ControlValue>(proc, Return, Origin(), second); - - CHECK(isIdentical(compileAndRun<int32_t>(proc, value), value)); -} - -void testBitwiseCastOnInt32InMemory(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); - Value* cast = root->appendNew<Value>(proc, BitwiseCast, Origin(), loadFloat); - root->appendNew<ControlValue>(proc, Return, Origin(), cast); - - CHECK(isIdentical(compileAndRun<float>(proc, &value), bitwise_cast<float>(value))); -} - -void testConvertDoubleToFloatArg(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument); - root->appendNew<ControlValue>(proc, Return, Origin(), asFloat); - - CHECK(isIdentical(compileAndRun<float>(proc, value), static_cast<float>(value))); -} - -void testConvertDoubleToFloatImm(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), value); - Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument); - root->appendNew<ControlValue>(proc, Return, Origin(), asFloat); - - CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value))); -} - -void testConvertDoubleToFloatMem(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadedDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address); - Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), loadedDouble); - root->appendNew<ControlValue>(proc, Return, Origin(), asFloat); - - CHECK(isIdentical(compileAndRun<float>(proc, &value), static_cast<float>(value))); -} - -void testConvertFloatToDoubleArg(float value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); - root->appendNew<ControlValue>(proc, Return, Origin(), asDouble); - - CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int32_t>(value)), static_cast<double>(value))); -} - -void testConvertFloatToDoubleImm(float value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), value); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument); - root->appendNew<ControlValue>(proc, Return, Origin(), asDouble); - - CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value))); -} - -void testConvertFloatToDoubleMem(float value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadedFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), loadedFloat); - root->appendNew<ControlValue>(proc, Return, Origin(), asDouble); - - CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(value))); -} - -void testConvertDoubleToFloatToDoubleToFloat(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat); - Value* asFloatAgain = root->appendNew<Value>(proc, DoubleToFloat, Origin(), asDouble); - root->appendNew<ControlValue>(proc, Return, Origin(), asFloatAgain); - - CHECK(isIdentical(compileAndRun<float>(proc, value), static_cast<float>(value))); -} - -void testLoadFloatConvertDoubleConvertFloatStoreFloat(float value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* dst = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - MemoryValue* loadedFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), src); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), loadedFloat); - Value* asFloatAgain = root->appendNew<Value>(proc, DoubleToFloat, Origin(), asDouble); - root->appendNew<MemoryValue>(proc, Store, Origin(), asFloatAgain, dst); - - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - float input = value; - float output = 0.; - CHECK(!compileAndRun<int64_t>(proc, &input, &output)); - CHECK(isIdentical(input, output)); -} - -void testFroundArg(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat); - root->appendNew<ControlValue>(proc, Return, Origin(), asDouble); - - CHECK(isIdentical(compileAndRun<double>(proc, value), static_cast<double>(static_cast<float>(value)))); -} - -void testFroundMem(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* loadedDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address); - Value* asFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), loadedDouble); - Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), asFloat); - root->appendNew<ControlValue>(proc, Return, Origin(), asDouble); - - CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(static_cast<float>(value)))); -} - -void testStore32(int value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slot = 0xbaadbeef; - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<ConstPtrValue>(proc, Origin(), &slot)); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, value)); - CHECK(slot == value); -} - -void testStoreConstant(int value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slot = 0xbaadbeef; - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Const32Value>(proc, Origin(), value), - root->appendNew<ConstPtrValue>(proc, Origin(), &slot)); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == value); -} - -void testStoreConstantPtr(intptr_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - intptr_t slot; - if (is64Bit()) - slot = (static_cast<intptr_t>(0xbaadbeef) << 32) + static_cast<intptr_t>(0xbaadbeef); - else - slot = 0xbaadbeef; - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), value), - root->appendNew<ConstPtrValue>(proc, Origin(), &slot)); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == value); -} - -void testStore8Arg() -{ - { // Direct addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* value = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - - root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address); - root->appendNew<ControlValue>(proc, Return, Origin(), value); - - int8_t storage = 0; - CHECK(compileAndRun<int64_t>(proc, 42, &storage) == 42); - CHECK(storage == 42); - } - - { // Indexed addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* value = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1); - - Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base); - Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset); - - root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address); - root->appendNew<ControlValue>(proc, Return, Origin(), value); - - int8_t storage = 0; - CHECK(compileAndRun<int64_t>(proc, 42, &storage, 1) == 42); - CHECK(storage == 42); - } -} - -void testStore8Imm() -{ - { // Direct addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* value = root->appendNew<Const32Value>(proc, Origin(), 42); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - - root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address); - root->appendNew<ControlValue>(proc, Return, Origin(), value); - - int8_t storage = 0; - CHECK(compileAndRun<int64_t>(proc, &storage) == 42); - CHECK(storage == 42); - } - - { // Indexed addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* value = root->appendNew<Const32Value>(proc, Origin(), 42); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1); - - Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base); - Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset); - - root->appendNew<MemoryValue>(proc, Store8, Origin(), value, address); - root->appendNew<ControlValue>(proc, Return, Origin(), value); - - int8_t storage = 0; - CHECK(compileAndRun<int64_t>(proc, &storage, 1) == 42); - CHECK(storage == 42); - } -} - -void testStorePartial8BitRegisterOnX86() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - // We want to have this in ECX. - Value* returnValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - - // We want this suck in EDX. - Value* whereToStore = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - - // The patch point is there to help us force the hand of the compiler. - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - - // For the value above to be materialized and give the allocator - // a stronger insentive to name those register the way we need. - patchpoint->append(ConstrainedValue(returnValue, ValueRep(GPRInfo::regT3))); - patchpoint->append(ConstrainedValue(whereToStore, ValueRep(GPRInfo::regT2))); - - // We'll produce EDI. - patchpoint->resultConstraint = ValueRep::reg(GPRInfo::regT6); - - // Give the allocator a good reason not to use any other register. - RegisterSet clobberSet = RegisterSet::allGPRs(); - clobberSet.exclude(RegisterSet::stackRegisters()); - clobberSet.exclude(RegisterSet::reservedHardwareRegisters()); - clobberSet.clear(GPRInfo::regT3); - clobberSet.clear(GPRInfo::regT2); - clobberSet.clear(GPRInfo::regT6); - patchpoint->clobberLate(clobberSet); - - // Set EDI. - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - jit.xor64(params[0].gpr(), params[0].gpr()); - }); - - // If everything went well, we should have the big number in eax, - // patchpoint == EDI and whereToStore = EDX. - // Since EDI == 5, and AH = 5 on 8 bit store, this would go wrong - // if we use X86 partial registers. - root->appendNew<MemoryValue>(proc, Store8, Origin(), patchpoint, whereToStore); - - root->appendNew<ControlValue>(proc, Return, Origin(), returnValue); - - int8_t storage = 0xff; - CHECK(compileAndRun<int64_t>(proc, 0x12345678abcdef12, &storage) == 0x12345678abcdef12); - CHECK(!storage); -} - -void testStore16Arg() -{ - { // Direct addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* value = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - - root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address); - root->appendNew<ControlValue>(proc, Return, Origin(), value); - - int16_t storage = -1; - CHECK(compileAndRun<int64_t>(proc, 42, &storage) == 42); - CHECK(storage == 42); - } - - { // Indexed addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* value = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1); - - Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base); - Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset); - - root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address); - root->appendNew<ControlValue>(proc, Return, Origin(), value); - - int16_t storage = -1; - CHECK(compileAndRun<int64_t>(proc, 42, &storage, 1) == 42); - CHECK(storage == 42); - } -} - -void testStore16Imm() -{ - { // Direct addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* value = root->appendNew<Const32Value>(proc, Origin(), 42); - Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - - root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address); - root->appendNew<ControlValue>(proc, Return, Origin(), value); - - int16_t storage = -1; - CHECK(compileAndRun<int64_t>(proc, &storage) == 42); - CHECK(storage == 42); - } - - { // Indexed addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* value = root->appendNew<Const32Value>(proc, Origin(), 42); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1); - - Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base); - Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset); - - root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address); - root->appendNew<ControlValue>(proc, Return, Origin(), value); - - int16_t storage = -1; - CHECK(compileAndRun<int64_t>(proc, &storage, 1) == 42); - CHECK(storage == 42); - } -} - -void testTrunc(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(compileAndRun<int>(proc, value) == static_cast<int>(value)); -} - -void testAdd1(int value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), 1))); - - CHECK(compileAndRun<int>(proc, value) == value + 1); -} - -void testAdd1Ptr(intptr_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ConstPtrValue>(proc, Origin(), 1))); - - CHECK(compileAndRun<intptr_t>(proc, value) == value + 1); -} - -void testNeg32(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int32_t>(proc, value) == -value); -} - -void testNegPtr(intptr_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), 0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(compileAndRun<intptr_t>(proc, value) == -value); -} - -void testStoreAddLoad32(int amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slot = 37; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoadImm32(int amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slot = 37; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr), - root->appendNew<Const32Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoad8(int amount, B3::Opcode loadOpcode) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int8_t slot = 37; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store8, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoadImm8(int amount, B3::Opcode loadOpcode) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int8_t slot = 37; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store8, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), - root->appendNew<Const32Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoad16(int amount, B3::Opcode loadOpcode) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int16_t slot = 37; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store16, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoadImm16(int amount, B3::Opcode loadOpcode) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int16_t slot = 37; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store16, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), - root->appendNew<Const32Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoad64(int amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int64_t slot = 37000000000ll; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == 37000000000ll + amount); -} - -void testStoreAddLoadImm64(int64_t amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int64_t slot = 370000000000ll; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr), - root->appendNew<Const64Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == 370000000000ll + amount); -} - -void testStoreAddLoad32Index(int amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slot = 37; - int* ptr = &slot; - intptr_t zero = 0; - Value* slotPtr = root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &zero))); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoadImm32Index(int amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slot = 37; - int* ptr = &slot; - intptr_t zero = 0; - Value* slotPtr = root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &zero))); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr), - root->appendNew<Const32Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoad8Index(int amount, B3::Opcode loadOpcode) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int8_t slot = 37; - int8_t* ptr = &slot; - intptr_t zero = 0; - Value* slotPtr = root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &zero))); - root->appendNew<MemoryValue>( - proc, Store8, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoadImm8Index(int amount, B3::Opcode loadOpcode) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int8_t slot = 37; - int8_t* ptr = &slot; - intptr_t zero = 0; - Value* slotPtr = root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &zero))); - root->appendNew<MemoryValue>( - proc, Store8, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), - root->appendNew<Const32Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoad16Index(int amount, B3::Opcode loadOpcode) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int16_t slot = 37; - int16_t* ptr = &slot; - intptr_t zero = 0; - Value* slotPtr = root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &zero))); - root->appendNew<MemoryValue>( - proc, Store16, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoadImm16Index(int amount, B3::Opcode loadOpcode) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int16_t slot = 37; - int16_t* ptr = &slot; - intptr_t zero = 0; - Value* slotPtr = root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &zero))); - root->appendNew<MemoryValue>( - proc, Store16, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), - root->appendNew<Const32Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == 37 + amount); -} - -void testStoreAddLoad64Index(int amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int64_t slot = 37000000000ll; - int64_t* ptr = &slot; - intptr_t zero = 0; - Value* slotPtr = root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &zero))); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == 37000000000ll + amount); -} - -void testStoreAddLoadImm64Index(int64_t amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int64_t slot = 370000000000ll; - int64_t* ptr = &slot; - intptr_t zero = 0; - Value* slotPtr = root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &zero))); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr), - root->appendNew<Const64Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == 370000000000ll + amount); -} - -void testStoreSubLoad(int amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int32_t startValue = std::numeric_limits<int32_t>::min(); - int32_t slot = startValue; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, amount)); - CHECK(slot == startValue - amount); -} - -void testStoreAddLoadInterference(int amount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slot = 37; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - ArgumentRegValue* otherSlotPtr = - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - MemoryValue* load = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 666), - otherSlotPtr); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - load, root->appendNew<Const32Value>(proc, Origin(), amount)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc, &slot)); - CHECK(slot == 37 + amount); -} - -void testStoreAddAndLoad(int amount, int mask) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slot = 37; - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr), - root->appendNew<Const32Value>(proc, Origin(), amount)), - root->appendNew<Const32Value>(proc, Origin(), mask)), - slotPtr); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); - CHECK(slot == ((37 + amount) & mask)); -} - -void testStoreNegLoad32(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - int32_t slot = value; - - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)), - slotPtr); - - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int32_t>(proc)); - CHECK(slot == -value); -} - -void testStoreNegLoadPtr(intptr_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - intptr_t slot = value; - - ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot); - - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Sub, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), 0), - root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)), - slotPtr); - - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int32_t>(proc)); - CHECK(slot == -value); -} - -void testAdd1Uncommuted(int value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 1), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int>(proc, value) == value + 1); -} - -void testLoadOffset() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int array[] = { 1, 2 }; - ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, sizeof(int)))); - - CHECK(compileAndRun<int>(proc) == array[0] + array[1]); -} - -void testLoadOffsetNotConstant() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int array[] = { 1, 2 }; - Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, sizeof(int)))); - - CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]); -} - -void testLoadOffsetUsingAdd() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int array[] = { 1, 2 }; - ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), arrayPtr, - root->appendNew<ConstPtrValue>(proc, Origin(), 0))), - root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), arrayPtr, - root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int)))))); - - CHECK(compileAndRun<int>(proc) == array[0] + array[1]); -} - -void testLoadOffsetUsingAddInterference() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int array[] = { 1, 2 }; - ConstPtrValue* arrayPtr = root->appendNew<ConstPtrValue>(proc, Origin(), array); - ArgumentRegValue* otherArrayPtr = - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Const32Value* theNumberOfTheBeast = root->appendNew<Const32Value>(proc, Origin(), 666); - MemoryValue* left = root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), arrayPtr, - root->appendNew<ConstPtrValue>(proc, Origin(), 0))); - MemoryValue* right = root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), arrayPtr, - root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int)))); - root->appendNew<MemoryValue>( - proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0); - root->appendNew<MemoryValue>( - proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, sizeof(int)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), left, right)); - - CHECK(compileAndRun<int>(proc, &array[0]) == 1 + 2); - CHECK(array[0] == 666); - CHECK(array[1] == 666); -} - -void testLoadOffsetUsingAddNotConstant() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int array[] = { 1, 2 }; - Value* arrayPtr = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), arrayPtr, - root->appendNew<ConstPtrValue>(proc, Origin(), 0))), - root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), arrayPtr, - root->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int)))))); - - CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]); -} - -void testLoadAddrShift(unsigned shift) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - int slots[2]; - - // Figure out which slot to use while having proper alignment for the shift. - int* slot; - uintptr_t arg; - for (unsigned i = sizeof(slots)/sizeof(slots[0]); i--;) { - slot = slots + i; - arg = bitwise_cast<uintptr_t>(slot) >> shift; - if (bitwise_cast<int*>(arg << shift) == slot) - break; - } - - *slot = 8675309; - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const32Value>(proc, Origin(), shift)))); - - CHECK(compileAndRun<int>(proc, arg) == 8675309); -} - -void testFramePointer() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, FramePointer, Origin())); - - void* fp = compileAndRun<void*>(proc); - CHECK(fp < &proc); - CHECK(fp >= bitwise_cast<char*>(&proc) - 10000); -} - -void testOverrideFramePointer() -{ - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - // Add a stack slot to make the frame non trivial. - root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8)); - - // Sub on x86 UseDef the source. If FP is not protected correctly, it will be overridden since it is the last visible use. - Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* fp = root->appendNew<Value>(proc, FramePointer, Origin()); - Value* result = root->appendNew<Value>(proc, Sub, Origin(), fp, offset); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - CHECK(compileAndRun<int64_t>(proc, 1)); - } - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8)); - - Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* fp = root->appendNew<Value>(proc, FramePointer, Origin()); - Value* offsetFP = root->appendNew<Value>(proc, BitAnd, Origin(), offset, fp); - Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* offsetArg = root->appendNew<Value>(proc, Add, Origin(), offset, arg); - Value* result = root->appendNew<Value>(proc, Add, Origin(), offsetArg, offsetFP); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - CHECK(compileAndRun<int64_t>(proc, 1, 2)); - } -} - -void testStackSlot() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(1))); - - void* stackSlot = compileAndRun<void*>(proc); - CHECK(stackSlot < &proc); - CHECK(stackSlot >= bitwise_cast<char*>(&proc) - 10000); -} - -void testLoadFromFramePointer() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<Value>(proc, FramePointer, Origin()))); - - void* fp = compileAndRun<void*>(proc); - void* myFP = __builtin_frame_address(0); - CHECK(fp <= myFP); - CHECK(fp >= bitwise_cast<char*>(myFP) - 10000); -} - -void testStoreLoadStackSlot(int value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - SlotBaseValue* stack = - root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(sizeof(int))); - - root->appendNew<MemoryValue>( - proc, Store, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - stack); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), stack)); - - CHECK(compileAndRun<int>(proc, value) == value); -} - -template<typename LoadedType, typename EffectiveType> -EffectiveType modelLoad(EffectiveType value) -{ - union { - EffectiveType original; - LoadedType loaded; - } u; - - u.original = value; - if (std::is_signed<LoadedType>::value) - return static_cast<EffectiveType>(u.loaded); - return static_cast<EffectiveType>(static_cast<typename std::make_unsigned<EffectiveType>::type>(u.loaded)); -} - -template<> -float modelLoad<float, float>(float value) { return value; } - -template<> -double modelLoad<double, double>(double value) { return value; } - -template<B3::Type type, typename CType, typename InputType> -void testLoad(B3::Opcode opcode, InputType value) -{ - // Simple load from an absolute address. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, opcode, type, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &value))); - - CHECK(isIdentical(compileAndRun<CType>(proc), modelLoad<CType>(value))); - } - - // Simple load from an address in a register. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, opcode, type, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - - CHECK(isIdentical(compileAndRun<CType>(proc, &value), modelLoad<CType>(value))); - } - - // Simple load from an address in a register, at an offset. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, opcode, type, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - sizeof(InputType))); - - CHECK(isIdentical(compileAndRun<CType>(proc, &value - 1), modelLoad<CType>(value))); - } - - // Load from a simple base-index with various scales. - for (unsigned logScale = 0; logScale <= 3; ++logScale) { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, opcode, type, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1), - root->appendNew<Const32Value>(proc, Origin(), logScale))))); - - CHECK(isIdentical(compileAndRun<CType>(proc, &value - 2, (sizeof(InputType) * 2) >> logScale), modelLoad<CType>(value))); - } - - // Load from a simple base-index with various scales, but commuted. - for (unsigned logScale = 0; logScale <= 3; ++logScale) { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>( - proc, opcode, type, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1), - root->appendNew<Const32Value>(proc, Origin(), logScale)), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(isIdentical(compileAndRun<CType>(proc, &value - 2, (sizeof(InputType) * 2) >> logScale), modelLoad<CType>(value))); - } -} - -template<typename T> -void testLoad(B3::Opcode opcode, int32_t value) -{ - return testLoad<Int32, T>(opcode, value); -} - -template<B3::Type type, typename T> -void testLoad(T value) -{ - return testLoad<type, T>(Load, value); -} - -void testStoreFloat(double input) -{ - // Simple store from an address in a register. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument); - - Value* destinationAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress); - - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - float output = 0.; - CHECK(!compileAndRun<int64_t>(proc, input, &output)); - CHECK(isIdentical(static_cast<float>(input), output)); - } - - // Simple indexed store. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* argumentAsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), argument); - - Value* destinationBaseAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* index = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* scaledIndex = root->appendNew<Value>( - proc, Shl, Origin(), - index, - root->appendNew<Const32Value>(proc, Origin(), 2)); - Value* destinationAddress = root->appendNew<Value>(proc, Add, Origin(), scaledIndex, destinationBaseAddress); - - root->appendNew<MemoryValue>(proc, Store, Origin(), argumentAsFloat, destinationAddress); - - root->appendNew<ControlValue>(proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - float output = 0.; - CHECK(!compileAndRun<int64_t>(proc, input, &output - 1, 1)); - CHECK(isIdentical(static_cast<float>(input), output)); - } -} - -void testSpillGP() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Vector<Value*> sources; - sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - - for (unsigned i = 0; i < 30; ++i) { - sources.append( - root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2]) - ); - } - - Value* total = root->appendNew<Const64Value>(proc, Origin(), 0); - for (Value* value : sources) - total = root->appendNew<Value>(proc, Add, Origin(), total, value); - - root->appendNew<ControlValue>(proc, Return, Origin(), total); - compileAndRun<int>(proc, 1, 2); -} - -void testSpillFP() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Vector<Value*> sources; - sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)); - sources.append(root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)); - - for (unsigned i = 0; i < 30; ++i) { - sources.append( - root->appendNew<Value>(proc, Add, Origin(), sources[sources.size() - 1], sources[sources.size() - 2]) - ); - } - - Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.); - for (Value* value : sources) - total = root->appendNew<Value>(proc, Add, Origin(), total, value); - - root->appendNew<ControlValue>(proc, Return, Origin(), total); - compileAndRun<double>(proc, 1.1, 2.5); -} - -void testInt32ToDoublePartialRegisterStall() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* loop = proc.addBlock(); - BasicBlock* done = proc.addBlock(); - - // Head. - Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.); - Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total); - UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter); - root->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loop)); - - // Loop. - Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin()); - Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin()); - originalCounter->setPhi(loopCounter); - originalTotal->setPhi(loopTotal); - - Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter); - Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter); - Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal); - UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal); - updatedTotalUpsilon->setPhi(loopTotal); - - Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1)); - UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter); - decCounterUpsilon->setPhi(loopCounter); - loop->appendNew<ControlValue>( - proc, Branch, Origin(), - decCounter, - FrequentedBlock(loop), FrequentedBlock(done)); - - // Tail. - done->appendNew<ControlValue>(proc, Return, Origin(), updatedTotal); - CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.)); -} - -void testInt32ToDoublePartialRegisterWithoutStall() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* loop = proc.addBlock(); - BasicBlock* done = proc.addBlock(); - - // Head. - Value* total = root->appendNew<ConstDoubleValue>(proc, Origin(), 0.); - Value* counter = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - UpsilonValue* originalTotal = root->appendNew<UpsilonValue>(proc, Origin(), total); - UpsilonValue* originalCounter = root->appendNew<UpsilonValue>(proc, Origin(), counter); - uint64_t forPaddingInput; - Value* forPaddingInputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingInput); - uint64_t forPaddingOutput; - Value* forPaddingOutputAddress = root->appendNew<ConstPtrValue>(proc, Origin(), &forPaddingOutput); - root->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loop)); - - // Loop. - Value* loopCounter = loop->appendNew<Value>(proc, Phi, Int64, Origin()); - Value* loopTotal = loop->appendNew<Value>(proc, Phi, Double, Origin()); - originalCounter->setPhi(loopCounter); - originalTotal->setPhi(loopTotal); - - Value* truncatedCounter = loop->appendNew<Value>(proc, Trunc, Origin(), loopCounter); - Value* doubleCounter = loop->appendNew<Value>(proc, IToD, Origin(), truncatedCounter); - Value* updatedTotal = loop->appendNew<Value>(proc, Add, Origin(), doubleCounter, loopTotal); - - // Add enough padding instructions to avoid a stall. - Value* loadPadding = loop->appendNew<MemoryValue>(proc, Load, Int64, Origin(), forPaddingInputAddress); - Value* padding = loop->appendNew<Value>(proc, BitXor, Origin(), loadPadding, loopCounter); - padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, BitXor, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, Add, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, BitOr, Origin(), padding, loopCounter); - padding = loop->appendNew<Value>(proc, Sub, Origin(), padding, loopCounter); - loop->appendNew<MemoryValue>(proc, Store, Origin(), padding, forPaddingOutputAddress); - - UpsilonValue* updatedTotalUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), updatedTotal); - updatedTotalUpsilon->setPhi(loopTotal); - - Value* decCounter = loop->appendNew<Value>(proc, Sub, Origin(), loopCounter, loop->appendNew<Const64Value>(proc, Origin(), 1)); - UpsilonValue* decCounterUpsilon = loop->appendNew<UpsilonValue>(proc, Origin(), decCounter); - decCounterUpsilon->setPhi(loopCounter); - loop->appendNew<ControlValue>( - proc, Branch, Origin(), - decCounter, - FrequentedBlock(loop), FrequentedBlock(done)); - - // Tail. - done->appendNew<ControlValue>(proc, Return, Origin(), updatedTotal); - CHECK(isIdentical(compileAndRun<double>(proc, 100000), 5000050000.)); -} - -void testBranch() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchPtr() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, static_cast<intptr_t>(42)) == 1); - CHECK(invoke<int>(*code, static_cast<intptr_t>(0)) == 0); -} - -void testDiamond() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - BasicBlock* done = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>( - proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - thenCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done)); - - UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>( - proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - elseCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done)); - - Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin()); - thenResult->setPhi(phi); - elseResult->setPhi(phi); - done->appendNew<ControlValue>(proc, Return, Origin(), phi); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchNotEqual() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, NotEqual, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), 0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchNotEqualCommute() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, NotEqual, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchNotEqualNotEqual() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, NotEqual, Origin(), - root->appendNew<Value>( - proc, NotEqual, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), 0)), - root->appendNew<Const32Value>(proc, Origin(), 0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchEqual() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), 0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 0)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 1)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchEqualEqual() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), 0)), - root->appendNew<Const32Value>(proc, Origin(), 0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchEqualCommute() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 0)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 1)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchEqualEqual1() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), 0)), - root->appendNew<Const32Value>(proc, Origin(), 1)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 0)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 1)); - - auto code = compile(proc); - CHECK(invoke<int>(*code, 42) == 1); - CHECK(invoke<int>(*code, 0) == 0); -} - -void testBranchEqualOrUnorderedArgs(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argumentA, - argumentB), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc, a, b) == expected); -} - -void testBranchEqualOrUnorderedArgs(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argumentA, - argumentB), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected); -} - -void testBranchNotEqualAndOrderedArgs(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* equalOrUnordered = root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argumentA, - argumentB); - Value* notEqualAndOrdered = root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0), - equalOrUnordered); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - notEqualAndOrdered, - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc, a, b) == expected); -} - -void testBranchNotEqualAndOrderedArgs(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* equalOrUnordered = root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argumentA, - argumentB); - Value* notEqualAndOrdered = root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0), - equalOrUnordered); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - notEqualAndOrdered, - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected); -} - -void testBranchEqualOrUnorderedDoubleArgImm(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argumentA, - argumentB), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc, a) == expected); -} - -void testBranchEqualOrUnorderedFloatArgImm(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argumentA, - argumentB), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc, &a) == expected); -} - -void testBranchEqualOrUnorderedDoubleImms(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a); - Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argumentA, - argumentB), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc) == expected); -} - -void testBranchEqualOrUnorderedFloatImms(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a); - Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argumentA, - argumentB), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc) == expected); -} - -void testBranchEqualOrUnorderedFloatWithUselessDoubleConversion(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* argument1 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* argument1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument1); - Value* argument2AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument2); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, EqualOrUnordered, Origin(), - argument1AsDouble, - argument2AsDouble), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 42)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), -13)); - - int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13; - CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected); -} - -void testBranchFold(int value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Const32Value>(proc, Origin(), value), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(compileAndRun<int>(proc) == !!value); -} - -void testDiamondFold(int value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - BasicBlock* done = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Const32Value>(proc, Origin(), value), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - UpsilonValue* thenResult = thenCase->appendNew<UpsilonValue>( - proc, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - thenCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done)); - - UpsilonValue* elseResult = elseCase->appendNew<UpsilonValue>( - proc, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - elseCase->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(done)); - - Value* phi = done->appendNew<Value>(proc, Phi, Int32, Origin()); - thenResult->setPhi(phi); - elseResult->setPhi(phi); - done->appendNew<ControlValue>(proc, Return, Origin(), phi); - - CHECK(compileAndRun<int>(proc) == !!value); -} - -void testBranchNotEqualFoldPtr(intptr_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, NotEqual, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), value), - root->appendNew<ConstPtrValue>(proc, Origin(), 0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(compileAndRun<int>(proc) == !!value); -} - -void testBranchEqualFoldPtr(intptr_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), value), - root->appendNew<ConstPtrValue>(proc, Origin(), 0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(compileAndRun<int>(proc) == !value); -} - -void testBranchLoadPtr() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - intptr_t cond; - cond = 42; - CHECK(invoke<int>(*code, &cond) == 1); - cond = 0; - CHECK(invoke<int>(*code, &cond) == 0); -} - -void testBranchLoad32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - int32_t cond; - cond = 42; - CHECK(invoke<int>(*code, &cond) == 1); - cond = 0; - CHECK(invoke<int>(*code, &cond) == 0); -} - -void testBranchLoad8S() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<MemoryValue>( - proc, Load8S, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - int8_t cond; - cond = -1; - CHECK(invoke<int>(*code, &cond) == 1); - cond = 0; - CHECK(invoke<int>(*code, &cond) == 0); -} - -void testBranchLoad8Z() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - uint8_t cond; - cond = 1; - CHECK(invoke<int>(*code, &cond) == 1); - cond = 0; - CHECK(invoke<int>(*code, &cond) == 0); -} - -void testBranchLoad16S() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<MemoryValue>( - proc, Load16S, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - int16_t cond; - cond = -1; - CHECK(invoke<int>(*code, &cond) == 1); - cond = 0; - CHECK(invoke<int>(*code, &cond) == 0); -} - -void testBranchLoad16Z() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<MemoryValue>( - proc, Load16Z, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<Const32Value>(proc, Origin(), 1)); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - uint16_t cond; - cond = 1; - CHECK(invoke<int>(*code, &cond) == 1); - cond = 0; - CHECK(invoke<int>(*code, &cond) == 0); -} - -void testComplex(unsigned numVars, unsigned numConstructs) -{ - double before = monotonicallyIncreasingTimeMS(); - - Procedure proc; - BasicBlock* current = proc.addBlock(); - - Const32Value* one = current->appendNew<Const32Value>(proc, Origin(), 1); - - Vector<int32_t> varSlots; - for (unsigned i = numVars; i--;) - varSlots.append(i); - - Vector<Value*> vars; - for (int32_t& varSlot : varSlots) { - Value* varSlotPtr = current->appendNew<ConstPtrValue>(proc, Origin(), &varSlot); - vars.append(current->appendNew<MemoryValue>(proc, Load, Int32, Origin(), varSlotPtr)); - } - - for (unsigned i = 0; i < numConstructs; ++i) { - if (i & 1) { - // Control flow diamond. - unsigned predicateVarIndex = ((i >> 1) + 2) % numVars; - unsigned thenIncVarIndex = ((i >> 1) + 0) % numVars; - unsigned elseIncVarIndex = ((i >> 1) + 1) % numVars; - - BasicBlock* thenBlock = proc.addBlock(); - BasicBlock* elseBlock = proc.addBlock(); - BasicBlock* continuation = proc.addBlock(); - - current->appendNew<ControlValue>( - proc, Branch, Origin(), vars[predicateVarIndex], - FrequentedBlock(thenBlock), FrequentedBlock(elseBlock)); - - UpsilonValue* thenThenResult = thenBlock->appendNew<UpsilonValue>( - proc, Origin(), - thenBlock->appendNew<Value>(proc, Add, Origin(), vars[thenIncVarIndex], one)); - UpsilonValue* thenElseResult = thenBlock->appendNew<UpsilonValue>( - proc, Origin(), vars[elseIncVarIndex]); - thenBlock->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation)); - - UpsilonValue* elseElseResult = elseBlock->appendNew<UpsilonValue>( - proc, Origin(), - elseBlock->appendNew<Value>(proc, Add, Origin(), vars[elseIncVarIndex], one)); - UpsilonValue* elseThenResult = elseBlock->appendNew<UpsilonValue>( - proc, Origin(), vars[thenIncVarIndex]); - elseBlock->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation)); - - Value* thenPhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin()); - thenThenResult->setPhi(thenPhi); - elseThenResult->setPhi(thenPhi); - vars[thenIncVarIndex] = thenPhi; - - Value* elsePhi = continuation->appendNew<Value>(proc, Phi, Int32, Origin()); - thenElseResult->setPhi(elsePhi); - elseElseResult->setPhi(elsePhi); - vars[elseIncVarIndex] = thenPhi; - - current = continuation; - } else { - // Loop. - - BasicBlock* loopEntry = proc.addBlock(); - BasicBlock* loopReentry = proc.addBlock(); - BasicBlock* loopBody = proc.addBlock(); - BasicBlock* loopExit = proc.addBlock(); - BasicBlock* loopSkip = proc.addBlock(); - BasicBlock* continuation = proc.addBlock(); - - Value* startIndex = vars[((i >> 1) + 1) % numVars]; - Value* startSum = current->appendNew<Const32Value>(proc, Origin(), 0); - current->appendNew<ControlValue>( - proc, Branch, Origin(), startIndex, - FrequentedBlock(loopEntry), FrequentedBlock(loopSkip)); - - UpsilonValue* startIndexForBody = loopEntry->appendNew<UpsilonValue>( - proc, Origin(), startIndex); - UpsilonValue* startSumForBody = loopEntry->appendNew<UpsilonValue>( - proc, Origin(), startSum); - loopEntry->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loopBody)); - - Value* bodyIndex = loopBody->appendNew<Value>(proc, Phi, Int32, Origin()); - startIndexForBody->setPhi(bodyIndex); - Value* bodySum = loopBody->appendNew<Value>(proc, Phi, Int32, Origin()); - startSumForBody->setPhi(bodySum); - Value* newBodyIndex = loopBody->appendNew<Value>(proc, Sub, Origin(), bodyIndex, one); - Value* newBodySum = loopBody->appendNew<Value>( - proc, Add, Origin(), - bodySum, - loopBody->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - loopBody->appendNew<Value>( - proc, Add, Origin(), - loopBody->appendNew<ConstPtrValue>(proc, Origin(), varSlots.data()), - loopBody->appendNew<Value>( - proc, Shl, Origin(), - loopBody->appendNew<Value>( - proc, ZExt32, Origin(), - loopBody->appendNew<Value>( - proc, BitAnd, Origin(), - newBodyIndex, - loopBody->appendNew<Const32Value>( - proc, Origin(), numVars - 1))), - loopBody->appendNew<Const32Value>(proc, Origin(), 2))))); - loopBody->appendNew<ControlValue>( - proc, Branch, Origin(), newBodyIndex, - FrequentedBlock(loopReentry), FrequentedBlock(loopExit)); - - loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodyIndex, bodyIndex); - loopReentry->appendNew<UpsilonValue>(proc, Origin(), newBodySum, bodySum); - loopReentry->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loopBody)); - - UpsilonValue* exitSum = loopExit->appendNew<UpsilonValue>(proc, Origin(), newBodySum); - loopExit->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation)); - - UpsilonValue* skipSum = loopSkip->appendNew<UpsilonValue>(proc, Origin(), startSum); - loopSkip->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(continuation)); - - Value* finalSum = continuation->appendNew<Value>(proc, Phi, Int32, Origin()); - exitSum->setPhi(finalSum); - skipSum->setPhi(finalSum); - - current = continuation; - vars[((i >> 1) + 0) % numVars] = finalSum; - } - } - - current->appendNew<ControlValue>(proc, Return, Origin(), vars[0]); - - compile(proc); - - double after = monotonicallyIncreasingTimeMS(); - dataLog(toCString(" That took ", after - before, " ms.\n")); -} - -void testSimplePatchpoint() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - CHECK(params[2].isGPR()); - add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testSimplePatchpointWithoutOuputClobbersGPArgs() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42); - Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13); - - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin()); - patchpoint->clobberLate(RegisterSet(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1)); - patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister)); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params[0].gpr()); - jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), params[1].gpr()); - jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR0); - jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), GPRInfo::argumentGPR1); - }); - - Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testSimplePatchpointWithOuputClobbersGPArgs() -{ - // We can't predict where the output will be but we want to be sure it is not - // one of the clobbered registers which is a bit hard to test. - // - // What we do is force the hand of our register allocator by clobbering absolutely - // everything but 1. The only valid allocation is to give it to the result and - // spill everything else. - - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* const1 = root->appendNew<Const64Value>(proc, Origin(), 42); - Value* const2 = root->appendNew<Const64Value>(proc, Origin(), 13); - - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int64, Origin()); - - RegisterSet clobberAll = RegisterSet::allGPRs(); - clobberAll.exclude(RegisterSet::stackRegisters()); - clobberAll.exclude(RegisterSet::reservedHardwareRegisters()); - clobberAll.clear(GPRInfo::argumentGPR2); - patchpoint->clobberLate(clobberAll); - - patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister)); - - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - CHECK(params[2].isGPR()); - jit.move(params[1].gpr(), params[0].gpr()); - jit.add64(params[2].gpr(), params[0].gpr()); - - clobberAll.forEach([&] (Reg reg) { - jit.move(CCallHelpers::TrustedImm32(0x00ff00ff), reg.gpr()); - }); - }); - - Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint, - root->appendNew<Value>(proc, Add, Origin(), arg1, arg2)); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int>(proc, 1, 2) == 58); -} - -void testSimplePatchpointWithoutOuputClobbersFPArgs() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5); - Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1); - - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin()); - patchpoint->clobberLate(RegisterSet(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1)); - patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister)); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isFPR()); - CHECK(params[1].isFPR()); - jit.moveZeroToDouble(params[0].fpr()); - jit.moveZeroToDouble(params[1].fpr()); - jit.moveZeroToDouble(FPRInfo::argumentFPR0); - jit.moveZeroToDouble(FPRInfo::argumentFPR1); - }); - - Value* result = root->appendNew<Value>(proc, Add, Origin(), arg1, arg2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 4); -} - -void testSimplePatchpointWithOuputClobbersFPArgs() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* const1 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5); - Value* const2 = root->appendNew<ConstDoubleValue>(proc, Origin(), 13.1); - - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin()); - - RegisterSet clobberAll = RegisterSet::allFPRs(); - clobberAll.exclude(RegisterSet::stackRegisters()); - clobberAll.exclude(RegisterSet::reservedHardwareRegisters()); - clobberAll.clear(FPRInfo::argumentFPR2); - patchpoint->clobberLate(clobberAll); - - patchpoint->append(ConstrainedValue(const1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(const2, ValueRep::SomeRegister)); - - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0].isFPR()); - CHECK(params[1].isFPR()); - CHECK(params[2].isFPR()); - jit.addDouble(params[1].fpr(), params[2].fpr(), params[0].fpr()); - - clobberAll.forEach([&] (Reg reg) { - jit.moveZeroToDouble(reg.fpr()); - }); - }); - - Value* result = root->appendNew<Value>(proc, Add, Origin(), patchpoint, - root->appendNew<Value>(proc, Add, Origin(), arg1, arg2)); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<double>(proc, 1.5, 2.5) == 59.6); -} - -void testPatchpointWithEarlyClobber() -{ - auto test = [] (GPRReg registerToClobber, bool arg1InArgGPR, bool arg2InArgGPR) { - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - patchpoint->clobberEarly(RegisterSet(registerToClobber)); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - CHECK((params[1].gpr() == GPRInfo::argumentGPR0) == arg1InArgGPR); - CHECK((params[2].gpr() == GPRInfo::argumentGPR1) == arg2InArgGPR); - - add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); - }); - - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); - }; - - test(GPRInfo::nonArgGPR0, true, true); - test(GPRInfo::argumentGPR0, false, true); - test(GPRInfo::argumentGPR1, true, false); -} - -void testPatchpointCallArg() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(ConstrainedValue(arg1, ValueRep::stackArgument(0))); - patchpoint->append(ConstrainedValue(arg2, ValueRep::stackArgument(8))); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0].isGPR()); - CHECK(params[1].isStack()); - CHECK(params[2].isStack()); - jit.load32( - CCallHelpers::Address(GPRInfo::callFrameRegister, params[1].offsetFromFP()), - params[0].gpr()); - jit.add32( - CCallHelpers::Address(GPRInfo::callFrameRegister, params[2].offsetFromFP()), - params[0].gpr()); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testPatchpointFixedRegister() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(ConstrainedValue(arg1, ValueRep(GPRInfo::regT0))); - patchpoint->append(ConstrainedValue(arg2, ValueRep(GPRInfo::regT1))); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0].isGPR()); - CHECK(params[1] == ValueRep(GPRInfo::regT0)); - CHECK(params[2] == ValueRep(GPRInfo::regT1)); - add32(jit, GPRInfo::regT0, GPRInfo::regT1, params[0].gpr()); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testPatchpointAny(ValueRep rep) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(ConstrainedValue(arg1, rep)); - patchpoint->append(ConstrainedValue(arg2, rep)); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - // We shouldn't have spilled the inputs, so we assert that they're in registers. - CHECK(params.size() == 3); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - CHECK(params[2].isGPR()); - add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testPatchpointGPScratch() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(arg1, ValueRep::SomeRegister); - patchpoint->append(arg2, ValueRep::SomeRegister); - patchpoint->numGPScratchRegisters = 2; - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - // We shouldn't have spilled the inputs, so we assert that they're in registers. - CHECK(params.size() == 3); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - CHECK(params[2].isGPR()); - CHECK(params.gpScratch(0) != InvalidGPRReg); - CHECK(params.gpScratch(0) != params[0].gpr()); - CHECK(params.gpScratch(0) != params[1].gpr()); - CHECK(params.gpScratch(0) != params[2].gpr()); - CHECK(params.gpScratch(1) != InvalidGPRReg); - CHECK(params.gpScratch(1) != params.gpScratch(0)); - CHECK(params.gpScratch(1) != params[0].gpr()); - CHECK(params.gpScratch(1) != params[1].gpr()); - CHECK(params.gpScratch(1) != params[2].gpr()); - CHECK(!params.unavailableRegisters().get(params.gpScratch(0))); - CHECK(!params.unavailableRegisters().get(params.gpScratch(1))); - add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testPatchpointFPScratch() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(arg1, ValueRep::SomeRegister); - patchpoint->append(arg2, ValueRep::SomeRegister); - patchpoint->numFPScratchRegisters = 2; - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - // We shouldn't have spilled the inputs, so we assert that they're in registers. - CHECK(params.size() == 3); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - CHECK(params[2].isGPR()); - CHECK(params.fpScratch(0) != InvalidFPRReg); - CHECK(params.fpScratch(1) != InvalidFPRReg); - CHECK(params.fpScratch(1) != params.fpScratch(0)); - CHECK(!params.unavailableRegisters().get(params.fpScratch(0))); - CHECK(!params.unavailableRegisters().get(params.fpScratch(1))); - add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testPatchpointLotsOfLateAnys() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Vector<int> things; - for (unsigned i = 200; i--;) - things.append(i); - - Vector<Value*> values; - for (int& thing : things) { - Value* value = root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &thing)); - values.append(value); - } - - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->clobber(RegisterSet::macroScratchRegisters()); - for (Value* value : values) - patchpoint->append(ConstrainedValue(value, ValueRep::LateColdAny)); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - // We shouldn't have spilled the inputs, so we assert that they're in registers. - CHECK(params.size() == things.size() + 1); - CHECK(params[0].isGPR()); - jit.move(CCallHelpers::TrustedImm32(0), params[0].gpr()); - for (unsigned i = 1; i < params.size(); ++i) { - if (params[i].isGPR()) { - CHECK(params[i] != params[0]); - jit.add32(params[i].gpr(), params[0].gpr()); - } else { - CHECK(params[i].isStack()); - jit.add32(CCallHelpers::Address(GPRInfo::callFrameRegister, params[i].offsetFromFP()), params[0].gpr()); - } - } - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc) == (things.size() * (things.size() - 1)) / 2); -} - -void testPatchpointAnyImm(ValueRep rep) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(ConstrainedValue(arg1, rep)); - patchpoint->append(ConstrainedValue(arg2, rep)); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - CHECK(params[2].isConstant()); - CHECK(params[2].value() == 42); - jit.add32( - CCallHelpers::TrustedImm32(static_cast<int32_t>(params[2].value())), - params[1].gpr(), params[0].gpr()); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1) == 43); -} - -void testPatchpointManyImms() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), 42); - Value* arg2 = root->appendNew<Const64Value>(proc, Origin(), 43); - Value* arg3 = root->appendNew<Const64Value>(proc, Origin(), 43000000000000ll); - Value* arg4 = root->appendNew<ConstDoubleValue>(proc, Origin(), 42.5); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Void, Origin()); - patchpoint->append(ConstrainedValue(arg1, ValueRep::WarmAny)); - patchpoint->append(ConstrainedValue(arg2, ValueRep::WarmAny)); - patchpoint->append(ConstrainedValue(arg3, ValueRep::WarmAny)); - patchpoint->append(ConstrainedValue(arg4, ValueRep::WarmAny)); - patchpoint->setGenerator( - [&] (CCallHelpers&, const StackmapGenerationParams& params) { - CHECK(params.size() == 4); - CHECK(params[0] == ValueRep::constant(42)); - CHECK(params[1] == ValueRep::constant(43)); - CHECK(params[2] == ValueRep::constant(43000000000000ll)); - CHECK(params[3] == ValueRep::constant(bitwise_cast<int64_t>(42.5))); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(!compileAndRun<int>(proc)); -} - -void testPatchpointWithRegisterResult() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - patchpoint->resultConstraint = ValueRep::reg(GPRInfo::nonArgGPR0); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0] == ValueRep::reg(GPRInfo::nonArgGPR0)); - CHECK(params[1].isGPR()); - CHECK(params[2].isGPR()); - add32(jit, params[1].gpr(), params[2].gpr(), GPRInfo::nonArgGPR0); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testPatchpointWithStackArgumentResult() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - patchpoint->resultConstraint = ValueRep::stackArgument(0); - patchpoint->clobber(RegisterSet::macroScratchRegisters()); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0] == ValueRep::stack(-static_cast<intptr_t>(proc.frameSize()))); - CHECK(params[1].isGPR()); - CHECK(params[2].isGPR()); - jit.add32(params[1].gpr(), params[2].gpr(), jit.scratchRegister()); - jit.store32(jit.scratchRegister(), CCallHelpers::Address(CCallHelpers::stackPointerRegister, 0)); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<int>(proc, 1, 2) == 3); -} - -void testPatchpointWithAnyResult() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin()); - patchpoint->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - patchpoint->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - patchpoint->resultConstraint = ValueRep::WarmAny; - patchpoint->clobberLate(RegisterSet::allFPRs()); - patchpoint->clobber(RegisterSet::macroScratchRegisters()); - patchpoint->clobber(RegisterSet(GPRInfo::regT0)); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 3); - CHECK(params[0].isStack()); - CHECK(params[1].isGPR()); - CHECK(params[2].isGPR()); - add32(jit, params[1].gpr(), params[2].gpr(), GPRInfo::regT0); - jit.convertInt32ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0); - jit.storeDouble(FPRInfo::fpRegT0, CCallHelpers::Address(GPRInfo::callFrameRegister, params[0].offsetFromFP())); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - CHECK(compileAndRun<double>(proc, 1, 2) == 3); -} - -void testSimpleCheck() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - CheckValue* check = root->appendNew<CheckValue>(proc, Check, Origin(), arg); - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - - CHECK(invoke<int>(*code, 0) == 0); - CHECK(invoke<int>(*code, 1) == 42); -} - -void testCheckFalse() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - CheckValue* check = root->appendNew<CheckValue>( - proc, Check, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - check->setGenerator( - [&] (CCallHelpers&, const StackmapGenerationParams&) { - CHECK(!"This should not have executed"); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - - CHECK(invoke<int>(*code) == 0); -} - -void testCheckTrue() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - CheckValue* check = root->appendNew<CheckValue>( - proc, Check, Origin(), root->appendNew<Const32Value>(proc, Origin(), 1)); - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.value()->opcode() == Patchpoint); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - - CHECK(invoke<int>(*code) == 42); -} - -void testCheckLessThan() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - CheckValue* check = root->appendNew<CheckValue>( - proc, Check, Origin(), - root->appendNew<Value>( - proc, LessThan, Origin(), arg, - root->appendNew<Const32Value>(proc, Origin(), 42))); - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - - CHECK(invoke<int>(*code, 42) == 0); - CHECK(invoke<int>(*code, 1000) == 0); - CHECK(invoke<int>(*code, 41) == 42); - CHECK(invoke<int>(*code, 0) == 42); - CHECK(invoke<int>(*code, -1) == 42); -} - -void testCheckMegaCombo() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* index = root->appendNew<Value>( - proc, ZExt32, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - Value* ptr = root->appendNew<Value>( - proc, Add, Origin(), base, - root->appendNew<Value>( - proc, Shl, Origin(), index, - root->appendNew<Const32Value>(proc, Origin(), 1))); - - CheckValue* check = root->appendNew<CheckValue>( - proc, Check, Origin(), - root->appendNew<Value>( - proc, LessThan, Origin(), - root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr), - root->appendNew<Const32Value>(proc, Origin(), 42))); - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - - int8_t value; - value = 42; - CHECK(invoke<int>(*code, &value - 2, 1) == 0); - value = 127; - CHECK(invoke<int>(*code, &value - 2, 1) == 0); - value = 41; - CHECK(invoke<int>(*code, &value - 2, 1) == 42); - value = 0; - CHECK(invoke<int>(*code, &value - 2, 1) == 42); - value = -1; - CHECK(invoke<int>(*code, &value - 2, 1) == 42); -} - -void testCheckTrickyMegaCombo() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* index = root->appendNew<Value>( - proc, ZExt32, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)), - root->appendNew<Const32Value>(proc, Origin(), 1))); - - Value* ptr = root->appendNew<Value>( - proc, Add, Origin(), base, - root->appendNew<Value>( - proc, Shl, Origin(), index, - root->appendNew<Const32Value>(proc, Origin(), 1))); - - CheckValue* check = root->appendNew<CheckValue>( - proc, Check, Origin(), - root->appendNew<Value>( - proc, LessThan, Origin(), - root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr), - root->appendNew<Const32Value>(proc, Origin(), 42))); - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - - int8_t value; - value = 42; - CHECK(invoke<int>(*code, &value - 2, 0) == 0); - value = 127; - CHECK(invoke<int>(*code, &value - 2, 0) == 0); - value = 41; - CHECK(invoke<int>(*code, &value - 2, 0) == 42); - value = 0; - CHECK(invoke<int>(*code, &value - 2, 0) == 42); - value = -1; - CHECK(invoke<int>(*code, &value - 2, 0) == 42); -} - -void testCheckTwoMegaCombos() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* index = root->appendNew<Value>( - proc, ZExt32, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - Value* ptr = root->appendNew<Value>( - proc, Add, Origin(), base, - root->appendNew<Value>( - proc, Shl, Origin(), index, - root->appendNew<Const32Value>(proc, Origin(), 1))); - - Value* predicate = root->appendNew<Value>( - proc, LessThan, Origin(), - root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr), - root->appendNew<Const32Value>(proc, Origin(), 42)); - - CheckValue* check = root->appendNew<CheckValue>(proc, Check, Origin(), predicate); - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - CheckValue* check2 = root->appendNew<CheckValue>(proc, Check, Origin(), predicate); - check2->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(43), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - - int8_t value; - value = 42; - CHECK(invoke<int>(*code, &value - 2, 1) == 0); - value = 127; - CHECK(invoke<int>(*code, &value - 2, 1) == 0); - value = 41; - CHECK(invoke<int>(*code, &value - 2, 1) == 42); - value = 0; - CHECK(invoke<int>(*code, &value - 2, 1) == 42); - value = -1; - CHECK(invoke<int>(*code, &value - 2, 1) == 42); -} - -void testCheckTwoNonRedundantMegaCombos() -{ - Procedure proc; - - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* index = root->appendNew<Value>( - proc, ZExt32, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* branchPredicate = root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)), - root->appendNew<Const32Value>(proc, Origin(), 0xff)); - - Value* ptr = root->appendNew<Value>( - proc, Add, Origin(), base, - root->appendNew<Value>( - proc, Shl, Origin(), index, - root->appendNew<Const32Value>(proc, Origin(), 1))); - - Value* checkPredicate = root->appendNew<Value>( - proc, LessThan, Origin(), - root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr), - root->appendNew<Const32Value>(proc, Origin(), 42)); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), branchPredicate, - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - CheckValue* check = thenCase->appendNew<CheckValue>(proc, Check, Origin(), checkPredicate); - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), thenCase->appendNew<Const32Value>(proc, Origin(), 43)); - - CheckValue* check2 = elseCase->appendNew<CheckValue>(proc, Check, Origin(), checkPredicate); - check2->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(!params.size()); - - // This should always work because a function this simple should never have callee - // saves. - jit.move(CCallHelpers::TrustedImm32(44), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), elseCase->appendNew<Const32Value>(proc, Origin(), 45)); - - auto code = compile(proc); - - int8_t value; - - value = 42; - CHECK(invoke<int>(*code, &value - 2, 1, true) == 43); - value = 127; - CHECK(invoke<int>(*code, &value - 2, 1, true) == 43); - value = 41; - CHECK(invoke<int>(*code, &value - 2, 1, true) == 42); - value = 0; - CHECK(invoke<int>(*code, &value - 2, 1, true) == 42); - value = -1; - CHECK(invoke<int>(*code, &value - 2, 1, true) == 42); - - value = 42; - CHECK(invoke<int>(*code, &value - 2, 1, false) == 45); - value = 127; - CHECK(invoke<int>(*code, &value - 2, 1, false) == 45); - value = 41; - CHECK(invoke<int>(*code, &value - 2, 1, false) == 44); - value = 0; - CHECK(invoke<int>(*code, &value - 2, 1, false) == 44); - value = -1; - CHECK(invoke<int>(*code, &value - 2, 1, false) == 44); -} - -void testCheckAddImm() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2); - checkAdd->append(arg1); - checkAdd->append(arg2); - checkAdd->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isConstant()); - CHECK(params[1].value() == 42); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1); - jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkAdd)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0) == 42.0); - CHECK(invoke<double>(*code, 1) == 43.0); - CHECK(invoke<double>(*code, 42) == 84.0); - CHECK(invoke<double>(*code, 2147483647) == 2147483689.0); -} - -void testCheckAddImmCommute() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg2, arg1); - checkAdd->append(arg1); - checkAdd->append(arg2); - checkAdd->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isConstant()); - CHECK(params[1].value() == 42); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1); - jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkAdd)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0) == 42.0); - CHECK(invoke<double>(*code, 1) == 43.0); - CHECK(invoke<double>(*code, 42) == 84.0); - CHECK(invoke<double>(*code, 2147483647) == 2147483689.0); -} - -void testCheckAddImmSomeRegister() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2); - checkAdd->appendSomeRegister(arg1); - checkAdd->appendSomeRegister(arg2); - checkAdd->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkAdd)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0) == 42.0); - CHECK(invoke<double>(*code, 1) == 43.0); - CHECK(invoke<double>(*code, 42) == 84.0); - CHECK(invoke<double>(*code, 2147483647) == 2147483689.0); -} - -void testCheckAdd() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2); - checkAdd->appendSomeRegister(arg1); - checkAdd->appendSomeRegister(arg2); - checkAdd->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkAdd)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0, 42) == 42.0); - CHECK(invoke<double>(*code, 1, 42) == 43.0); - CHECK(invoke<double>(*code, 42, 42) == 84.0); - CHECK(invoke<double>(*code, 2147483647, 42) == 2147483689.0); -} - -void testCheckAdd64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2); - checkAdd->appendSomeRegister(arg1); - checkAdd->appendSomeRegister(arg2); - checkAdd->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt64ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkAdd)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0ll, 42ll) == 42.0); - CHECK(invoke<double>(*code, 1ll, 42ll) == 43.0); - CHECK(invoke<double>(*code, 42ll, 42ll) == 84.0); - CHECK(invoke<double>(*code, 9223372036854775807ll, 42ll) == static_cast<double>(9223372036854775807ll) + 42.0); -} - -void testCheckAddFold(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2); - checkAdd->setGenerator( - [&] (CCallHelpers&, const StackmapGenerationParams&) { - CHECK(!"Should have been folded"); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), checkAdd); - - auto code = compile(proc); - - CHECK(invoke<int>(*code) == a + b); -} - -void testCheckAddFoldFail(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2); - checkAdd->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams&) { - AllowMacroScratchRegisterUsage allowScratch(jit); - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), checkAdd); - - auto code = compile(proc); - - CHECK(invoke<int>(*code) == 42); -} - -void testCheckAddArgumentAliasing64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - - // Pretend to use all the args. - PatchpointValue* useArgs = root->appendNew<PatchpointValue>(proc, Void, Origin()); - useArgs->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - useArgs->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - useArgs->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); - useArgs->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - // Last use of first arg (here, arg1). - CheckValue* checkAdd1 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2); - checkAdd1->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - // Last use of second arg (here, arg2). - CheckValue* checkAdd2 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg3, arg2); - checkAdd2->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - // Keep arg3 live. - PatchpointValue* keepArg2Live = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepArg2Live->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepArg2Live->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - // Only use of checkAdd1 and checkAdd2. - CheckValue* checkAdd3 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), checkAdd1, checkAdd2); - checkAdd3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - root->appendNew<ControlValue>(proc, Return, Origin(), checkAdd3); - - CHECK(compileAndRun<int64_t>(proc, 1, 2, 3) == 8); -} - -void testCheckAddArgumentAliasing32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* arg3 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)); - - // Pretend to use all the args. - PatchpointValue* useArgs = root->appendNew<PatchpointValue>(proc, Void, Origin()); - useArgs->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - useArgs->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - useArgs->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); - useArgs->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - // Last use of first arg (here, arg1). - CheckValue* checkAdd1 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg1, arg2); - checkAdd1->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - // Last use of second arg (here, arg3). - CheckValue* checkAdd2 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg2, arg3); - checkAdd2->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - // Keep arg3 live. - PatchpointValue* keepArg2Live = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepArg2Live->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepArg2Live->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - // Only use of checkAdd1 and checkAdd2. - CheckValue* checkAdd3 = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), checkAdd1, checkAdd2); - checkAdd3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - root->appendNew<ControlValue>(proc, Return, Origin(), checkAdd3); - - CHECK(compileAndRun<int32_t>(proc, 1, 2, 3) == 8); -} - -void testCheckAddSelfOverflow64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg, arg); - checkAdd->append(arg); - checkAdd->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - jit.move(params[0].gpr(), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - - // Make sure the arg is not the destination of the operation. - PatchpointValue* opaqueUse = root->appendNew<PatchpointValue>(proc, Void, Origin()); - opaqueUse->append(ConstrainedValue(arg, ValueRep::SomeRegister)); - opaqueUse->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), checkAdd); - - auto code = compile(proc); - - CHECK(invoke<int64_t>(*code, 0ll) == 0); - CHECK(invoke<int64_t>(*code, 1ll) == 2); - CHECK(invoke<int64_t>(*code, std::numeric_limits<int64_t>::max()) == std::numeric_limits<int64_t>::max()); -} - -void testCheckAddSelfOverflow32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - CheckValue* checkAdd = root->appendNew<CheckValue>(proc, CheckAdd, Origin(), arg, arg); - checkAdd->append(arg); - checkAdd->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - jit.move(params[0].gpr(), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - - // Make sure the arg is not the destination of the operation. - PatchpointValue* opaqueUse = root->appendNew<PatchpointValue>(proc, Void, Origin()); - opaqueUse->append(ConstrainedValue(arg, ValueRep::SomeRegister)); - opaqueUse->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), checkAdd); - - auto code = compile(proc); - - CHECK(invoke<int32_t>(*code, 0ll) == 0); - CHECK(invoke<int32_t>(*code, 1ll) == 2); - CHECK(invoke<int32_t>(*code, std::numeric_limits<int32_t>::max()) == std::numeric_limits<int32_t>::max()); -} - -void testCheckSubImm() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 42); - CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2); - checkSub->append(arg1); - checkSub->append(arg2); - checkSub->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isConstant()); - CHECK(params[1].value() == 42); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(42), FPRInfo::fpRegT1); - jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkSub)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0) == -42.0); - CHECK(invoke<double>(*code, 1) == -41.0); - CHECK(invoke<double>(*code, 42) == 0.0); - CHECK(invoke<double>(*code, -2147483647) == -2147483689.0); -} - -void testCheckSubBadImm() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - int32_t badImm = std::numeric_limits<int>::min(); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), badImm); - CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2); - checkSub->append(arg1); - checkSub->append(arg2); - checkSub->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - - if (params[1].isConstant()) { - CHECK(params[1].value() == badImm); - jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(badImm), FPRInfo::fpRegT1); - } else { - CHECK(params[1].isGPR()); - jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - } - jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkSub)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0) == -static_cast<double>(badImm)); - CHECK(invoke<double>(*code, -1) == -static_cast<double>(badImm) - 1); - CHECK(invoke<double>(*code, 1) == -static_cast<double>(badImm) + 1); - CHECK(invoke<double>(*code, 42) == -static_cast<double>(badImm) + 42); -} - -void testCheckSub() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2); - checkSub->append(arg1); - checkSub->append(arg2); - checkSub->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkSub)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0, 42) == -42.0); - CHECK(invoke<double>(*code, 1, 42) == -41.0); - CHECK(invoke<double>(*code, 42, 42) == 0.0); - CHECK(invoke<double>(*code, -2147483647, 42) == -2147483689.0); -} - -NEVER_INLINE double doubleSub(double a, double b) -{ - return a - b; -} - -void testCheckSub64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2); - checkSub->append(arg1); - checkSub->append(arg2); - checkSub->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt64ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkSub)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0ll, 42ll) == -42.0); - CHECK(invoke<double>(*code, 1ll, 42ll) == -41.0); - CHECK(invoke<double>(*code, 42ll, 42ll) == 0.0); - CHECK(invoke<double>(*code, -9223372036854775807ll, 42ll) == doubleSub(static_cast<double>(-9223372036854775807ll), 42.0)); -} - -void testCheckSubFold(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b); - CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2); - checkSub->setGenerator( - [&] (CCallHelpers&, const StackmapGenerationParams&) { - CHECK(!"Should have been folded"); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), checkSub); - - auto code = compile(proc); - - CHECK(invoke<int>(*code) == a - b); -} - -void testCheckSubFoldFail(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b); - CheckValue* checkSub = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2); - checkSub->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams&) { - AllowMacroScratchRegisterUsage allowScratch(jit); - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), checkSub); - - auto code = compile(proc); - - CHECK(invoke<int>(*code) == 42); -} - -void testCheckNeg() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), 0); - Value* arg2 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - CheckValue* checkNeg = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2); - checkNeg->append(arg2); - checkNeg->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 1); - CHECK(params[0].isGPR()); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT1); - jit.negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkNeg)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0) == 0.0); - CHECK(invoke<double>(*code, 1) == -1.0); - CHECK(invoke<double>(*code, 42) == -42.0); - CHECK(invoke<double>(*code, -2147483647 - 1) == 2147483648.0); -} - -void testCheckNeg64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const64Value>(proc, Origin(), 0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - CheckValue* checkNeg = root->appendNew<CheckValue>(proc, CheckSub, Origin(), arg1, arg2); - checkNeg->append(arg2); - checkNeg->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 1); - CHECK(params[0].isGPR()); - jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT1); - jit.negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkNeg)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0ll) == 0.0); - CHECK(invoke<double>(*code, 1ll) == -1.0); - CHECK(invoke<double>(*code, 42ll) == -42.0); - CHECK(invoke<double>(*code, -9223372036854775807ll - 1) == 9223372036854775808.0); -} - -void testCheckMul() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul->append(arg1); - checkMul->append(arg2); - checkMul->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkMul)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0, 42) == 0.0); - CHECK(invoke<double>(*code, 1, 42) == 42.0); - CHECK(invoke<double>(*code, 42, 42) == 42.0 * 42.0); - CHECK(invoke<double>(*code, 2147483647, 42) == 2147483647.0 * 42.0); -} - -void testCheckMulMemory() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - int left; - int right; - - Value* arg1 = root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &left)); - Value* arg2 = root->appendNew<MemoryValue>( - proc, Load, Int32, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), &right)); - CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul->append(arg1); - checkMul->append(arg2); - checkMul->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkMul)); - - auto code = compile(proc); - - left = 0; - right = 42; - CHECK(invoke<double>(*code) == 0.0); - - left = 1; - right = 42; - CHECK(invoke<double>(*code) == 42.0); - - left = 42; - right = 42; - CHECK(invoke<double>(*code) == 42.0 * 42.0); - - left = 2147483647; - right = 42; - CHECK(invoke<double>(*code) == 2147483647.0 * 42.0); -} - -void testCheckMul2() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), 2); - CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul->append(arg1); - checkMul->append(arg2); - checkMul->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isConstant()); - CHECK(params[1].value() == 2); - jit.convertInt32ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt32ToDouble(CCallHelpers::TrustedImm32(2), FPRInfo::fpRegT1); - jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkMul)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0) == 0.0); - CHECK(invoke<double>(*code, 1) == 2.0); - CHECK(invoke<double>(*code, 42) == 42.0 * 2.0); - CHECK(invoke<double>(*code, 2147483647) == 2147483647.0 * 2.0); -} - -void testCheckMul64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul->append(arg1); - checkMul->append(arg2); - checkMul->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt64ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkMul)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0, 42) == 0.0); - CHECK(invoke<double>(*code, 1, 42) == 42.0); - CHECK(invoke<double>(*code, 42, 42) == 42.0 * 42.0); - CHECK(invoke<double>(*code, 9223372036854775807ll, 42) == static_cast<double>(9223372036854775807ll) * 42.0); -} - -void testCheckMulFold(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b); - CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul->setGenerator( - [&] (CCallHelpers&, const StackmapGenerationParams&) { - CHECK(!"Should have been folded"); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), checkMul); - - auto code = compile(proc); - - CHECK(invoke<int>(*code) == a * b); -} - -void testCheckMulFoldFail(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Const32Value>(proc, Origin(), a); - Value* arg2 = root->appendNew<Const32Value>(proc, Origin(), b); - CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams&) { - AllowMacroScratchRegisterUsage allowScratch(jit); - jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>(proc, Return, Origin(), checkMul); - - auto code = compile(proc); - - CHECK(invoke<int>(*code) == 42); -} - -void testCheckMulArgumentAliasing64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - - // Pretend to use all the args. - PatchpointValue* useArgs = root->appendNew<PatchpointValue>(proc, Void, Origin()); - useArgs->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - useArgs->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - useArgs->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); - useArgs->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - // Last use of first arg (here, arg1). - CheckValue* checkMul1 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul1->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - // Last use of second arg (here, arg2). - CheckValue* checkMul2 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg3, arg2); - checkMul2->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - // Keep arg3 live. - PatchpointValue* keepArg2Live = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepArg2Live->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepArg2Live->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - // Only use of checkMul1 and checkMul2. - CheckValue* checkMul3 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), checkMul1, checkMul2); - checkMul3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - root->appendNew<ControlValue>(proc, Return, Origin(), checkMul3); - - CHECK(compileAndRun<int64_t>(proc, 2, 3, 4) == 72); -} - -void testCheckMulArgumentAliasing32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* arg3 = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)); - - // Pretend to use all the args. - PatchpointValue* useArgs = root->appendNew<PatchpointValue>(proc, Void, Origin()); - useArgs->append(ConstrainedValue(arg1, ValueRep::SomeRegister)); - useArgs->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - useArgs->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); - useArgs->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - // Last use of first arg (here, arg1). - CheckValue* checkMul1 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul1->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - // Last use of second arg (here, arg3). - CheckValue* checkMul2 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg2, arg3); - checkMul2->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - // Keep arg3 live. - PatchpointValue* keepArg2Live = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepArg2Live->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepArg2Live->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - // Only use of checkMul1 and checkMul2. - CheckValue* checkMul3 = root->appendNew<CheckValue>(proc, CheckMul, Origin(), checkMul1, checkMul2); - checkMul3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - - root->appendNew<ControlValue>(proc, Return, Origin(), checkMul3); - - CHECK(compileAndRun<int32_t>(proc, 2, 3, 4) == 72); -} - -void testCheckMul64SShr() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg1 = root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const32Value>(proc, Origin(), 1)); - Value* arg2 = root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1), - root->appendNew<Const32Value>(proc, Origin(), 1)); - CheckValue* checkMul = root->appendNew<CheckValue>(proc, CheckMul, Origin(), arg1, arg2); - checkMul->append(arg1); - checkMul->append(arg2); - checkMul->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 2); - CHECK(params[0].isGPR()); - CHECK(params[1].isGPR()); - jit.convertInt64ToDouble(params[0].gpr(), FPRInfo::fpRegT0); - jit.convertInt64ToDouble(params[1].gpr(), FPRInfo::fpRegT1); - jit.mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, IToD, Origin(), checkMul)); - - auto code = compile(proc); - - CHECK(invoke<double>(*code, 0ll, 42ll) == 0.0); - CHECK(invoke<double>(*code, 1ll, 42ll) == 0.0); - CHECK(invoke<double>(*code, 42ll, 42ll) == (42.0 / 2.0) * (42.0 / 2.0)); - CHECK(invoke<double>(*code, 10000000000ll, 10000000000ll) == 25000000000000000000.0); -} - -template<typename LeftFunctor, typename RightFunctor, typename InputType> -void genericTestCompare( - B3::Opcode opcode, const LeftFunctor& leftFunctor, const RightFunctor& rightFunctor, - InputType left, InputType right, int result) -{ - // Using a compare. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* leftValue = leftFunctor(root, proc); - Value* rightValue = rightFunctor(root, proc); - Value* comparisonResult = root->appendNew<Value>(proc, opcode, Origin(), leftValue, rightValue); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, NotEqual, Origin(), - comparisonResult, - root->appendIntConstant(proc, Origin(), comparisonResult->type(), 0))); - - CHECK(compileAndRun<int>(proc, left, right) == result); - } - - // Using a branch. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* leftValue = leftFunctor(root, proc); - Value* rightValue = rightFunctor(root, proc); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), leftValue, rightValue), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - // We use a patchpoint on the then case to ensure that this doesn't get if-converted. - PatchpointValue* patchpoint = thenCase->appendNew<PatchpointValue>(proc, Int32, Origin()); - patchpoint->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - CHECK(params.size() == 1); - CHECK(params[0].isGPR()); - jit.move(CCallHelpers::TrustedImm32(1), params[0].gpr()); - }); - thenCase->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<Const32Value>(proc, Origin(), 0)); - - CHECK(compileAndRun<int>(proc, left, right) == result); - } -} - -template<typename InputType> -InputType modelCompare(B3::Opcode opcode, InputType left, InputType right) -{ - switch (opcode) { - case Equal: - return left == right; - case NotEqual: - return left != right; - case LessThan: - return left < right; - case GreaterThan: - return left > right; - case LessEqual: - return left <= right; - case GreaterEqual: - return left >= right; - case Above: - return static_cast<typename std::make_unsigned<InputType>::type>(left) > - static_cast<typename std::make_unsigned<InputType>::type>(right); - case Below: - return static_cast<typename std::make_unsigned<InputType>::type>(left) < - static_cast<typename std::make_unsigned<InputType>::type>(right); - case AboveEqual: - return static_cast<typename std::make_unsigned<InputType>::type>(left) >= - static_cast<typename std::make_unsigned<InputType>::type>(right); - case BelowEqual: - return static_cast<typename std::make_unsigned<InputType>::type>(left) <= - static_cast<typename std::make_unsigned<InputType>::type>(right); - case BitAnd: - return !!(left & right); - default: - RELEASE_ASSERT_NOT_REACHED(); - return 0; - } -} - -template<typename T> -void testCompareLoad(B3::Opcode opcode, B3::Opcode loadOpcode, int left, int right) -{ - int result = modelCompare(opcode, modelLoad<T>(left), right); - - // Test addr-to-tmp - int slot = left; - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<MemoryValue>( - proc, loadOpcode, Int32, Origin(), - block->appendNew<ConstPtrValue>(proc, Origin(), &slot)); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Value>( - proc, Trunc, Origin(), - block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - }, - left, right, result); - - // Test addr-to-imm - slot = left; - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<MemoryValue>( - proc, loadOpcode, Int32, Origin(), - block->appendNew<ConstPtrValue>(proc, Origin(), &slot)); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const32Value>(proc, Origin(), right); - }, - left, right, result); - - result = modelCompare(opcode, left, modelLoad<T>(right)); - - // Test tmp-to-addr - slot = right; - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Value>( - proc, Trunc, Origin(), - block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<MemoryValue>( - proc, loadOpcode, Int32, Origin(), - block->appendNew<ConstPtrValue>(proc, Origin(), &slot)); - }, - left, right, result); - - // Test imm-to-addr - slot = right; - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const32Value>(proc, Origin(), left); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<MemoryValue>( - proc, loadOpcode, Int32, Origin(), - block->appendNew<ConstPtrValue>(proc, Origin(), &slot)); - }, - left, right, result); - - // Test addr-to-addr, with the same addr. - slot = left; - Value* value; - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - value = block->appendNew<MemoryValue>( - proc, loadOpcode, Int32, Origin(), - block->appendNew<ConstPtrValue>(proc, Origin(), &slot)); - return value; - }, - [&] (BasicBlock*, Procedure&) { - return value; - }, - left, left, modelCompare(opcode, modelLoad<T>(left), modelLoad<T>(left))); -} - -void testCompareImpl(B3::Opcode opcode, int64_t left, int64_t right) -{ - int64_t result = modelCompare(opcode, left, right); - int32_t int32Result = modelCompare(opcode, static_cast<int32_t>(left), static_cast<int32_t>(right)); - - // Test tmp-to-tmp. - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - }, - left, right, result); - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Value>( - proc, Trunc, Origin(), - block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Value>( - proc, Trunc, Origin(), - block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - }, - left, right, int32Result); - - // Test imm-to-tmp. - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const64Value>(proc, Origin(), left); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - }, - left, right, result); - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const32Value>(proc, Origin(), left); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Value>( - proc, Trunc, Origin(), - block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - }, - left, right, int32Result); - - // Test tmp-to-imm. - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const64Value>(proc, Origin(), right); - }, - left, right, result); - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Value>( - proc, Trunc, Origin(), - block->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const32Value>(proc, Origin(), right); - }, - left, right, int32Result); - - // Test imm-to-imm. - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const64Value>(proc, Origin(), left); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const64Value>(proc, Origin(), right); - }, - left, right, result); - genericTestCompare( - opcode, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const32Value>(proc, Origin(), left); - }, - [&] (BasicBlock* block, Procedure& proc) { - return block->appendNew<Const32Value>(proc, Origin(), right); - }, - left, right, int32Result); - - testCompareLoad<int32_t>(opcode, Load, left, right); - testCompareLoad<int8_t>(opcode, Load8S, left, right); - testCompareLoad<uint8_t>(opcode, Load8Z, left, right); - testCompareLoad<int16_t>(opcode, Load16S, left, right); - testCompareLoad<uint16_t>(opcode, Load16Z, left, right); -} - -void testCompare(B3::Opcode opcode, int64_t left, int64_t right) -{ - testCompareImpl(opcode, left, right); - testCompareImpl(opcode, left, right + 1); - testCompareImpl(opcode, left, right - 1); -} - -void testEqualDouble(double left, double right, bool result) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1))); - - CHECK(compileAndRun<bool>(proc, left, right) == result); -} - -int simpleFunction(int a, int b) -{ - return a + b; -} - -void testCallSimple(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<CCallValue>( - proc, Int32, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(simpleFunction)), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int>(proc, a, b) == a + b); -} - -void testCallRare(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* common = proc.addBlock(); - BasicBlock* rare = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(rare, FrequencyClass::Rare), - FrequentedBlock(common)); - - common->appendNew<ControlValue>( - proc, Return, Origin(), common->appendNew<Const32Value>(proc, Origin(), 0)); - - rare->appendNew<ControlValue>( - proc, Return, Origin(), - rare->appendNew<CCallValue>( - proc, Int32, Origin(), - rare->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(simpleFunction)), - rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1), - rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - - CHECK(compileAndRun<int>(proc, true, a, b) == a + b); -} - -void testCallRareLive(int a, int b, int c) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* common = proc.addBlock(); - BasicBlock* rare = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(rare, FrequencyClass::Rare), - FrequentedBlock(common)); - - common->appendNew<ControlValue>( - proc, Return, Origin(), common->appendNew<Const32Value>(proc, Origin(), 0)); - - rare->appendNew<ControlValue>( - proc, Return, Origin(), - rare->appendNew<Value>( - proc, Add, Origin(), - rare->appendNew<CCallValue>( - proc, Int32, Origin(), - rare->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(simpleFunction)), - rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1), - rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)), - rare->appendNew<Value>( - proc, Trunc, Origin(), - rare->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)))); - - CHECK(compileAndRun<int>(proc, true, a, b, c) == a + b + c); -} - -void testCallSimplePure(int a, int b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<CCallValue>( - proc, Int32, Origin(), Effects::none(), - root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(simpleFunction)), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int>(proc, a, b) == a + b); -} - -int functionWithHellaArguments(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, int n, int o, int p, int q, int r, int s, int t, int u, int v, int w, int x, int y, int z) -{ - return (a << 0) + (b << 1) + (c << 2) + (d << 3) + (e << 4) + (f << 5) + (g << 6) + (h << 7) + (i << 8) + (j << 9) + (k << 10) + (l << 11) + (m << 12) + (n << 13) + (o << 14) + (p << 15) + (q << 16) + (r << 17) + (s << 18) + (t << 19) + (u << 20) + (v << 21) + (w << 22) + (x << 23) + (y << 24) + (z << 25); -} - -void testCallFunctionWithHellaArguments() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Vector<Value*> args; - for (unsigned i = 0; i < 26; ++i) - args.append(root->appendNew<Const32Value>(proc, Origin(), i + 1)); - - CCallValue* call = root->appendNew<CCallValue>( - proc, Int32, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(functionWithHellaArguments))); - call->children().appendVector(args); - - root->appendNew<ControlValue>(proc, Return, Origin(), call); - - CHECK(compileAndRun<int>(proc) == functionWithHellaArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)); -} - -void testReturnDouble(double value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<ConstDoubleValue>(proc, Origin(), value)); - - CHECK(isIdentical(compileAndRun<double>(proc), value)); -} - -void testReturnFloat(float value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<ConstFloatValue>(proc, Origin(), value)); - - CHECK(isIdentical(compileAndRun<float>(proc), value)); -} - -double simpleFunctionDouble(double a, double b) -{ - return a + b; -} - -void testCallSimpleDouble(double a, double b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<CCallValue>( - proc, Double, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(simpleFunctionDouble)), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1))); - - CHECK(compileAndRun<double>(proc, a, b) == a + b); -} - -float simpleFunctionFloat(float a, float b) -{ - return a + b; -} - -void testCallSimpleFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<CCallValue>( - proc, Float, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(simpleFunctionFloat)), - floatValue1, - floatValue2)); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), a + b)); -} - -double functionWithHellaDoubleArguments(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j, double k, double l, double m, double n, double o, double p, double q, double r, double s, double t, double u, double v, double w, double x, double y, double z) -{ - return a * pow(2, 0) + b * pow(2, 1) + c * pow(2, 2) + d * pow(2, 3) + e * pow(2, 4) + f * pow(2, 5) + g * pow(2, 6) + h * pow(2, 7) + i * pow(2, 8) + j * pow(2, 9) + k * pow(2, 10) + l * pow(2, 11) + m * pow(2, 12) + n * pow(2, 13) + o * pow(2, 14) + p * pow(2, 15) + q * pow(2, 16) + r * pow(2, 17) + s * pow(2, 18) + t * pow(2, 19) + u * pow(2, 20) + v * pow(2, 21) + w * pow(2, 22) + x * pow(2, 23) + y * pow(2, 24) + z * pow(2, 25); -} - -void testCallFunctionWithHellaDoubleArguments() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Vector<Value*> args; - for (unsigned i = 0; i < 26; ++i) - args.append(root->appendNew<ConstDoubleValue>(proc, Origin(), i + 1)); - - CCallValue* call = root->appendNew<CCallValue>( - proc, Double, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(functionWithHellaDoubleArguments))); - call->children().appendVector(args); - - root->appendNew<ControlValue>(proc, Return, Origin(), call); - - CHECK(compileAndRun<double>(proc) == functionWithHellaDoubleArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)); -} - -float functionWithHellaFloatArguments(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p, float q, float r, float s, float t, float u, float v, float w, float x, float y, float z) -{ - return a * pow(2, 0) + b * pow(2, 1) + c * pow(2, 2) + d * pow(2, 3) + e * pow(2, 4) + f * pow(2, 5) + g * pow(2, 6) + h * pow(2, 7) + i * pow(2, 8) + j * pow(2, 9) + k * pow(2, 10) + l * pow(2, 11) + m * pow(2, 12) + n * pow(2, 13) + o * pow(2, 14) + p * pow(2, 15) + q * pow(2, 16) + r * pow(2, 17) + s * pow(2, 18) + t * pow(2, 19) + u * pow(2, 20) + v * pow(2, 21) + w * pow(2, 22) + x * pow(2, 23) + y * pow(2, 24) + z * pow(2, 25); -} - -void testCallFunctionWithHellaFloatArguments() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Vector<Value*> args; - for (unsigned i = 0; i < 26; ++i) - args.append(root->appendNew<ConstFloatValue>(proc, Origin(), i + 1)); - - CCallValue* call = root->appendNew<CCallValue>( - proc, Float, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(functionWithHellaFloatArguments))); - call->children().appendVector(args); - - root->appendNew<ControlValue>(proc, Return, Origin(), call); - - CHECK(compileAndRun<float>(proc) == functionWithHellaFloatArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)); -} - -void testChillDiv(int num, int den, int res) -{ - // Test non-constant. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ChillDiv, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))); - - CHECK(compileAndRun<int>(proc, num, den) == res); - } - - // Test constant. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ChillDiv, Origin(), - root->appendNew<Const32Value>(proc, Origin(), num), - root->appendNew<Const32Value>(proc, Origin(), den))); - - CHECK(compileAndRun<int>(proc) == res); - } -} - -void testChillDivTwice(int num1, int den1, int num2, int den2, int res) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>( - proc, ChillDiv, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))), - root->appendNew<Value>( - proc, ChillDiv, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3))))); - - CHECK(compileAndRun<int>(proc, num1, den1, num2, den2) == res); -} - -void testChillDiv64(int64_t num, int64_t den, int64_t res) -{ - if (!is64Bit()) - return; - - // Test non-constant. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ChillDiv, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - CHECK(compileAndRun<int64_t>(proc, num, den) == res); - } - - // Test constant. - { - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ChillDiv, Origin(), - root->appendNew<Const64Value>(proc, Origin(), num), - root->appendNew<Const64Value>(proc, Origin(), den))); - - CHECK(compileAndRun<int64_t>(proc) == res); - } -} - -void testModArg(int64_t value) -{ - if (!value) - return; - - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument, argument); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(!compileAndRun<int64_t>(proc, value)); -} - -void testModArgs(int64_t numerator, int64_t denominator) -{ - if (!denominator) - return; - if (numerator == std::numeric_limits<int64_t>::min() && denominator == -1) - return; - - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == numerator % denominator); -} - -void testModImms(int64_t numerator, int64_t denominator) -{ - if (!denominator) - return; - if (numerator == std::numeric_limits<int64_t>::min() && denominator == -1) - return; - - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument1 = root->appendNew<Const64Value>(proc, Origin(), numerator); - Value* argument2 = root->appendNew<Const64Value>(proc, Origin(), denominator); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == numerator % denominator); -} - -void testModArg32(int32_t value) -{ - if (!value) - return; - - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument, argument); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(!compileAndRun<int32_t>(proc, value)); -} - -void testModArgs32(int32_t numerator, int32_t denominator) -{ - if (!denominator) - return; - if (numerator == std::numeric_limits<int32_t>::min() && denominator == -1) - return; - - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == numerator % denominator); -} - -void testModImms32(int32_t numerator, int32_t denominator) -{ - if (!denominator) - return; - if (numerator == std::numeric_limits<int32_t>::min() && denominator == -1) - return; - - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument1 = root->appendNew<Const32Value>(proc, Origin(), numerator); - Value* argument2 = root->appendNew<Const32Value>(proc, Origin(), denominator); - Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == numerator % denominator); -} - -void testChillModArg(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument, argument); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(!compileAndRun<int64_t>(proc, value)); -} - -void testChillModArgs(int64_t numerator, int64_t denominator) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == chillMod(numerator, denominator)); -} - -void testChillModImms(int64_t numerator, int64_t denominator) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument1 = root->appendNew<Const64Value>(proc, Origin(), numerator); - Value* argument2 = root->appendNew<Const64Value>(proc, Origin(), denominator); - Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == chillMod(numerator, denominator)); -} - -void testChillModArg32(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument, argument); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(!compileAndRun<int32_t>(proc, value)); -} - -void testChillModArgs32(int32_t numerator, int32_t denominator) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == chillMod(numerator, denominator)); -} - -void testChillModImms32(int32_t numerator, int32_t denominator) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* argument1 = root->appendNew<Const32Value>(proc, Origin(), numerator); - Value* argument2 = root->appendNew<Const32Value>(proc, Origin(), denominator); - Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2); - root->appendNew<ControlValue>(proc, Return, Origin(), result); - - CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == chillMod(numerator, denominator)); -} - -void testSwitch(unsigned degree, unsigned gap = 1) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - BasicBlock* terminate = proc.addBlock(); - terminate->appendNew<ControlValue>( - proc, Return, Origin(), - terminate->appendNew<Const32Value>(proc, Origin(), 0)); - - SwitchValue* switchValue = root->appendNew<SwitchValue>( - proc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(terminate)); - - for (unsigned i = 0; i < degree; ++i) { - BasicBlock* newBlock = proc.addBlock(); - newBlock->appendNew<ControlValue>( - proc, Return, Origin(), - newBlock->appendNew<ArgumentRegValue>( - proc, Origin(), (i & 1) ? GPRInfo::argumentGPR2 : GPRInfo::argumentGPR1)); - switchValue->appendCase(SwitchCase(gap * i, FrequentedBlock(newBlock))); - } - - auto code = compile(proc); - - for (unsigned i = 0; i < degree; ++i) { - CHECK(invoke<int32_t>(*code, i * gap, 42, 11) == ((i & 1) ? 11 : 42)); - if (gap > 1) { - CHECK(!invoke<int32_t>(*code, i * gap + 1, 42, 11)); - CHECK(!invoke<int32_t>(*code, i * gap - 1, 42, 11)); - } - } - - CHECK(!invoke<int32_t>(*code, -1, 42, 11)); - CHECK(!invoke<int32_t>(*code, degree * gap, 42, 11)); - CHECK(!invoke<int32_t>(*code, degree * gap + 1, 42, 11)); -} - -void testSwitchChillDiv(unsigned degree, unsigned gap = 1) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - Value* right = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); - - BasicBlock* terminate = proc.addBlock(); - terminate->appendNew<ControlValue>( - proc, Return, Origin(), - terminate->appendNew<Const32Value>(proc, Origin(), 0)); - - SwitchValue* switchValue = root->appendNew<SwitchValue>( - proc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(terminate)); - - for (unsigned i = 0; i < degree; ++i) { - BasicBlock* newBlock = proc.addBlock(); - - newBlock->appendNew<ControlValue>( - proc, Return, Origin(), - newBlock->appendNew<Value>( - proc, ChillDiv, Origin(), (i & 1) ? right : left, (i & 1) ? left : right)); - - switchValue->appendCase(SwitchCase(gap * i, FrequentedBlock(newBlock))); - } - - auto code = compile(proc); - - for (unsigned i = 0; i < degree; ++i) { - CHECK(invoke<int32_t>(*code, i * gap, 42, 11) == ((i & 1) ? 11/42 : 42/11)); - if (gap > 1) { - CHECK(!invoke<int32_t>(*code, i * gap + 1, 42, 11)); - CHECK(!invoke<int32_t>(*code, i * gap - 1, 42, 11)); - } - } - - CHECK(!invoke<int32_t>(*code, -1, 42, 11)); - CHECK(!invoke<int32_t>(*code, degree * gap, 42, 11)); - CHECK(!invoke<int32_t>(*code, degree * gap + 1, 42, 11)); -} - -void testSwitchTargettingSameBlock() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - BasicBlock* terminate = proc.addBlock(); - terminate->appendNew<ControlValue>( - proc, Return, Origin(), - terminate->appendNew<Const32Value>(proc, Origin(), 5)); - - SwitchValue* switchValue = root->appendNew<SwitchValue>( - proc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(terminate)); - - BasicBlock* otherTarget = proc.addBlock(); - otherTarget->appendNew<ControlValue>( - proc, Return, Origin(), - otherTarget->appendNew<Const32Value>(proc, Origin(), 42)); - switchValue->appendCase(SwitchCase(3, FrequentedBlock(otherTarget))); - switchValue->appendCase(SwitchCase(13, FrequentedBlock(otherTarget))); - - auto code = compile(proc); - - for (unsigned i = 0; i < 20; ++i) { - int32_t expected = (i == 3 || i == 13) ? 42 : 5; - CHECK(invoke<int32_t>(*code, i) == expected); - } -} - -void testSwitchTargettingSameBlockFoldPathConstant() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - BasicBlock* terminate = proc.addBlock(); - terminate->appendNew<ControlValue>( - proc, Return, Origin(), - terminate->appendNew<Const32Value>(proc, Origin(), 42)); - - Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - SwitchValue* switchValue = root->appendNew<SwitchValue>( - proc, Origin(), - argument, - FrequentedBlock(terminate)); - - BasicBlock* otherTarget = proc.addBlock(); - otherTarget->appendNew<ControlValue>( - proc, Return, Origin(), argument); - switchValue->appendCase(SwitchCase(3, FrequentedBlock(otherTarget))); - switchValue->appendCase(SwitchCase(13, FrequentedBlock(otherTarget))); - - auto code = compile(proc); - - for (unsigned i = 0; i < 20; ++i) { - int32_t expected = (i == 3 || i == 13) ? i : 42; - CHECK(invoke<int32_t>(*code, i) == expected); - } -} - -void testTruncFold(int64_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<Const64Value>(proc, Origin(), value))); - - CHECK(compileAndRun<int>(proc) == static_cast<int>(value)); -} - -void testZExt32(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZExt32, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<uint64_t>(proc, value) == static_cast<uint64_t>(static_cast<uint32_t>(value))); -} - -void testZExt32Fold(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZExt32, Origin(), - root->appendNew<Const32Value>(proc, Origin(), value))); - - CHECK(compileAndRun<uint64_t>(proc, value) == static_cast<uint64_t>(static_cast<uint32_t>(value))); -} - -void testSExt32(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt32, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int64_t>(proc, value) == static_cast<int64_t>(value)); -} - -void testSExt32Fold(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt32, Origin(), - root->appendNew<Const32Value>(proc, Origin(), value))); - - CHECK(compileAndRun<int64_t>(proc, value) == static_cast<int64_t>(value)); -} - -void testTruncZExt32(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<Value>( - proc, ZExt32, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))))); - - CHECK(compileAndRun<int32_t>(proc, value) == value); -} - -void testTruncSExt32(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<Value>( - proc, SExt32, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))))); - - CHECK(compileAndRun<int32_t>(proc, value) == value); -} - -void testSExt8(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt8, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value))); -} - -void testSExt8Fold(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt8, Origin(), - root->appendNew<Const32Value>(proc, Origin(), value))); - - CHECK(compileAndRun<int32_t>(proc) == static_cast<int32_t>(static_cast<int8_t>(value))); -} - -void testSExt8SExt8(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt8, Origin(), - root->appendNew<Value>( - proc, SExt8, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))))); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value))); -} - -void testSExt8SExt16(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt8, Origin(), - root->appendNew<Value>( - proc, SExt16, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))))); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value))); -} - -void testSExt8BitAnd(int32_t value, int32_t mask) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt8, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), mask)))); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value & mask))); -} - -void testBitAndSExt8(int32_t value, int32_t mask) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, SExt8, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - root->appendNew<Const32Value>(proc, Origin(), mask))); - - CHECK(compileAndRun<int32_t>(proc, value) == (static_cast<int32_t>(static_cast<int8_t>(value)) & mask)); -} - -void testSExt16(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt16, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)))); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int16_t>(value))); -} - -void testSExt16Fold(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt16, Origin(), - root->appendNew<Const32Value>(proc, Origin(), value))); - - CHECK(compileAndRun<int32_t>(proc) == static_cast<int32_t>(static_cast<int16_t>(value))); -} - -void testSExt16SExt16(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt16, Origin(), - root->appendNew<Value>( - proc, SExt16, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))))); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int16_t>(value))); -} - -void testSExt16SExt8(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt16, Origin(), - root->appendNew<Value>( - proc, SExt8, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))))); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int8_t>(value))); -} - -void testSExt16BitAnd(int32_t value, int32_t mask) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt16, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), mask)))); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<int32_t>(static_cast<int16_t>(value & mask))); -} - -void testBitAndSExt16(int32_t value, int32_t mask) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, SExt16, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - root->appendNew<Const32Value>(proc, Origin(), mask))); - - CHECK(compileAndRun<int32_t>(proc, value) == (static_cast<int32_t>(static_cast<int16_t>(value)) & mask)); -} - -void testSExt32BitAnd(int32_t value, int32_t mask) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SExt32, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), mask)))); - - CHECK(compileAndRun<int64_t>(proc, value) == static_cast<int64_t>(value & mask)); -} - -void testBitAndSExt32(int32_t value, int64_t mask) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, SExt32, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), - root->appendNew<Const64Value>(proc, Origin(), mask))); - - CHECK(compileAndRun<int64_t>(proc, value) == (static_cast<int64_t>(value) & mask)); -} - -void testBasicSelect() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ConstPtrValue>(proc, Origin(), 42)), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - - auto code = compile(proc); - CHECK(invoke<intptr_t>(*code, 42, 1, 2) == 1); - CHECK(invoke<intptr_t>(*code, 42, 642462, 32533) == 642462); - CHECK(invoke<intptr_t>(*code, 43, 1, 2) == 2); - CHECK(invoke<intptr_t>(*code, 43, 642462, 32533) == 32533); -} - -void testSelectTest() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - - auto code = compile(proc); - CHECK(invoke<intptr_t>(*code, 42, 1, 2) == 1); - CHECK(invoke<intptr_t>(*code, 42, 642462, 32533) == 642462); - CHECK(invoke<intptr_t>(*code, 0, 1, 2) == 2); - CHECK(invoke<intptr_t>(*code, 0, 642462, 32533) == 32533); -} - -void testSelectCompareDouble() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, LessThan, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - auto code = compile(proc); - CHECK(invoke<intptr_t>(*code, -1.0, 1.0, 1, 2) == 1); - CHECK(invoke<intptr_t>(*code, 42.5, 42.51, 642462, 32533) == 642462); - CHECK(invoke<intptr_t>(*code, PNaN, 0.0, 1, 2) == 2); - CHECK(invoke<intptr_t>(*code, 42.51, 42.5, 642462, 32533) == 32533); - CHECK(invoke<intptr_t>(*code, 42.52, 42.52, 524978245, 352) == 352); -} - -template<B3::Opcode opcode> -void testSelectCompareFloat(float a, float b, bool (*operation)(float, float)) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, opcode, Origin(), - floatValue1, - floatValue2), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3))); - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), 42, -5), operation(a, b) ? 42 : -5)); -} - -void testSelectCompareFloat(float a, float b) -{ - testSelectCompareFloat<Equal>(a, b, [](float a, float b) -> bool { return a == b; }); - testSelectCompareFloat<NotEqual>(a, b, [](float a, float b) -> bool { return a != b; }); - testSelectCompareFloat<LessThan>(a, b, [](float a, float b) -> bool { return a < b; }); - testSelectCompareFloat<GreaterThan>(a, b, [](float a, float b) -> bool { return a > b; }); - testSelectCompareFloat<LessEqual>(a, b, [](float a, float b) -> bool { return a <= b; }); - testSelectCompareFloat<GreaterEqual>(a, b, [](float a, float b) -> bool { return a >= b; }); - testSelectCompareFloat<EqualOrUnordered>(a, b, [](float a, float b) -> bool { return a != a || b != b || a == b; }); -} - -template<B3::Opcode opcode> -void testSelectCompareFloatToDouble(float a, float b, bool (*operation)(float, float)) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* doubleValue1 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue1); - Value* doubleValue2 = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue2); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, opcode, Origin(), - doubleValue1, - doubleValue2), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3))); - CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), 42, -5), operation(a, b) ? 42 : -5)); -} - -void testSelectCompareFloatToDouble(float a, float b) -{ - testSelectCompareFloatToDouble<Equal>(a, b, [](float a, float b) -> bool { return a == b; }); - testSelectCompareFloatToDouble<NotEqual>(a, b, [](float a, float b) -> bool { return a != b; }); - testSelectCompareFloatToDouble<LessThan>(a, b, [](float a, float b) -> bool { return a < b; }); - testSelectCompareFloatToDouble<GreaterThan>(a, b, [](float a, float b) -> bool { return a > b; }); - testSelectCompareFloatToDouble<LessEqual>(a, b, [](float a, float b) -> bool { return a <= b; }); - testSelectCompareFloatToDouble<GreaterEqual>(a, b, [](float a, float b) -> bool { return a >= b; }); - testSelectCompareFloatToDouble<EqualOrUnordered>(a, b, [](float a, float b) -> bool { return a != a || b != b || a == b; }); -} - -void testSelectDouble() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ConstPtrValue>(proc, Origin(), 42)), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1))); - - auto code = compile(proc); - CHECK(invoke<double>(*code, 42, 1.5, 2.6) == 1.5); - CHECK(invoke<double>(*code, 42, 642462.7, 32533.8) == 642462.7); - CHECK(invoke<double>(*code, 43, 1.9, 2.0) == 2.0); - CHECK(invoke<double>(*code, 43, 642462.1, 32533.2) == 32533.2); -} - -void testSelectDoubleTest() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1))); - - auto code = compile(proc); - CHECK(invoke<double>(*code, 42, 1.5, 2.6) == 1.5); - CHECK(invoke<double>(*code, 42, 642462.7, 32533.8) == 642462.7); - CHECK(invoke<double>(*code, 0, 1.9, 2.0) == 2.0); - CHECK(invoke<double>(*code, 0, 642462.1, 32533.2) == 32533.2); -} - -void testSelectDoubleCompareDouble() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, LessThan, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1)), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3))); - - auto code = compile(proc); - CHECK(invoke<double>(*code, -1.0, 1.0, 1.1, 2.2) == 1.1); - CHECK(invoke<double>(*code, 42.5, 42.51, 642462.3, 32533.4) == 642462.3); - CHECK(invoke<double>(*code, PNaN, 0.0, 1.5, 2.6) == 2.6); - CHECK(invoke<double>(*code, 42.51, 42.5, 642462.7, 32533.8) == 32533.8); - CHECK(invoke<double>(*code, 42.52, 42.52, 524978245.9, 352.0) == 352.0); -} - -void testSelectDoubleCompareFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, LessThan, Origin(), - floatValue1, - floatValue2), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1))); - - CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), 42.1, -M_PI), a < b ? 42.1 : -M_PI)); -} - -void testSelectFloatCompareFloat(float a, float b) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); - Value* argument3int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)); - Value* argument4int32 = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3)); - Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32); - Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32); - Value* floatValue3 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument3int32); - Value* floatValue4 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument4int32); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, LessThan, Origin(), - floatValue1, - floatValue2), - floatValue3, - floatValue4)); - - CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b), bitwise_cast<int32_t>(1.1f), bitwise_cast<int32_t>(-42.f)), a < b ? 1.1f : -42.f)); -} - - -template<B3::Opcode opcode> -void testSelectDoubleCompareDouble(bool (*operation)(double, double)) -{ - { // Compare arguments and selected arguments are all different. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2); - Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, opcode, Origin(), - arg0, - arg1), - arg2, - arg3)); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<double>()) { - for (auto& right : floatingPointOperands<double>()) { - double expected = operation(left.value, right.value) ? 42.5 : -66.5; - CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, -66.5), expected)); - } - } - } - { // Compare arguments and selected arguments are all different. "thenCase" is live after operation. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2); - Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3); - - Value* result = root->appendNew<Value>(proc, Select, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1), - arg2, - arg3); - - PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<double>()) { - for (auto& right : floatingPointOperands<double>()) { - double expected = operation(left.value, right.value) ? 42.5 : -66.5; - CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, -66.5), expected)); - } - } - } - { // Compare arguments and selected arguments are all different. "elseCase" is live after operation. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2); - Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3); - - Value* result = root->appendNew<Value>(proc, Select, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1), - arg2, - arg3); - - PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); - keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<double>()) { - for (auto& right : floatingPointOperands<double>()) { - double expected = operation(left.value, right.value) ? 42.5 : -66.5; - CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, -66.5), expected)); - } - } - } - { // Compare arguments and selected arguments are all different. Both cases are live after operation. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2); - Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR3); - - Value* result = root->appendNew<Value>(proc, Select, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1), - arg2, - arg3); - - PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); - keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<double>()) { - for (auto& right : floatingPointOperands<double>()) { - double expected = operation(left.value, right.value) ? 42.5 : -66.5; - CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, -66.5), expected)); - } - } - } - { // The left argument is the same as the "elseCase" argument. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, opcode, Origin(), - arg0, - arg1), - arg2, - arg0)); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<double>()) { - for (auto& right : floatingPointOperands<double>()) { - double expected = operation(left.value, right.value) ? 42.5 : left.value; - CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, left.value), expected)); - } - } - } - { // The left argument is the same as the "elseCase" argument. "thenCase" is live after operation. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR2); - - Value* result = root->appendNew<Value>(proc, Select, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1), - arg2, - arg0); - - PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<double>()) { - for (auto& right : floatingPointOperands<double>()) { - double expected = operation(left.value, right.value) ? 42.5 : left.value; - CHECK(isIdentical(invoke<double>(*code, left.value, right.value, 42.5, left.value), expected)); - } - } - } -} - -void testSelectDoubleCompareDoubleWithAliasing() -{ - testSelectDoubleCompareDouble<Equal>([](double a, double b) -> bool { return a == b; }); - testSelectDoubleCompareDouble<NotEqual>([](double a, double b) -> bool { return a != b; }); - testSelectDoubleCompareDouble<LessThan>([](double a, double b) -> bool { return a < b; }); - testSelectDoubleCompareDouble<GreaterThan>([](double a, double b) -> bool { return a > b; }); - testSelectDoubleCompareDouble<LessEqual>([](double a, double b) -> bool { return a <= b; }); - testSelectDoubleCompareDouble<GreaterEqual>([](double a, double b) -> bool { return a >= b; }); - testSelectDoubleCompareDouble<EqualOrUnordered>([](double a, double b) -> bool { return a != a || b != b || a == b; }); -} - -template<B3::Opcode opcode> -void testSelectFloatCompareFloat(bool (*operation)(float, float)) -{ - { // Compare arguments and selected arguments are all different. - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - Value* arg3 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3))); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, opcode, Origin(), - arg0, - arg1), - arg2, - arg3)); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<float>()) { - for (auto& right : floatingPointOperands<float>()) { - float expected = operation(left.value, right.value) ? 42.5 : -66.5; - CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(-66.5f)), expected)); - } - } - } - { // Compare arguments and selected arguments are all different. "thenCase" is live after operation. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - Value* arg3 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3))); - - Value* result = root->appendNew<Value>(proc, Select, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1), - arg2, - arg3); - - PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<float>()) { - for (auto& right : floatingPointOperands<float>()) { - float expected = operation(left.value, right.value) ? 42.5 : -66.5; - CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(-66.5f)), expected)); - } - } - } - { // Compare arguments and selected arguments are all different. "elseCase" is live after operation. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - Value* arg3 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3))); - - Value* result = root->appendNew<Value>(proc, Select, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1), - arg2, - arg3); - - PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); - keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<float>()) { - for (auto& right : floatingPointOperands<float>()) { - float expected = operation(left.value, right.value) ? 42.5 : -66.5; - CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(-66.5f)), expected)); - } - } - } - { // Compare arguments and selected arguments are all different. Both cases are live after operation. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - Value* arg3 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR3))); - - Value* result = root->appendNew<Value>(proc, Select, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1), - arg2, - arg3); - - PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); - keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<float>()) { - for (auto& right : floatingPointOperands<float>()) { - float expected = operation(left.value, right.value) ? 42.5 : -66.5; - CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(-66.5f)), expected)); - } - } - } - { // The left argument is the same as the "elseCase" argument. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, opcode, Origin(), - arg0, - arg1), - arg2, - arg0)); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<float>()) { - for (auto& right : floatingPointOperands<float>()) { - float expected = operation(left.value, right.value) ? 42.5 : left.value; - CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(left.value)), expected)); - } - } - } - { // The left argument is the same as the "elseCase" argument. "thenCase" is live after operation. - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg0 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))); - Value* arg1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - Value* arg2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), - root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - - Value* result = root->appendNew<Value>(proc, Select, Origin(), - root->appendNew<Value>(proc, opcode, Origin(), arg0, arg1), - arg2, - arg0); - - PatchpointValue* keepValuesLive = root->appendNew<PatchpointValue>(proc, Void, Origin()); - keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); - keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - - root->appendNew<ControlValue>(proc, Return, Origin(), result); - auto code = compile(proc); - - for (auto& left : floatingPointOperands<float>()) { - for (auto& right : floatingPointOperands<float>()) { - float expected = operation(left.value, right.value) ? 42.5 : left.value; - CHECK(isIdentical(invoke<float>(*code, bitwise_cast<int32_t>(left.value), bitwise_cast<int32_t>(right.value), bitwise_cast<int32_t>(42.5f), bitwise_cast<int32_t>(left.value)), expected)); - } - } - } -} - -void testSelectFloatCompareFloatWithAliasing() -{ - testSelectFloatCompareFloat<Equal>([](float a, float b) -> bool { return a == b; }); - testSelectFloatCompareFloat<NotEqual>([](float a, float b) -> bool { return a != b; }); - testSelectFloatCompareFloat<LessThan>([](float a, float b) -> bool { return a < b; }); - testSelectFloatCompareFloat<GreaterThan>([](float a, float b) -> bool { return a > b; }); - testSelectFloatCompareFloat<LessEqual>([](float a, float b) -> bool { return a <= b; }); - testSelectFloatCompareFloat<GreaterEqual>([](float a, float b) -> bool { return a >= b; }); - testSelectFloatCompareFloat<EqualOrUnordered>([](float a, float b) -> bool { return a != a || b != b || a == b; }); -} - -void testSelectFold(intptr_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<ConstPtrValue>(proc, Origin(), value), - root->appendNew<ConstPtrValue>(proc, Origin(), 42)), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1))); - - auto code = compile(proc); - CHECK(invoke<intptr_t>(*code, 1, 2) == (value == 42 ? 1 : 2)); - CHECK(invoke<intptr_t>(*code, 642462, 32533) == (value == 42 ? 642462 : 32533)); -} - -void testSelectInvert() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, Equal, Origin(), - root->appendNew<Value>( - proc, NotEqual, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<ConstPtrValue>(proc, Origin(), 42)), - root->appendNew<Const32Value>(proc, Origin(), 0)), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2))); - - auto code = compile(proc); - CHECK(invoke<intptr_t>(*code, 42, 1, 2) == 1); - CHECK(invoke<intptr_t>(*code, 42, 642462, 32533) == 642462); - CHECK(invoke<intptr_t>(*code, 43, 1, 2) == 2); - CHECK(invoke<intptr_t>(*code, 43, 642462, 32533) == 32533); -} - -void testCheckSelect() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - CheckValue* check = root->appendNew<CheckValue>( - proc, Check, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>( - proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), 0xff)), - root->appendNew<ConstPtrValue>(proc, Origin(), -42), - root->appendNew<ConstPtrValue>(proc, Origin(), 35)), - root->appendNew<ConstPtrValue>(proc, Origin(), 42))); - unsigned generationCount = 0; - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams&) { - AllowMacroScratchRegisterUsage allowScratch(jit); - - generationCount++; - jit.move(CCallHelpers::TrustedImm32(666), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - CHECK(generationCount == 1); - CHECK(invoke<int>(*code, true) == 0); - CHECK(invoke<int>(*code, false) == 666); -} - -void testCheckSelectCheckSelect() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - CheckValue* check = root->appendNew<CheckValue>( - proc, Check, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>( - proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), 0xff)), - root->appendNew<ConstPtrValue>(proc, Origin(), -42), - root->appendNew<ConstPtrValue>(proc, Origin(), 35)), - root->appendNew<ConstPtrValue>(proc, Origin(), 42))); - - unsigned generationCount = 0; - check->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams&) { - AllowMacroScratchRegisterUsage allowScratch(jit); - - generationCount++; - jit.move(CCallHelpers::TrustedImm32(666), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - - CheckValue* check2 = root->appendNew<CheckValue>( - proc, Check, Origin(), - root->appendNew<Value>( - proc, Add, Origin(), - root->appendNew<Value>( - proc, Select, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>( - proc, Origin(), GPRInfo::argumentGPR1)), - root->appendNew<Const32Value>(proc, Origin(), 0xff)), - root->appendNew<ConstPtrValue>(proc, Origin(), -43), - root->appendNew<ConstPtrValue>(proc, Origin(), 36)), - root->appendNew<ConstPtrValue>(proc, Origin(), 43))); - - unsigned generationCount2 = 0; - check2->setGenerator( - [&] (CCallHelpers& jit, const StackmapGenerationParams&) { - AllowMacroScratchRegisterUsage allowScratch(jit); - - generationCount2++; - jit.move(CCallHelpers::TrustedImm32(667), GPRInfo::returnValueGPR); - jit.emitFunctionEpilogue(); - jit.ret(); - }); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Const32Value>(proc, Origin(), 0)); - - auto code = compile(proc); - CHECK(generationCount == 1); - CHECK(generationCount2 == 1); - CHECK(invoke<int>(*code, true, true) == 0); - CHECK(invoke<int>(*code, false, true) == 666); - CHECK(invoke<int>(*code, true, false) == 667); -} - -double b3Pow(double x, int y) -{ - if (y < 0 || y > 1000) - return pow(x, y); - double result = 1; - while (y) { - if (y & 1) - result *= x; - x *= x; - y >>= 1; - } - return result; -} - -void testPowDoubleByIntegerLoop(double xOperand, int32_t yOperand) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* x = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - Value* y = root->appendNew<Value>(proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - auto result = powDoubleInt32(proc, root, Origin(), x, y); - BasicBlock* continuation = result.first; - continuation->appendNew<ControlValue>(proc, Return, Origin(), result.second); - - CHECK(isIdentical(compileAndRun<double>(proc, xOperand, yOperand), b3Pow(xOperand, yOperand))); -} - -void testTruncOrHigh() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), 0x100000000)))); - - int64_t value = 0x123456781234; - CHECK(compileAndRun<int>(proc, value) == 0x56781234); -} - -void testTruncOrLow() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), 0x1000000)))); - - int64_t value = 0x123456781234; - CHECK(compileAndRun<int>(proc, value) == 0x57781234); -} - -void testBitAndOrHigh() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), 0x8)), - root->appendNew<Const64Value>(proc, Origin(), 0x777777777777))); - - int64_t value = 0x123456781234; - CHECK(compileAndRun<int64_t>(proc, value) == 0x123456701234ll); -} - -void testBitAndOrLow() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, BitAnd, Origin(), - root->appendNew<Value>( - proc, BitOr, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const64Value>(proc, Origin(), 0x1)), - root->appendNew<Const64Value>(proc, Origin(), 0x777777777777))); - - int64_t value = 0x123456781234; - CHECK(compileAndRun<int64_t>(proc, value) == 0x123456701235ll); -} - -void testBranch64Equal(int64_t left, int64_t right) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - bool trueResult = true; - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - thenCase->appendNew<ConstPtrValue>(proc, Origin(), &trueResult))); - - bool elseResult = false; - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - elseCase->appendNew<ConstPtrValue>(proc, Origin(), &elseResult))); - - CHECK(compileAndRun<bool>(proc, left, right) == (left == right)); -} - -void testBranch64EqualImm(int64_t left, int64_t right) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - Value* arg2 = root->appendNew<ConstPtrValue>(proc, Origin(), right); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - bool trueResult = true; - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - thenCase->appendNew<ConstPtrValue>(proc, Origin(), &trueResult))); - - bool elseResult = false; - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - elseCase->appendNew<ConstPtrValue>(proc, Origin(), &elseResult))); - - CHECK(compileAndRun<bool>(proc, left) == (left == right)); -} - -void testBranch64EqualMem(int64_t left, int64_t right) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* arg1 = root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - bool trueResult = true; - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - thenCase->appendNew<ConstPtrValue>(proc, Origin(), &trueResult))); - - bool elseResult = false; - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - elseCase->appendNew<ConstPtrValue>(proc, Origin(), &elseResult))); - - CHECK(compileAndRun<bool>(proc, &left, right) == (left == right)); -} - -void testBranch64EqualMemImm(int64_t left, int64_t right) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenCase = proc.addBlock(); - BasicBlock* elseCase = proc.addBlock(); - - Value* arg1 = root->appendNew<MemoryValue>( - proc, Load, pointerType(), Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - Value* arg2 = root->appendNew<ConstPtrValue>(proc, Origin(), right); - root->appendNew<ControlValue>( - proc, Branch, Origin(), - root->appendNew<Value>(proc, Equal, Origin(), arg1, arg2), - FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - - bool trueResult = true; - thenCase->appendNew<ControlValue>( - proc, Return, Origin(), - thenCase->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - thenCase->appendNew<ConstPtrValue>(proc, Origin(), &trueResult))); - - bool elseResult = false; - elseCase->appendNew<ControlValue>( - proc, Return, Origin(), - elseCase->appendNew<MemoryValue>( - proc, Load8Z, Origin(), - elseCase->appendNew<ConstPtrValue>(proc, Origin(), &elseResult))); - - CHECK(compileAndRun<bool>(proc, &left) == (left == right)); -} - -void testStore8Load8Z(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - int8_t byte; - Value* ptr = root->appendNew<ConstPtrValue>(proc, Origin(), &byte); - - root->appendNew<MemoryValue>( - proc, Store8, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - ptr); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>(proc, Load8Z, Origin(), ptr)); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<uint8_t>(value)); -} - -void testStore16Load16Z(int32_t value) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - int16_t byte; - Value* ptr = root->appendNew<ConstPtrValue>(proc, Origin(), &byte); - - root->appendNew<MemoryValue>( - proc, Store16, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - ptr); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<MemoryValue>(proc, Load16Z, Origin(), ptr)); - - CHECK(compileAndRun<int32_t>(proc, value) == static_cast<uint16_t>(value)); -} - -void testSShrShl32(int32_t value, int32_t sshrAmount, int32_t shlAmount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew<Const32Value>(proc, Origin(), shlAmount)), - root->appendNew<Const32Value>(proc, Origin(), sshrAmount))); - - CHECK( - compileAndRun<int32_t>(proc, value) - == ((value << (shlAmount & 31)) >> (sshrAmount & 31))); -} - -void testSShrShl64(int64_t value, int32_t sshrAmount, int32_t shlAmount) -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), - root->appendNew<Const32Value>(proc, Origin(), shlAmount)), - root->appendNew<Const32Value>(proc, Origin(), sshrAmount))); - - CHECK( - compileAndRun<int64_t>(proc, value) - == ((value << (shlAmount & 63)) >> (sshrAmount & 63))); -} - -template<typename T> -void testComputeDivisionMagic(T value, T magicMultiplier, unsigned shift) -{ - DivisionMagic<T> magic = computeDivisionMagic(value); - CHECK(magic.magicMultiplier == magicMultiplier); - CHECK(magic.shift == shift); -} - -void testTrivialInfiniteLoop() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* loop = proc.addBlock(); - root->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loop)); - loop->appendNew<ControlValue>(proc, Jump, Origin(), FrequentedBlock(loop)); - - compile(proc); -} - -void testFoldPathEqual() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - BasicBlock* thenBlock = proc.addBlock(); - BasicBlock* elseBlock = proc.addBlock(); - - Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - - root->appendNew<ControlValue>( - proc, Branch, Origin(), arg, FrequentedBlock(thenBlock), FrequentedBlock(elseBlock)); - - thenBlock->appendNew<ControlValue>( - proc, Return, Origin(), - thenBlock->appendNew<Value>( - proc, Equal, Origin(), arg, thenBlock->appendNew<ConstPtrValue>(proc, Origin(), 0))); - - elseBlock->appendNew<ControlValue>( - proc, Return, Origin(), - elseBlock->appendNew<Value>( - proc, Equal, Origin(), arg, elseBlock->appendNew<ConstPtrValue>(proc, Origin(), 0))); - - auto code = compile(proc); - CHECK(invoke<intptr_t>(*code, 0) == 1); - CHECK(invoke<intptr_t>(*code, 1) == 0); - CHECK(invoke<intptr_t>(*code, 42) == 0); -} - -void testLShiftSelf32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, Shl, Origin(), arg, arg)); - - auto code = compile(proc); - - auto check = [&] (int32_t value) { - CHECK(invoke<int32_t>(*code, value) == value << (value & 31)); - }; - - check(0); - check(1); - check(31); - check(32); -} - -void testRShiftSelf32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, SShr, Origin(), arg, arg)); - - auto code = compile(proc); - - auto check = [&] (int32_t value) { - CHECK(invoke<int32_t>(*code, value) == value >> (value & 31)); - }; - - check(0); - check(1); - check(31); - check(32); -} - -void testURShiftSelf32() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<Value>( - proc, Trunc, Origin(), - root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>(proc, ZShr, Origin(), arg, arg)); - - auto code = compile(proc); - - auto check = [&] (uint32_t value) { - CHECK(invoke<uint32_t>(*code, value) == value >> (value & 31)); - }; - - check(0); - check(1); - check(31); - check(32); -} - -void testLShiftSelf64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, Shl, Origin(), arg, root->appendNew<Value>(proc, Trunc, Origin(), arg))); - - auto code = compile(proc); - - auto check = [&] (int64_t value) { - CHECK(invoke<int64_t>(*code, value) == value << (value & 63)); - }; - - check(0); - check(1); - check(31); - check(32); - check(63); - check(64); -} - -void testRShiftSelf64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, SShr, Origin(), arg, root->appendNew<Value>(proc, Trunc, Origin(), arg))); - - auto code = compile(proc); - - auto check = [&] (int64_t value) { - CHECK(invoke<int64_t>(*code, value) == value >> (value & 63)); - }; - - check(0); - check(1); - check(31); - check(32); - check(63); - check(64); -} - -void testURShiftSelf64() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew<ControlValue>( - proc, Return, Origin(), - root->appendNew<Value>( - proc, ZShr, Origin(), arg, root->appendNew<Value>(proc, Trunc, Origin(), arg))); - - auto code = compile(proc); - - auto check = [&] (uint64_t value) { - CHECK(invoke<uint64_t>(*code, value) == value >> (value & 63)); - }; - - check(0); - check(1); - check(31); - check(32); - check(63); - check(64); -} - -void testPatchpointDoubleRegs() -{ - Procedure proc; - BasicBlock* root = proc.addBlock(); - - Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); - - PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Double, Origin()); - patchpoint->append(arg, ValueRep(FPRInfo::fpRegT0)); - patchpoint->resultConstraint = ValueRep(FPRInfo::fpRegT0); - - unsigned numCalls = 0; - patchpoint->setGenerator( - [&] (CCallHelpers&, const StackmapGenerationParams&) { - numCalls++; - }); - - root->appendNew<ControlValue>(proc, Return, Origin(), patchpoint); - - auto code = compile(proc); - CHECK(numCalls == 1); - CHECK(invoke<double>(*code, 42.5) == 42.5); -} - -// Make sure the compiler does not try to optimize anything out. -NEVER_INLINE double zero() -{ - return 0.; -} - -double negativeZero() -{ - return -zero(); -} - - - -#define RUN(test) do { \ - if (!shouldRun(#test)) \ - break; \ - tasks.append( \ - createSharedTask<void()>( \ - [&] () { \ - dataLog(#test "...\n"); \ - test; \ - dataLog(#test ": OK!\n"); \ - })); \ - } while (false); - -#define RUN_UNARY(test, values) \ - for (auto a : values) { \ - CString testStr = toCString(#test, "(", a.name, ")"); \ - if (!shouldRun(testStr.data())) \ - continue; \ - tasks.append(createSharedTask<void()>( \ - [=] () { \ - dataLog(toCString(testStr, "...\n")); \ - test(a.value); \ - dataLog(toCString(testStr, ": OK!\n")); \ - })); \ - } - -#define RUN_BINARY(test, valuesA, valuesB) \ - for (auto a : valuesA) { \ - for (auto b : valuesB) { \ - CString testStr = toCString(#test, "(", a.name, ", ", b.name, ")"); \ - if (!shouldRun(testStr.data())) \ - continue; \ - tasks.append(createSharedTask<void()>( \ - [=] () { \ - dataLog(toCString(testStr, "...\n")); \ - test(a.value, b.value); \ - dataLog(toCString(testStr, ": OK!\n")); \ - })); \ - } \ - } - -void run(const char* filter) -{ - JSC::initializeThreading(); - vm = &VM::create(LargeHeap).leakRef(); - - Deque<RefPtr<SharedTask<void()>>> tasks; - - auto shouldRun = [&] (const char* testName) -> bool { - return !filter || !!strcasestr(testName, filter); - }; - - RUN(test42()); - RUN(testLoad42()); - RUN(testLoadOffsetImm9Max()); - RUN(testLoadOffsetImm9MaxPlusOne()); - RUN(testLoadOffsetImm9MaxPlusTwo()); - RUN(testLoadOffsetImm9Min()); - RUN(testLoadOffsetImm9MinMinusOne()); - RUN(testLoadOffsetScaledUnsignedImm12Max()); - RUN(testLoadOffsetScaledUnsignedOverImm12Max()); - RUN(testArg(43)); - RUN(testReturnConst64(5)); - RUN(testReturnConst64(-42)); - - RUN(testAddArg(111)); - RUN(testAddArgs(1, 1)); - RUN(testAddArgs(1, 2)); - RUN(testAddArgImm(1, 2)); - RUN(testAddArgImm(0, 2)); - RUN(testAddArgImm(1, 0)); - RUN(testAddImmArg(1, 2)); - RUN(testAddImmArg(0, 2)); - RUN(testAddImmArg(1, 0)); - RUN_BINARY(testAddArgMem, int64Operands(), int64Operands()); - RUN_BINARY(testAddMemArg, int64Operands(), int64Operands()); - RUN_BINARY(testAddImmMem, int64Operands(), int64Operands()); - RUN_UNARY(testAddArg32, int32Operands()); - RUN(testAddArgs32(1, 1)); - RUN(testAddArgs32(1, 2)); - RUN_BINARY(testAddArgMem32, int32Operands(), int32Operands()); - RUN_BINARY(testAddMemArg32, int32Operands(), int32Operands()); - RUN_BINARY(testAddImmMem32, int32Operands(), int32Operands()); - RUN(testAddArgZeroImmZDef()); - RUN(testAddLoadTwice()); - - RUN(testAddArgDouble(M_PI)); - RUN(testAddArgsDouble(M_PI, 1)); - RUN(testAddArgsDouble(M_PI, -M_PI)); - RUN(testAddArgImmDouble(M_PI, 1)); - RUN(testAddArgImmDouble(M_PI, 0)); - RUN(testAddArgImmDouble(M_PI, negativeZero())); - RUN(testAddArgImmDouble(0, 0)); - RUN(testAddArgImmDouble(0, negativeZero())); - RUN(testAddArgImmDouble(negativeZero(), 0)); - RUN(testAddArgImmDouble(negativeZero(), negativeZero())); - RUN(testAddImmArgDouble(M_PI, 1)); - RUN(testAddImmArgDouble(M_PI, 0)); - RUN(testAddImmArgDouble(M_PI, negativeZero())); - RUN(testAddImmArgDouble(0, 0)); - RUN(testAddImmArgDouble(0, negativeZero())); - RUN(testAddImmArgDouble(negativeZero(), 0)); - RUN(testAddImmArgDouble(negativeZero(), negativeZero())); - RUN(testAddImmsDouble(M_PI, 1)); - RUN(testAddImmsDouble(M_PI, 0)); - RUN(testAddImmsDouble(M_PI, negativeZero())); - RUN(testAddImmsDouble(0, 0)); - RUN(testAddImmsDouble(0, negativeZero())); - RUN(testAddImmsDouble(negativeZero(), negativeZero())); - RUN_UNARY(testAddArgFloat, floatingPointOperands<float>()); - RUN_BINARY(testAddArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testAddArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testAddImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testAddImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_UNARY(testAddArgFloatWithUselessDoubleConversion, floatingPointOperands<float>()); - RUN_BINARY(testAddArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testAddArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - - RUN(testMulArg(5)); - RUN(testMulAddArg(5)); - RUN(testMulAddArg(85)); - RUN(testMulArgStore(5)); - RUN(testMulArgStore(85)); - RUN(testMulArgs(1, 1)); - RUN(testMulArgs(1, 2)); - RUN(testMulArgs(3, 3)); - RUN(testMulArgImm(1, 2)); - RUN(testMulArgImm(1, 4)); - RUN(testMulArgImm(1, 8)); - RUN(testMulArgImm(1, 16)); - RUN(testMulArgImm(1, 0x80000000llu)); - RUN(testMulArgImm(1, 0x800000000000llu)); - RUN(testMulArgImm(7, 2)); - RUN(testMulArgImm(7, 4)); - RUN(testMulArgImm(7, 8)); - RUN(testMulArgImm(7, 16)); - RUN(testMulArgImm(7, 0x80000000llu)); - RUN(testMulArgImm(7, 0x800000000000llu)); - RUN(testMulArgImm(-42, 2)); - RUN(testMulArgImm(-42, 4)); - RUN(testMulArgImm(-42, 8)); - RUN(testMulArgImm(-42, 16)); - RUN(testMulArgImm(-42, 0x80000000llu)); - RUN(testMulArgImm(-42, 0x800000000000llu)); - RUN(testMulArgImm(0, 2)); - RUN(testMulArgImm(1, 0)); - RUN(testMulArgImm(3, 3)); - RUN(testMulArgImm(3, -1)); - RUN(testMulArgImm(-3, -1)); - RUN(testMulArgImm(0, -1)); - RUN(testMulImmArg(1, 2)); - RUN(testMulImmArg(0, 2)); - RUN(testMulImmArg(1, 0)); - RUN(testMulImmArg(3, 3)); - RUN(testMulArgs32(1, 1)); - RUN(testMulArgs32(1, 2)); - RUN(testMulLoadTwice()); - RUN(testMulAddArgsLeft()); - RUN(testMulAddArgsRight()); - RUN(testMulAddArgsLeft32()); - RUN(testMulAddArgsRight32()); - RUN(testMulSubArgsLeft()); - RUN(testMulSubArgsRight()); - RUN(testMulSubArgsLeft32()); - RUN(testMulSubArgsRight32()); - RUN(testMulNegArgs()); - RUN(testMulNegArgs32()); - - RUN_UNARY(testMulArgDouble, floatingPointOperands<double>()); - RUN_BINARY(testMulArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testMulArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testMulImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testMulImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_UNARY(testMulArgFloat, floatingPointOperands<float>()); - RUN_BINARY(testMulArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testMulArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testMulImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testMulImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_UNARY(testMulArgFloatWithUselessDoubleConversion, floatingPointOperands<float>()); - RUN_BINARY(testMulArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testMulArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - - RUN(testDivArgDouble(M_PI)); - RUN(testDivArgsDouble(M_PI, 1)); - RUN(testDivArgsDouble(M_PI, -M_PI)); - RUN(testDivArgImmDouble(M_PI, 1)); - RUN(testDivArgImmDouble(M_PI, 0)); - RUN(testDivArgImmDouble(M_PI, negativeZero())); - RUN(testDivArgImmDouble(0, 0)); - RUN(testDivArgImmDouble(0, negativeZero())); - RUN(testDivArgImmDouble(negativeZero(), 0)); - RUN(testDivArgImmDouble(negativeZero(), negativeZero())); - RUN(testDivImmArgDouble(M_PI, 1)); - RUN(testDivImmArgDouble(M_PI, 0)); - RUN(testDivImmArgDouble(M_PI, negativeZero())); - RUN(testDivImmArgDouble(0, 0)); - RUN(testDivImmArgDouble(0, negativeZero())); - RUN(testDivImmArgDouble(negativeZero(), 0)); - RUN(testDivImmArgDouble(negativeZero(), negativeZero())); - RUN(testDivImmsDouble(M_PI, 1)); - RUN(testDivImmsDouble(M_PI, 0)); - RUN(testDivImmsDouble(M_PI, negativeZero())); - RUN(testDivImmsDouble(0, 0)); - RUN(testDivImmsDouble(0, negativeZero())); - RUN(testDivImmsDouble(negativeZero(), negativeZero())); - RUN_UNARY(testDivArgFloat, floatingPointOperands<float>()); - RUN_BINARY(testDivArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testDivArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testDivImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testDivImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_UNARY(testDivArgFloatWithUselessDoubleConversion, floatingPointOperands<float>()); - RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - - RUN_UNARY(testModArgDouble, floatingPointOperands<double>()); - RUN_BINARY(testModArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testModArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testModImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testModImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_UNARY(testModArgFloat, floatingPointOperands<float>()); - RUN_BINARY(testModArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testModArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testModImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testModImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - - RUN(testSubArg(24)); - RUN(testSubArgs(1, 1)); - RUN(testSubArgs(1, 2)); - RUN(testSubArgs(13, -42)); - RUN(testSubArgs(-13, 42)); - RUN(testSubArgImm(1, 1)); - RUN(testSubArgImm(1, 2)); - RUN(testSubArgImm(13, -42)); - RUN(testSubArgImm(-13, 42)); - RUN(testSubArgImm(42, 0)); - RUN(testSubImmArg(1, 1)); - RUN(testSubImmArg(1, 2)); - RUN(testSubImmArg(13, -42)); - RUN(testSubImmArg(-13, 42)); - RUN_BINARY(testSubArgMem, int64Operands(), int64Operands()); - RUN_BINARY(testSubMemArg, int64Operands(), int64Operands()); - RUN_BINARY(testSubImmMem, int32Operands(), int32Operands()); - RUN_BINARY(testSubMemImm, int32Operands(), int32Operands()); - RUN_UNARY(testNegValueSubOne, int32Operands()); - - RUN(testSubArgs32(1, 1)); - RUN(testSubArgs32(1, 2)); - RUN(testSubArgs32(13, -42)); - RUN(testSubArgs32(-13, 42)); - RUN(testSubArgImm32(1, 1)); - RUN(testSubArgImm32(1, 2)); - RUN(testSubArgImm32(13, -42)); - RUN(testSubArgImm32(-13, 42)); - RUN(testSubImmArg32(1, 1)); - RUN(testSubImmArg32(1, 2)); - RUN(testSubImmArg32(13, -42)); - RUN(testSubImmArg32(-13, 42)); - RUN_BINARY(testSubArgMem32, int32Operands(), int32Operands()); - RUN_BINARY(testSubMemArg32, int32Operands(), int32Operands()); - RUN_BINARY(testSubImmMem32, int32Operands(), int32Operands()); - RUN_BINARY(testSubMemImm32, int32Operands(), int32Operands()); - RUN_UNARY(testNegValueSubOne32, int64Operands()); - - RUN_UNARY(testSubArgDouble, floatingPointOperands<double>()); - RUN_BINARY(testSubArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testSubArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testSubImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testSubImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_UNARY(testSubArgFloat, floatingPointOperands<float>()); - RUN_BINARY(testSubArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testSubArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testSubImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testSubImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_UNARY(testSubArgFloatWithUselessDoubleConversion, floatingPointOperands<float>()); - RUN_BINARY(testSubArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testSubArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - - RUN(testBitAndArgs(43, 43)); - RUN(testBitAndArgs(43, 0)); - RUN(testBitAndArgs(10, 3)); - RUN(testBitAndArgs(42, 0xffffffffffffffff)); - RUN(testBitAndSameArg(43)); - RUN(testBitAndSameArg(0)); - RUN(testBitAndSameArg(3)); - RUN(testBitAndSameArg(0xffffffffffffffff)); - RUN(testBitAndImms(43, 43)); - RUN(testBitAndImms(43, 0)); - RUN(testBitAndImms(10, 3)); - RUN(testBitAndImms(42, 0xffffffffffffffff)); - RUN(testBitAndArgImm(43, 43)); - RUN(testBitAndArgImm(43, 0)); - RUN(testBitAndArgImm(10, 3)); - RUN(testBitAndArgImm(42, 0xffffffffffffffff)); - RUN(testBitAndArgImm(42, 0xff)); - RUN(testBitAndArgImm(300, 0xff)); - RUN(testBitAndArgImm(-300, 0xff)); - RUN(testBitAndArgImm(42, 0xffff)); - RUN(testBitAndArgImm(40000, 0xffff)); - RUN(testBitAndArgImm(-40000, 0xffff)); - RUN(testBitAndImmArg(43, 43)); - RUN(testBitAndImmArg(43, 0)); - RUN(testBitAndImmArg(10, 3)); - RUN(testBitAndImmArg(42, 0xffffffffffffffff)); - RUN(testBitAndBitAndArgImmImm(2, 7, 3)); - RUN(testBitAndBitAndArgImmImm(1, 6, 6)); - RUN(testBitAndBitAndArgImmImm(0xffff, 24, 7)); - RUN(testBitAndImmBitAndArgImm(7, 2, 3)); - RUN(testBitAndImmBitAndArgImm(6, 1, 6)); - RUN(testBitAndImmBitAndArgImm(24, 0xffff, 7)); - RUN(testBitAndArgs32(43, 43)); - RUN(testBitAndArgs32(43, 0)); - RUN(testBitAndArgs32(10, 3)); - RUN(testBitAndArgs32(42, 0xffffffff)); - RUN(testBitAndSameArg32(43)); - RUN(testBitAndSameArg32(0)); - RUN(testBitAndSameArg32(3)); - RUN(testBitAndSameArg32(0xffffffff)); - RUN(testBitAndImms32(43, 43)); - RUN(testBitAndImms32(43, 0)); - RUN(testBitAndImms32(10, 3)); - RUN(testBitAndImms32(42, 0xffffffff)); - RUN(testBitAndArgImm32(43, 43)); - RUN(testBitAndArgImm32(43, 0)); - RUN(testBitAndArgImm32(10, 3)); - RUN(testBitAndArgImm32(42, 0xffffffff)); - RUN(testBitAndImmArg32(43, 43)); - RUN(testBitAndImmArg32(43, 0)); - RUN(testBitAndImmArg32(10, 3)); - RUN(testBitAndImmArg32(42, 0xffffffff)); - RUN(testBitAndImmArg32(42, 0xff)); - RUN(testBitAndImmArg32(300, 0xff)); - RUN(testBitAndImmArg32(-300, 0xff)); - RUN(testBitAndImmArg32(42, 0xffff)); - RUN(testBitAndImmArg32(40000, 0xffff)); - RUN(testBitAndImmArg32(-40000, 0xffff)); - RUN(testBitAndBitAndArgImmImm32(2, 7, 3)); - RUN(testBitAndBitAndArgImmImm32(1, 6, 6)); - RUN(testBitAndBitAndArgImmImm32(0xffff, 24, 7)); - RUN(testBitAndImmBitAndArgImm32(7, 2, 3)); - RUN(testBitAndImmBitAndArgImm32(6, 1, 6)); - RUN(testBitAndImmBitAndArgImm32(24, 0xffff, 7)); - RUN_BINARY(testBitAndWithMaskReturnsBooleans, int64Operands(), int64Operands()); - RUN_UNARY(testBitAndArgDouble, floatingPointOperands<double>()); - RUN_BINARY(testBitAndArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testBitAndArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testBitAndImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_UNARY(testBitAndArgFloat, floatingPointOperands<float>()); - RUN_BINARY(testBitAndArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testBitAndArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testBitAndImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testBitAndArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - - RUN(testBitOrArgs(43, 43)); - RUN(testBitOrArgs(43, 0)); - RUN(testBitOrArgs(10, 3)); - RUN(testBitOrArgs(42, 0xffffffffffffffff)); - RUN(testBitOrSameArg(43)); - RUN(testBitOrSameArg(0)); - RUN(testBitOrSameArg(3)); - RUN(testBitOrSameArg(0xffffffffffffffff)); - RUN(testBitOrImms(43, 43)); - RUN(testBitOrImms(43, 0)); - RUN(testBitOrImms(10, 3)); - RUN(testBitOrImms(42, 0xffffffffffffffff)); - RUN(testBitOrArgImm(43, 43)); - RUN(testBitOrArgImm(43, 0)); - RUN(testBitOrArgImm(10, 3)); - RUN(testBitOrArgImm(42, 0xffffffffffffffff)); - RUN(testBitOrImmArg(43, 43)); - RUN(testBitOrImmArg(43, 0)); - RUN(testBitOrImmArg(10, 3)); - RUN(testBitOrImmArg(42, 0xffffffffffffffff)); - RUN(testBitOrBitOrArgImmImm(2, 7, 3)); - RUN(testBitOrBitOrArgImmImm(1, 6, 6)); - RUN(testBitOrBitOrArgImmImm(0xffff, 24, 7)); - RUN(testBitOrImmBitOrArgImm(7, 2, 3)); - RUN(testBitOrImmBitOrArgImm(6, 1, 6)); - RUN(testBitOrImmBitOrArgImm(24, 0xffff, 7)); - RUN(testBitOrArgs32(43, 43)); - RUN(testBitOrArgs32(43, 0)); - RUN(testBitOrArgs32(10, 3)); - RUN(testBitOrArgs32(42, 0xffffffff)); - RUN(testBitOrSameArg32(43)); - RUN(testBitOrSameArg32(0)); - RUN(testBitOrSameArg32(3)); - RUN(testBitOrSameArg32(0xffffffff)); - RUN(testBitOrImms32(43, 43)); - RUN(testBitOrImms32(43, 0)); - RUN(testBitOrImms32(10, 3)); - RUN(testBitOrImms32(42, 0xffffffff)); - RUN(testBitOrArgImm32(43, 43)); - RUN(testBitOrArgImm32(43, 0)); - RUN(testBitOrArgImm32(10, 3)); - RUN(testBitOrArgImm32(42, 0xffffffff)); - RUN(testBitOrImmArg32(43, 43)); - RUN(testBitOrImmArg32(43, 0)); - RUN(testBitOrImmArg32(10, 3)); - RUN(testBitOrImmArg32(42, 0xffffffff)); - RUN(testBitOrBitOrArgImmImm32(2, 7, 3)); - RUN(testBitOrBitOrArgImmImm32(1, 6, 6)); - RUN(testBitOrBitOrArgImmImm32(0xffff, 24, 7)); - RUN(testBitOrImmBitOrArgImm32(7, 2, 3)); - RUN(testBitOrImmBitOrArgImm32(6, 1, 6)); - RUN(testBitOrImmBitOrArgImm32(24, 0xffff, 7)); - - RUN_BINARY(testBitXorArgs, int64Operands(), int64Operands()); - RUN_UNARY(testBitXorSameArg, int64Operands()); - RUN_BINARY(testBitXorImms, int64Operands(), int64Operands()); - RUN_BINARY(testBitXorArgImm, int64Operands(), int64Operands()); - RUN_BINARY(testBitXorImmArg, int64Operands(), int64Operands()); - RUN(testBitXorBitXorArgImmImm(2, 7, 3)); - RUN(testBitXorBitXorArgImmImm(1, 6, 6)); - RUN(testBitXorBitXorArgImmImm(0xffff, 24, 7)); - RUN(testBitXorImmBitXorArgImm(7, 2, 3)); - RUN(testBitXorImmBitXorArgImm(6, 1, 6)); - RUN(testBitXorImmBitXorArgImm(24, 0xffff, 7)); - RUN(testBitXorArgs32(43, 43)); - RUN(testBitXorArgs32(43, 0)); - RUN(testBitXorArgs32(10, 3)); - RUN(testBitXorArgs32(42, 0xffffffff)); - RUN(testBitXorSameArg32(43)); - RUN(testBitXorSameArg32(0)); - RUN(testBitXorSameArg32(3)); - RUN(testBitXorSameArg32(0xffffffff)); - RUN(testBitXorImms32(43, 43)); - RUN(testBitXorImms32(43, 0)); - RUN(testBitXorImms32(10, 3)); - RUN(testBitXorImms32(42, 0xffffffff)); - RUN(testBitXorArgImm32(43, 43)); - RUN(testBitXorArgImm32(43, 0)); - RUN(testBitXorArgImm32(10, 3)); - RUN(testBitXorArgImm32(42, 0xffffffff)); - RUN(testBitXorImmArg32(43, 43)); - RUN(testBitXorImmArg32(43, 0)); - RUN(testBitXorImmArg32(10, 3)); - RUN(testBitXorImmArg32(42, 0xffffffff)); - RUN(testBitXorBitXorArgImmImm32(2, 7, 3)); - RUN(testBitXorBitXorArgImmImm32(1, 6, 6)); - RUN(testBitXorBitXorArgImmImm32(0xffff, 24, 7)); - RUN(testBitXorImmBitXorArgImm32(7, 2, 3)); - RUN(testBitXorImmBitXorArgImm32(6, 1, 6)); - RUN(testBitXorImmBitXorArgImm32(24, 0xffff, 7)); - - RUN_UNARY(testBitNotArg, int64Operands()); - RUN_UNARY(testBitNotImm, int64Operands()); - RUN_UNARY(testBitNotMem, int64Operands()); - RUN_UNARY(testBitNotArg32, int32Operands()); - RUN_UNARY(testBitNotImm32, int32Operands()); - RUN_UNARY(testBitNotMem32, int32Operands()); - RUN_BINARY(testBitNotOnBooleanAndBranch32, int32Operands(), int32Operands()); - - RUN(testShlArgs(1, 0)); - RUN(testShlArgs(1, 1)); - RUN(testShlArgs(1, 62)); - RUN(testShlArgs(0xffffffffffffffff, 0)); - RUN(testShlArgs(0xffffffffffffffff, 1)); - RUN(testShlArgs(0xffffffffffffffff, 63)); - RUN(testShlImms(1, 0)); - RUN(testShlImms(1, 1)); - RUN(testShlImms(1, 62)); - RUN(testShlImms(1, 65)); - RUN(testShlImms(0xffffffffffffffff, 0)); - RUN(testShlImms(0xffffffffffffffff, 1)); - RUN(testShlImms(0xffffffffffffffff, 63)); - RUN(testShlArgImm(1, 0)); - RUN(testShlArgImm(1, 1)); - RUN(testShlArgImm(1, 62)); - RUN(testShlArgImm(1, 65)); - RUN(testShlArgImm(0xffffffffffffffff, 0)); - RUN(testShlArgImm(0xffffffffffffffff, 1)); - RUN(testShlArgImm(0xffffffffffffffff, 63)); - RUN(testShlArg32(2)); - RUN(testShlArgs32(1, 0)); - RUN(testShlArgs32(1, 1)); - RUN(testShlArgs32(1, 62)); - RUN(testShlImms32(1, 33)); - RUN(testShlArgs32(0xffffffff, 0)); - RUN(testShlArgs32(0xffffffff, 1)); - RUN(testShlArgs32(0xffffffff, 63)); - RUN(testShlImms32(1, 0)); - RUN(testShlImms32(1, 1)); - RUN(testShlImms32(1, 62)); - RUN(testShlImms32(1, 33)); - RUN(testShlImms32(0xffffffff, 0)); - RUN(testShlImms32(0xffffffff, 1)); - RUN(testShlImms32(0xffffffff, 63)); - RUN(testShlArgImm32(1, 0)); - RUN(testShlArgImm32(1, 1)); - RUN(testShlArgImm32(1, 62)); - RUN(testShlArgImm32(0xffffffff, 0)); - RUN(testShlArgImm32(0xffffffff, 1)); - RUN(testShlArgImm32(0xffffffff, 63)); - - RUN(testSShrArgs(1, 0)); - RUN(testSShrArgs(1, 1)); - RUN(testSShrArgs(1, 62)); - RUN(testSShrArgs(0xffffffffffffffff, 0)); - RUN(testSShrArgs(0xffffffffffffffff, 1)); - RUN(testSShrArgs(0xffffffffffffffff, 63)); - RUN(testSShrImms(1, 0)); - RUN(testSShrImms(1, 1)); - RUN(testSShrImms(1, 62)); - RUN(testSShrImms(1, 65)); - RUN(testSShrImms(0xffffffffffffffff, 0)); - RUN(testSShrImms(0xffffffffffffffff, 1)); - RUN(testSShrImms(0xffffffffffffffff, 63)); - RUN(testSShrArgImm(1, 0)); - RUN(testSShrArgImm(1, 1)); - RUN(testSShrArgImm(1, 62)); - RUN(testSShrArgImm(1, 65)); - RUN(testSShrArgImm(0xffffffffffffffff, 0)); - RUN(testSShrArgImm(0xffffffffffffffff, 1)); - RUN(testSShrArgImm(0xffffffffffffffff, 63)); - RUN(testSShrArg32(32)); - RUN(testSShrArgs32(1, 0)); - RUN(testSShrArgs32(1, 1)); - RUN(testSShrArgs32(1, 62)); - RUN(testSShrArgs32(1, 33)); - RUN(testSShrArgs32(0xffffffff, 0)); - RUN(testSShrArgs32(0xffffffff, 1)); - RUN(testSShrArgs32(0xffffffff, 63)); - RUN(testSShrImms32(1, 0)); - RUN(testSShrImms32(1, 1)); - RUN(testSShrImms32(1, 62)); - RUN(testSShrImms32(1, 33)); - RUN(testSShrImms32(0xffffffff, 0)); - RUN(testSShrImms32(0xffffffff, 1)); - RUN(testSShrImms32(0xffffffff, 63)); - RUN(testSShrArgImm32(1, 0)); - RUN(testSShrArgImm32(1, 1)); - RUN(testSShrArgImm32(1, 62)); - RUN(testSShrArgImm32(0xffffffff, 0)); - RUN(testSShrArgImm32(0xffffffff, 1)); - RUN(testSShrArgImm32(0xffffffff, 63)); - - RUN(testZShrArgs(1, 0)); - RUN(testZShrArgs(1, 1)); - RUN(testZShrArgs(1, 62)); - RUN(testZShrArgs(0xffffffffffffffff, 0)); - RUN(testZShrArgs(0xffffffffffffffff, 1)); - RUN(testZShrArgs(0xffffffffffffffff, 63)); - RUN(testZShrImms(1, 0)); - RUN(testZShrImms(1, 1)); - RUN(testZShrImms(1, 62)); - RUN(testZShrImms(1, 65)); - RUN(testZShrImms(0xffffffffffffffff, 0)); - RUN(testZShrImms(0xffffffffffffffff, 1)); - RUN(testZShrImms(0xffffffffffffffff, 63)); - RUN(testZShrArgImm(1, 0)); - RUN(testZShrArgImm(1, 1)); - RUN(testZShrArgImm(1, 62)); - RUN(testZShrArgImm(1, 65)); - RUN(testZShrArgImm(0xffffffffffffffff, 0)); - RUN(testZShrArgImm(0xffffffffffffffff, 1)); - RUN(testZShrArgImm(0xffffffffffffffff, 63)); - RUN(testZShrArg32(32)); - RUN(testZShrArgs32(1, 0)); - RUN(testZShrArgs32(1, 1)); - RUN(testZShrArgs32(1, 62)); - RUN(testZShrArgs32(1, 33)); - RUN(testZShrArgs32(0xffffffff, 0)); - RUN(testZShrArgs32(0xffffffff, 1)); - RUN(testZShrArgs32(0xffffffff, 63)); - RUN(testZShrImms32(1, 0)); - RUN(testZShrImms32(1, 1)); - RUN(testZShrImms32(1, 62)); - RUN(testZShrImms32(1, 33)); - RUN(testZShrImms32(0xffffffff, 0)); - RUN(testZShrImms32(0xffffffff, 1)); - RUN(testZShrImms32(0xffffffff, 63)); - RUN(testZShrArgImm32(1, 0)); - RUN(testZShrArgImm32(1, 1)); - RUN(testZShrArgImm32(1, 62)); - RUN(testZShrArgImm32(0xffffffff, 0)); - RUN(testZShrArgImm32(0xffffffff, 1)); - RUN(testZShrArgImm32(0xffffffff, 63)); - - RUN_UNARY(testClzArg64, int64Operands()); - RUN_UNARY(testClzMem64, int64Operands()); - RUN_UNARY(testClzArg32, int32Operands()); - RUN_UNARY(testClzMem32, int64Operands()); - - RUN_UNARY(testAbsArg, floatingPointOperands<double>()); - RUN_UNARY(testAbsImm, floatingPointOperands<double>()); - RUN_UNARY(testAbsMem, floatingPointOperands<double>()); - RUN_UNARY(testAbsAbsArg, floatingPointOperands<double>()); - RUN_UNARY(testAbsBitwiseCastArg, floatingPointOperands<double>()); - RUN_UNARY(testBitwiseCastAbsBitwiseCastArg, floatingPointOperands<double>()); - RUN_UNARY(testAbsArg, floatingPointOperands<float>()); - RUN_UNARY(testAbsImm, floatingPointOperands<float>()); - RUN_UNARY(testAbsMem, floatingPointOperands<float>()); - RUN_UNARY(testAbsAbsArg, floatingPointOperands<float>()); - RUN_UNARY(testAbsBitwiseCastArg, floatingPointOperands<float>()); - RUN_UNARY(testBitwiseCastAbsBitwiseCastArg, floatingPointOperands<float>()); - RUN_UNARY(testAbsArgWithUselessDoubleConversion, floatingPointOperands<float>()); - RUN_UNARY(testAbsArgWithEffectfulDoubleConversion, floatingPointOperands<float>()); - - RUN_UNARY(testCeilArg, floatingPointOperands<double>()); - RUN_UNARY(testCeilImm, floatingPointOperands<double>()); - RUN_UNARY(testCeilMem, floatingPointOperands<double>()); - RUN_UNARY(testCeilCeilArg, floatingPointOperands<double>()); - RUN_UNARY(testFloorCeilArg, floatingPointOperands<double>()); - RUN_UNARY(testCeilIToD64, int64Operands()); - RUN_UNARY(testCeilIToD32, int32Operands()); - RUN_UNARY(testCeilArg, floatingPointOperands<float>()); - RUN_UNARY(testCeilImm, floatingPointOperands<float>()); - RUN_UNARY(testCeilMem, floatingPointOperands<float>()); - RUN_UNARY(testCeilCeilArg, floatingPointOperands<float>()); - RUN_UNARY(testFloorCeilArg, floatingPointOperands<float>()); - RUN_UNARY(testCeilArgWithUselessDoubleConversion, floatingPointOperands<float>()); - RUN_UNARY(testCeilArgWithEffectfulDoubleConversion, floatingPointOperands<float>()); - - RUN_UNARY(testFloorArg, floatingPointOperands<double>()); - RUN_UNARY(testFloorImm, floatingPointOperands<double>()); - RUN_UNARY(testFloorMem, floatingPointOperands<double>()); - RUN_UNARY(testFloorFloorArg, floatingPointOperands<double>()); - RUN_UNARY(testCeilFloorArg, floatingPointOperands<double>()); - RUN_UNARY(testFloorIToD64, int64Operands()); - RUN_UNARY(testFloorIToD32, int32Operands()); - RUN_UNARY(testFloorArg, floatingPointOperands<float>()); - RUN_UNARY(testFloorImm, floatingPointOperands<float>()); - RUN_UNARY(testFloorMem, floatingPointOperands<float>()); - RUN_UNARY(testFloorFloorArg, floatingPointOperands<float>()); - RUN_UNARY(testCeilFloorArg, floatingPointOperands<float>()); - RUN_UNARY(testFloorArgWithUselessDoubleConversion, floatingPointOperands<float>()); - RUN_UNARY(testFloorArgWithEffectfulDoubleConversion, floatingPointOperands<float>()); - - RUN_UNARY(testSqrtArg, floatingPointOperands<double>()); - RUN_UNARY(testSqrtImm, floatingPointOperands<double>()); - RUN_UNARY(testSqrtMem, floatingPointOperands<double>()); - RUN_UNARY(testSqrtArg, floatingPointOperands<float>()); - RUN_UNARY(testSqrtImm, floatingPointOperands<float>()); - RUN_UNARY(testSqrtMem, floatingPointOperands<float>()); - RUN_UNARY(testSqrtArgWithUselessDoubleConversion, floatingPointOperands<float>()); - RUN_UNARY(testSqrtArgWithEffectfulDoubleConversion, floatingPointOperands<float>()); - - RUN_UNARY(testDoubleArgToInt64BitwiseCast, floatingPointOperands<double>()); - RUN_UNARY(testDoubleImmToInt64BitwiseCast, floatingPointOperands<double>()); - RUN_UNARY(testTwoBitwiseCastOnDouble, floatingPointOperands<double>()); - RUN_UNARY(testBitwiseCastOnDoubleInMemory, floatingPointOperands<double>()); - RUN_UNARY(testBitwiseCastOnDoubleInMemoryIndexed, floatingPointOperands<double>()); - RUN_UNARY(testInt64BArgToDoubleBitwiseCast, int64Operands()); - RUN_UNARY(testInt64BImmToDoubleBitwiseCast, int64Operands()); - RUN_UNARY(testTwoBitwiseCastOnInt64, int64Operands()); - RUN_UNARY(testBitwiseCastOnInt64InMemory, int64Operands()); - RUN_UNARY(testBitwiseCastOnInt64InMemoryIndexed, int64Operands()); - RUN_UNARY(testFloatImmToInt32BitwiseCast, floatingPointOperands<float>()); - RUN_UNARY(testBitwiseCastOnFloatInMemory, floatingPointOperands<float>()); - RUN_UNARY(testInt32BArgToFloatBitwiseCast, int32Operands()); - RUN_UNARY(testInt32BImmToFloatBitwiseCast, int32Operands()); - RUN_UNARY(testTwoBitwiseCastOnInt32, int32Operands()); - RUN_UNARY(testBitwiseCastOnInt32InMemory, int32Operands()); - - RUN_UNARY(testConvertDoubleToFloatArg, floatingPointOperands<double>()); - RUN_UNARY(testConvertDoubleToFloatImm, floatingPointOperands<double>()); - RUN_UNARY(testConvertDoubleToFloatMem, floatingPointOperands<double>()); - RUN_UNARY(testConvertFloatToDoubleArg, floatingPointOperands<float>()); - RUN_UNARY(testConvertFloatToDoubleImm, floatingPointOperands<float>()); - RUN_UNARY(testConvertFloatToDoubleMem, floatingPointOperands<float>()); - RUN_UNARY(testConvertDoubleToFloatToDoubleToFloat, floatingPointOperands<double>()); - RUN_UNARY(testStoreFloat, floatingPointOperands<double>()); - RUN_UNARY(testLoadFloatConvertDoubleConvertFloatStoreFloat, floatingPointOperands<float>()); - RUN_UNARY(testFroundArg, floatingPointOperands<double>()); - RUN_UNARY(testFroundMem, floatingPointOperands<double>()); - - RUN(testStore32(44)); - RUN(testStoreConstant(49)); - RUN(testStoreConstantPtr(49)); - RUN(testStore8Arg()); - RUN(testStore8Imm()); - RUN(testStorePartial8BitRegisterOnX86()); - RUN(testStore16Arg()); - RUN(testStore16Imm()); - RUN(testTrunc((static_cast<int64_t>(1) << 40) + 42)); - RUN(testAdd1(45)); - RUN(testAdd1Ptr(51)); - RUN(testAdd1Ptr(bitwise_cast<intptr_t>(vm))); - RUN(testNeg32(52)); - RUN(testNegPtr(53)); - RUN(testStoreAddLoad32(46)); - RUN(testStoreAddLoadImm32(46)); - RUN(testStoreAddLoad64(4600)); - RUN(testStoreAddLoadImm64(4600)); - RUN(testStoreAddLoad8(4, Load8Z)); - RUN(testStoreAddLoadImm8(4, Load8Z)); - RUN(testStoreAddLoad8(4, Load8S)); - RUN(testStoreAddLoadImm8(4, Load8S)); - RUN(testStoreAddLoad16(6, Load16Z)); - RUN(testStoreAddLoadImm16(6, Load16Z)); - RUN(testStoreAddLoad16(6, Load16S)); - RUN(testStoreAddLoadImm16(6, Load16S)); - RUN(testStoreAddLoad32Index(46)); - RUN(testStoreAddLoadImm32Index(46)); - RUN(testStoreAddLoad64Index(4600)); - RUN(testStoreAddLoadImm64Index(4600)); - RUN(testStoreAddLoad8Index(4, Load8Z)); - RUN(testStoreAddLoadImm8Index(4, Load8Z)); - RUN(testStoreAddLoad8Index(4, Load8S)); - RUN(testStoreAddLoadImm8Index(4, Load8S)); - RUN(testStoreAddLoad16Index(6, Load16Z)); - RUN(testStoreAddLoadImm16Index(6, Load16Z)); - RUN(testStoreAddLoad16Index(6, Load16S)); - RUN(testStoreAddLoadImm16Index(6, Load16S)); - RUN(testStoreSubLoad(46)); - RUN(testStoreAddLoadInterference(52)); - RUN(testStoreAddAndLoad(47, 0xffff)); - RUN(testStoreAddAndLoad(470000, 0xffff)); - RUN(testStoreNegLoad32(54)); - RUN(testStoreNegLoadPtr(55)); - RUN(testAdd1Uncommuted(48)); - RUN(testLoadOffset()); - RUN(testLoadOffsetNotConstant()); - RUN(testLoadOffsetUsingAdd()); - RUN(testLoadOffsetUsingAddInterference()); - RUN(testLoadOffsetUsingAddNotConstant()); - RUN(testLoadAddrShift(0)); - RUN(testLoadAddrShift(1)); - RUN(testLoadAddrShift(2)); - RUN(testLoadAddrShift(3)); - RUN(testFramePointer()); - RUN(testOverrideFramePointer()); - RUN(testStackSlot()); - RUN(testLoadFromFramePointer()); - RUN(testStoreLoadStackSlot(50)); - - RUN(testBranch()); - RUN(testBranchPtr()); - RUN(testDiamond()); - RUN(testBranchNotEqual()); - RUN(testBranchNotEqualCommute()); - RUN(testBranchNotEqualNotEqual()); - RUN(testBranchEqual()); - RUN(testBranchEqualEqual()); - RUN(testBranchEqualCommute()); - RUN(testBranchEqualEqual1()); - RUN_BINARY(testBranchEqualOrUnorderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testBranchEqualOrUnorderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testBranchEqualOrUnorderedDoubleArgImm, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testBranchEqualOrUnorderedFloatArgImm, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testBranchEqualOrUnorderedDoubleImms, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testBranchEqualOrUnorderedFloatImms, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testBranchEqualOrUnorderedFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>()); - RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN(testBranchFold(42)); - RUN(testBranchFold(0)); - RUN(testDiamondFold(42)); - RUN(testDiamondFold(0)); - RUN(testBranchNotEqualFoldPtr(42)); - RUN(testBranchNotEqualFoldPtr(0)); - RUN(testBranchEqualFoldPtr(42)); - RUN(testBranchEqualFoldPtr(0)); - RUN(testBranchLoadPtr()); - RUN(testBranchLoad32()); - RUN(testBranchLoad8S()); - RUN(testBranchLoad8Z()); - RUN(testBranchLoad16S()); - RUN(testBranchLoad16Z()); - - RUN(testComplex(64, 128)); - RUN(testComplex(4, 128)); - RUN(testComplex(4, 256)); - RUN(testComplex(4, 384)); - - RUN(testSimplePatchpoint()); - RUN(testSimplePatchpointWithoutOuputClobbersGPArgs()); - RUN(testSimplePatchpointWithOuputClobbersGPArgs()); - RUN(testSimplePatchpointWithoutOuputClobbersFPArgs()); - RUN(testSimplePatchpointWithOuputClobbersFPArgs()); - RUN(testPatchpointWithEarlyClobber()); - RUN(testPatchpointCallArg()); - RUN(testPatchpointFixedRegister()); - RUN(testPatchpointAny(ValueRep::WarmAny)); - RUN(testPatchpointAny(ValueRep::ColdAny)); - RUN(testPatchpointGPScratch()); - RUN(testPatchpointFPScratch()); - RUN(testPatchpointLotsOfLateAnys()); - RUN(testPatchpointAnyImm(ValueRep::WarmAny)); - RUN(testPatchpointAnyImm(ValueRep::ColdAny)); - RUN(testPatchpointAnyImm(ValueRep::LateColdAny)); - RUN(testPatchpointManyImms()); - RUN(testPatchpointWithRegisterResult()); - RUN(testPatchpointWithStackArgumentResult()); - RUN(testPatchpointWithAnyResult()); - RUN(testSimpleCheck()); - RUN(testCheckFalse()); - RUN(testCheckTrue()); - RUN(testCheckLessThan()); - RUN(testCheckMegaCombo()); - RUN(testCheckTrickyMegaCombo()); - RUN(testCheckTwoMegaCombos()); - RUN(testCheckTwoNonRedundantMegaCombos()); - RUN(testCheckAddImm()); - RUN(testCheckAddImmCommute()); - RUN(testCheckAddImmSomeRegister()); - RUN(testCheckAdd()); - RUN(testCheckAdd64()); - RUN(testCheckAddFold(100, 200)); - RUN(testCheckAddFoldFail(2147483647, 100)); - RUN(testCheckAddArgumentAliasing64()); - RUN(testCheckAddArgumentAliasing32()); - RUN(testCheckAddSelfOverflow64()); - RUN(testCheckAddSelfOverflow32()); - RUN(testCheckSubImm()); - RUN(testCheckSubBadImm()); - RUN(testCheckSub()); - RUN(testCheckSub64()); - RUN(testCheckSubFold(100, 200)); - RUN(testCheckSubFoldFail(-2147483647, 100)); - RUN(testCheckNeg()); - RUN(testCheckNeg64()); - RUN(testCheckMul()); - RUN(testCheckMulMemory()); - RUN(testCheckMul2()); - RUN(testCheckMul64()); - RUN(testCheckMulFold(100, 200)); - RUN(testCheckMulFoldFail(2147483647, 100)); - RUN(testCheckMulArgumentAliasing64()); - RUN(testCheckMulArgumentAliasing32()); - - RUN_BINARY([](int32_t a, int32_t b) { testCompare(Equal, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(NotEqual, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(LessThan, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(GreaterThan, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(LessEqual, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(GreaterEqual, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(Below, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(Above, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(BelowEqual, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(AboveEqual, a, b); }, int64Operands(), int64Operands()); - RUN_BINARY([](int32_t a, int32_t b) { testCompare(BitAnd, a, b); }, int64Operands(), int64Operands()); - - RUN(testEqualDouble(42, 42, true)); - RUN(testEqualDouble(0, -0, true)); - RUN(testEqualDouble(42, 43, false)); - RUN(testEqualDouble(PNaN, 42, false)); - RUN(testEqualDouble(42, PNaN, false)); - RUN(testEqualDouble(PNaN, PNaN, false)); - - RUN(testLoad<Int32>(60)); - RUN(testLoad<Int32>(-60)); - RUN(testLoad<Int32>(1000)); - RUN(testLoad<Int32>(-1000)); - RUN(testLoad<Int32>(1000000)); - RUN(testLoad<Int32>(-1000000)); - RUN(testLoad<Int32>(1000000000)); - RUN(testLoad<Int32>(-1000000000)); - RUN_UNARY(testLoad<Int64>, int64Operands()); - RUN_UNARY(testLoad<Float>, floatingPointOperands<float>()); - RUN_UNARY(testLoad<Double>, floatingPointOperands<double>()); - - RUN(testLoad<int8_t>(Load8S, 60)); - RUN(testLoad<int8_t>(Load8S, -60)); - RUN(testLoad<int8_t>(Load8S, 1000)); - RUN(testLoad<int8_t>(Load8S, -1000)); - RUN(testLoad<int8_t>(Load8S, 1000000)); - RUN(testLoad<int8_t>(Load8S, -1000000)); - RUN(testLoad<int8_t>(Load8S, 1000000000)); - RUN(testLoad<int8_t>(Load8S, -1000000000)); - - RUN(testLoad<uint8_t>(Load8Z, 60)); - RUN(testLoad<uint8_t>(Load8Z, -60)); - RUN(testLoad<uint8_t>(Load8Z, 1000)); - RUN(testLoad<uint8_t>(Load8Z, -1000)); - RUN(testLoad<uint8_t>(Load8Z, 1000000)); - RUN(testLoad<uint8_t>(Load8Z, -1000000)); - RUN(testLoad<uint8_t>(Load8Z, 1000000000)); - RUN(testLoad<uint8_t>(Load8Z, -1000000000)); - - RUN(testLoad<int16_t>(Load16S, 60)); - RUN(testLoad<int16_t>(Load16S, -60)); - RUN(testLoad<int16_t>(Load16S, 1000)); - RUN(testLoad<int16_t>(Load16S, -1000)); - RUN(testLoad<int16_t>(Load16S, 1000000)); - RUN(testLoad<int16_t>(Load16S, -1000000)); - RUN(testLoad<int16_t>(Load16S, 1000000000)); - RUN(testLoad<int16_t>(Load16S, -1000000000)); - - RUN(testLoad<uint16_t>(Load16Z, 60)); - RUN(testLoad<uint16_t>(Load16Z, -60)); - RUN(testLoad<uint16_t>(Load16Z, 1000)); - RUN(testLoad<uint16_t>(Load16Z, -1000)); - RUN(testLoad<uint16_t>(Load16Z, 1000000)); - RUN(testLoad<uint16_t>(Load16Z, -1000000)); - RUN(testLoad<uint16_t>(Load16Z, 1000000000)); - RUN(testLoad<uint16_t>(Load16Z, -1000000000)); - - RUN(testSpillGP()); - RUN(testSpillFP()); - - RUN(testInt32ToDoublePartialRegisterStall()); - RUN(testInt32ToDoublePartialRegisterWithoutStall()); - - RUN(testCallSimple(1, 2)); - RUN(testCallRare(1, 2)); - RUN(testCallRareLive(1, 2, 3)); - RUN(testCallSimplePure(1, 2)); - RUN(testCallFunctionWithHellaArguments()); - - RUN(testReturnDouble(0.0)); - RUN(testReturnDouble(negativeZero())); - RUN(testReturnDouble(42.5)); - RUN_UNARY(testReturnFloat, floatingPointOperands<float>()); - - RUN(testCallSimpleDouble(1, 2)); - RUN(testCallFunctionWithHellaDoubleArguments()); - RUN_BINARY(testCallSimpleFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN(testCallFunctionWithHellaFloatArguments()); - - RUN(testChillDiv(4, 2, 2)); - RUN(testChillDiv(1, 0, 0)); - RUN(testChillDiv(0, 0, 0)); - RUN(testChillDiv(1, -1, -1)); - RUN(testChillDiv(-2147483647 - 1, 0, 0)); - RUN(testChillDiv(-2147483647 - 1, 1, -2147483647 - 1)); - RUN(testChillDiv(-2147483647 - 1, -1, -2147483647 - 1)); - RUN(testChillDiv(-2147483647 - 1, 2, -1073741824)); - RUN(testChillDiv64(4, 2, 2)); - RUN(testChillDiv64(1, 0, 0)); - RUN(testChillDiv64(0, 0, 0)); - RUN(testChillDiv64(1, -1, -1)); - RUN(testChillDiv64(-9223372036854775807ll - 1, 0, 0)); - RUN(testChillDiv64(-9223372036854775807ll - 1, 1, -9223372036854775807ll - 1)); - RUN(testChillDiv64(-9223372036854775807ll - 1, -1, -9223372036854775807ll - 1)); - RUN(testChillDiv64(-9223372036854775807ll - 1, 2, -4611686018427387904)); - RUN(testChillDivTwice(4, 2, 6, 2, 5)); - RUN(testChillDivTwice(4, 0, 6, 2, 3)); - RUN(testChillDivTwice(4, 2, 6, 0, 2)); - - RUN_UNARY(testModArg, int64Operands()); - RUN_BINARY(testModArgs, int64Operands(), int64Operands()); - RUN_BINARY(testModImms, int64Operands(), int64Operands()); - RUN_UNARY(testModArg32, int32Operands()); - RUN_BINARY(testModArgs32, int32Operands(), int32Operands()); - RUN_BINARY(testModImms32, int32Operands(), int32Operands()); - RUN_UNARY(testChillModArg, int64Operands()); - RUN_BINARY(testChillModArgs, int64Operands(), int64Operands()); - RUN_BINARY(testChillModImms, int64Operands(), int64Operands()); - RUN_UNARY(testChillModArg32, int32Operands()); - RUN_BINARY(testChillModArgs32, int32Operands(), int32Operands()); - RUN_BINARY(testChillModImms32, int32Operands(), int32Operands()); - - RUN(testSwitch(0, 1)); - RUN(testSwitch(1, 1)); - RUN(testSwitch(2, 1)); - RUN(testSwitch(2, 2)); - RUN(testSwitch(10, 1)); - RUN(testSwitch(10, 2)); - RUN(testSwitch(100, 1)); - RUN(testSwitch(100, 100)); - - RUN(testSwitchChillDiv(0, 1)); - RUN(testSwitchChillDiv(1, 1)); - RUN(testSwitchChillDiv(2, 1)); - RUN(testSwitchChillDiv(2, 2)); - RUN(testSwitchChillDiv(10, 1)); - RUN(testSwitchChillDiv(10, 2)); - RUN(testSwitchChillDiv(100, 1)); - RUN(testSwitchChillDiv(100, 100)); - - RUN(testSwitchTargettingSameBlock()); - RUN(testSwitchTargettingSameBlockFoldPathConstant()); - - RUN(testTrunc(0)); - RUN(testTrunc(1)); - RUN(testTrunc(-1)); - RUN(testTrunc(1000000000000ll)); - RUN(testTrunc(-1000000000000ll)); - RUN(testTruncFold(0)); - RUN(testTruncFold(1)); - RUN(testTruncFold(-1)); - RUN(testTruncFold(1000000000000ll)); - RUN(testTruncFold(-1000000000000ll)); - - RUN(testZExt32(0)); - RUN(testZExt32(1)); - RUN(testZExt32(-1)); - RUN(testZExt32(1000000000ll)); - RUN(testZExt32(-1000000000ll)); - RUN(testZExt32Fold(0)); - RUN(testZExt32Fold(1)); - RUN(testZExt32Fold(-1)); - RUN(testZExt32Fold(1000000000ll)); - RUN(testZExt32Fold(-1000000000ll)); - - RUN(testSExt32(0)); - RUN(testSExt32(1)); - RUN(testSExt32(-1)); - RUN(testSExt32(1000000000ll)); - RUN(testSExt32(-1000000000ll)); - RUN(testSExt32Fold(0)); - RUN(testSExt32Fold(1)); - RUN(testSExt32Fold(-1)); - RUN(testSExt32Fold(1000000000ll)); - RUN(testSExt32Fold(-1000000000ll)); - - RUN(testTruncZExt32(0)); - RUN(testTruncZExt32(1)); - RUN(testTruncZExt32(-1)); - RUN(testTruncZExt32(1000000000ll)); - RUN(testTruncZExt32(-1000000000ll)); - RUN(testTruncSExt32(0)); - RUN(testTruncSExt32(1)); - RUN(testTruncSExt32(-1)); - RUN(testTruncSExt32(1000000000ll)); - RUN(testTruncSExt32(-1000000000ll)); - - RUN(testSExt8(0)); - RUN(testSExt8(1)); - RUN(testSExt8(42)); - RUN(testSExt8(-1)); - RUN(testSExt8(0xff)); - RUN(testSExt8(0x100)); - RUN(testSExt8Fold(0)); - RUN(testSExt8Fold(1)); - RUN(testSExt8Fold(42)); - RUN(testSExt8Fold(-1)); - RUN(testSExt8Fold(0xff)); - RUN(testSExt8Fold(0x100)); - RUN(testSExt8SExt8(0)); - RUN(testSExt8SExt8(1)); - RUN(testSExt8SExt8(42)); - RUN(testSExt8SExt8(-1)); - RUN(testSExt8SExt8(0xff)); - RUN(testSExt8SExt8(0x100)); - RUN(testSExt8SExt16(0)); - RUN(testSExt8SExt16(1)); - RUN(testSExt8SExt16(42)); - RUN(testSExt8SExt16(-1)); - RUN(testSExt8SExt16(0xff)); - RUN(testSExt8SExt16(0x100)); - RUN(testSExt8SExt16(0xffff)); - RUN(testSExt8SExt16(0x10000)); - RUN(testSExt8BitAnd(0, 0)); - RUN(testSExt8BitAnd(1, 0)); - RUN(testSExt8BitAnd(42, 0)); - RUN(testSExt8BitAnd(-1, 0)); - RUN(testSExt8BitAnd(0xff, 0)); - RUN(testSExt8BitAnd(0x100, 0)); - RUN(testSExt8BitAnd(0xffff, 0)); - RUN(testSExt8BitAnd(0x10000, 0)); - RUN(testSExt8BitAnd(0, 0xf)); - RUN(testSExt8BitAnd(1, 0xf)); - RUN(testSExt8BitAnd(42, 0xf)); - RUN(testSExt8BitAnd(-1, 0xf)); - RUN(testSExt8BitAnd(0xff, 0xf)); - RUN(testSExt8BitAnd(0x100, 0xf)); - RUN(testSExt8BitAnd(0xffff, 0xf)); - RUN(testSExt8BitAnd(0x10000, 0xf)); - RUN(testSExt8BitAnd(0, 0xff)); - RUN(testSExt8BitAnd(1, 0xff)); - RUN(testSExt8BitAnd(42, 0xff)); - RUN(testSExt8BitAnd(-1, 0xff)); - RUN(testSExt8BitAnd(0xff, 0xff)); - RUN(testSExt8BitAnd(0x100, 0xff)); - RUN(testSExt8BitAnd(0xffff, 0xff)); - RUN(testSExt8BitAnd(0x10000, 0xff)); - RUN(testSExt8BitAnd(0, 0x80)); - RUN(testSExt8BitAnd(1, 0x80)); - RUN(testSExt8BitAnd(42, 0x80)); - RUN(testSExt8BitAnd(-1, 0x80)); - RUN(testSExt8BitAnd(0xff, 0x80)); - RUN(testSExt8BitAnd(0x100, 0x80)); - RUN(testSExt8BitAnd(0xffff, 0x80)); - RUN(testSExt8BitAnd(0x10000, 0x80)); - RUN(testBitAndSExt8(0, 0xf)); - RUN(testBitAndSExt8(1, 0xf)); - RUN(testBitAndSExt8(42, 0xf)); - RUN(testBitAndSExt8(-1, 0xf)); - RUN(testBitAndSExt8(0xff, 0xf)); - RUN(testBitAndSExt8(0x100, 0xf)); - RUN(testBitAndSExt8(0xffff, 0xf)); - RUN(testBitAndSExt8(0x10000, 0xf)); - RUN(testBitAndSExt8(0, 0xff)); - RUN(testBitAndSExt8(1, 0xff)); - RUN(testBitAndSExt8(42, 0xff)); - RUN(testBitAndSExt8(-1, 0xff)); - RUN(testBitAndSExt8(0xff, 0xff)); - RUN(testBitAndSExt8(0x100, 0xff)); - RUN(testBitAndSExt8(0xffff, 0xff)); - RUN(testBitAndSExt8(0x10000, 0xff)); - RUN(testBitAndSExt8(0, 0xfff)); - RUN(testBitAndSExt8(1, 0xfff)); - RUN(testBitAndSExt8(42, 0xfff)); - RUN(testBitAndSExt8(-1, 0xfff)); - RUN(testBitAndSExt8(0xff, 0xfff)); - RUN(testBitAndSExt8(0x100, 0xfff)); - RUN(testBitAndSExt8(0xffff, 0xfff)); - RUN(testBitAndSExt8(0x10000, 0xfff)); - - RUN(testSExt16(0)); - RUN(testSExt16(1)); - RUN(testSExt16(42)); - RUN(testSExt16(-1)); - RUN(testSExt16(0xffff)); - RUN(testSExt16(0x10000)); - RUN(testSExt16Fold(0)); - RUN(testSExt16Fold(1)); - RUN(testSExt16Fold(42)); - RUN(testSExt16Fold(-1)); - RUN(testSExt16Fold(0xffff)); - RUN(testSExt16Fold(0x10000)); - RUN(testSExt16SExt8(0)); - RUN(testSExt16SExt8(1)); - RUN(testSExt16SExt8(42)); - RUN(testSExt16SExt8(-1)); - RUN(testSExt16SExt8(0xffff)); - RUN(testSExt16SExt8(0x10000)); - RUN(testSExt16SExt16(0)); - RUN(testSExt16SExt16(1)); - RUN(testSExt16SExt16(42)); - RUN(testSExt16SExt16(-1)); - RUN(testSExt16SExt16(0xffff)); - RUN(testSExt16SExt16(0x10000)); - RUN(testSExt16SExt16(0xffffff)); - RUN(testSExt16SExt16(0x1000000)); - RUN(testSExt16BitAnd(0, 0)); - RUN(testSExt16BitAnd(1, 0)); - RUN(testSExt16BitAnd(42, 0)); - RUN(testSExt16BitAnd(-1, 0)); - RUN(testSExt16BitAnd(0xffff, 0)); - RUN(testSExt16BitAnd(0x10000, 0)); - RUN(testSExt16BitAnd(0xffffff, 0)); - RUN(testSExt16BitAnd(0x1000000, 0)); - RUN(testSExt16BitAnd(0, 0xf)); - RUN(testSExt16BitAnd(1, 0xf)); - RUN(testSExt16BitAnd(42, 0xf)); - RUN(testSExt16BitAnd(-1, 0xf)); - RUN(testSExt16BitAnd(0xffff, 0xf)); - RUN(testSExt16BitAnd(0x10000, 0xf)); - RUN(testSExt16BitAnd(0xffffff, 0xf)); - RUN(testSExt16BitAnd(0x1000000, 0xf)); - RUN(testSExt16BitAnd(0, 0xffff)); - RUN(testSExt16BitAnd(1, 0xffff)); - RUN(testSExt16BitAnd(42, 0xffff)); - RUN(testSExt16BitAnd(-1, 0xffff)); - RUN(testSExt16BitAnd(0xffff, 0xffff)); - RUN(testSExt16BitAnd(0x10000, 0xffff)); - RUN(testSExt16BitAnd(0xffffff, 0xffff)); - RUN(testSExt16BitAnd(0x1000000, 0xffff)); - RUN(testSExt16BitAnd(0, 0x8000)); - RUN(testSExt16BitAnd(1, 0x8000)); - RUN(testSExt16BitAnd(42, 0x8000)); - RUN(testSExt16BitAnd(-1, 0x8000)); - RUN(testSExt16BitAnd(0xffff, 0x8000)); - RUN(testSExt16BitAnd(0x10000, 0x8000)); - RUN(testSExt16BitAnd(0xffffff, 0x8000)); - RUN(testSExt16BitAnd(0x1000000, 0x8000)); - RUN(testBitAndSExt16(0, 0xf)); - RUN(testBitAndSExt16(1, 0xf)); - RUN(testBitAndSExt16(42, 0xf)); - RUN(testBitAndSExt16(-1, 0xf)); - RUN(testBitAndSExt16(0xffff, 0xf)); - RUN(testBitAndSExt16(0x10000, 0xf)); - RUN(testBitAndSExt16(0xffffff, 0xf)); - RUN(testBitAndSExt16(0x1000000, 0xf)); - RUN(testBitAndSExt16(0, 0xffff)); - RUN(testBitAndSExt16(1, 0xffff)); - RUN(testBitAndSExt16(42, 0xffff)); - RUN(testBitAndSExt16(-1, 0xffff)); - RUN(testBitAndSExt16(0xffff, 0xffff)); - RUN(testBitAndSExt16(0x10000, 0xffff)); - RUN(testBitAndSExt16(0xffffff, 0xffff)); - RUN(testBitAndSExt16(0x1000000, 0xffff)); - RUN(testBitAndSExt16(0, 0xfffff)); - RUN(testBitAndSExt16(1, 0xfffff)); - RUN(testBitAndSExt16(42, 0xfffff)); - RUN(testBitAndSExt16(-1, 0xfffff)); - RUN(testBitAndSExt16(0xffff, 0xfffff)); - RUN(testBitAndSExt16(0x10000, 0xfffff)); - RUN(testBitAndSExt16(0xffffff, 0xfffff)); - RUN(testBitAndSExt16(0x1000000, 0xfffff)); - - RUN(testSExt32BitAnd(0, 0)); - RUN(testSExt32BitAnd(1, 0)); - RUN(testSExt32BitAnd(42, 0)); - RUN(testSExt32BitAnd(-1, 0)); - RUN(testSExt32BitAnd(0x80000000, 0)); - RUN(testSExt32BitAnd(0, 0xf)); - RUN(testSExt32BitAnd(1, 0xf)); - RUN(testSExt32BitAnd(42, 0xf)); - RUN(testSExt32BitAnd(-1, 0xf)); - RUN(testSExt32BitAnd(0x80000000, 0xf)); - RUN(testSExt32BitAnd(0, 0x80000000)); - RUN(testSExt32BitAnd(1, 0x80000000)); - RUN(testSExt32BitAnd(42, 0x80000000)); - RUN(testSExt32BitAnd(-1, 0x80000000)); - RUN(testSExt32BitAnd(0x80000000, 0x80000000)); - RUN(testBitAndSExt32(0, 0xf)); - RUN(testBitAndSExt32(1, 0xf)); - RUN(testBitAndSExt32(42, 0xf)); - RUN(testBitAndSExt32(-1, 0xf)); - RUN(testBitAndSExt32(0xffff, 0xf)); - RUN(testBitAndSExt32(0x10000, 0xf)); - RUN(testBitAndSExt32(0xffffff, 0xf)); - RUN(testBitAndSExt32(0x1000000, 0xf)); - RUN(testBitAndSExt32(0, 0xffff00000000llu)); - RUN(testBitAndSExt32(1, 0xffff00000000llu)); - RUN(testBitAndSExt32(42, 0xffff00000000llu)); - RUN(testBitAndSExt32(-1, 0xffff00000000llu)); - RUN(testBitAndSExt32(0x80000000, 0xffff00000000llu)); - - RUN(testBasicSelect()); - RUN(testSelectTest()); - RUN(testSelectCompareDouble()); - RUN_BINARY(testSelectCompareFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testSelectCompareFloatToDouble, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN(testSelectDouble()); - RUN(testSelectDoubleTest()); - RUN(testSelectDoubleCompareDouble()); - RUN_BINARY(testSelectDoubleCompareFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN_BINARY(testSelectFloatCompareFloat, floatingPointOperands<float>(), floatingPointOperands<float>()); - RUN(testSelectDoubleCompareDoubleWithAliasing()); - RUN(testSelectFloatCompareFloatWithAliasing()); - RUN(testSelectFold(42)); - RUN(testSelectFold(43)); - RUN(testSelectInvert()); - RUN(testCheckSelect()); - RUN(testCheckSelectCheckSelect()); - RUN_BINARY(testPowDoubleByIntegerLoop, floatingPointOperands<double>(), int64Operands()); - - RUN(testTruncOrHigh()); - RUN(testTruncOrLow()); - RUN(testBitAndOrHigh()); - RUN(testBitAndOrLow()); - - RUN(testBranch64Equal(0, 0)); - RUN(testBranch64Equal(1, 1)); - RUN(testBranch64Equal(-1, -1)); - RUN(testBranch64Equal(1, -1)); - RUN(testBranch64Equal(-1, 1)); - RUN(testBranch64EqualImm(0, 0)); - RUN(testBranch64EqualImm(1, 1)); - RUN(testBranch64EqualImm(-1, -1)); - RUN(testBranch64EqualImm(1, -1)); - RUN(testBranch64EqualImm(-1, 1)); - RUN(testBranch64EqualMem(0, 0)); - RUN(testBranch64EqualMem(1, 1)); - RUN(testBranch64EqualMem(-1, -1)); - RUN(testBranch64EqualMem(1, -1)); - RUN(testBranch64EqualMem(-1, 1)); - RUN(testBranch64EqualMemImm(0, 0)); - RUN(testBranch64EqualMemImm(1, 1)); - RUN(testBranch64EqualMemImm(-1, -1)); - RUN(testBranch64EqualMemImm(1, -1)); - RUN(testBranch64EqualMemImm(-1, 1)); - - RUN(testStore8Load8Z(0)); - RUN(testStore8Load8Z(123)); - RUN(testStore8Load8Z(12345)); - RUN(testStore8Load8Z(-123)); - - RUN(testStore16Load16Z(0)); - RUN(testStore16Load16Z(123)); - RUN(testStore16Load16Z(12345)); - RUN(testStore16Load16Z(12345678)); - RUN(testStore16Load16Z(-123)); - - RUN(testSShrShl32(42, 24, 24)); - RUN(testSShrShl32(-42, 24, 24)); - RUN(testSShrShl32(4200, 24, 24)); - RUN(testSShrShl32(-4200, 24, 24)); - RUN(testSShrShl32(4200000, 24, 24)); - RUN(testSShrShl32(-4200000, 24, 24)); - - RUN(testSShrShl32(42, 16, 16)); - RUN(testSShrShl32(-42, 16, 16)); - RUN(testSShrShl32(4200, 16, 16)); - RUN(testSShrShl32(-4200, 16, 16)); - RUN(testSShrShl32(4200000, 16, 16)); - RUN(testSShrShl32(-4200000, 16, 16)); - - RUN(testSShrShl32(42, 8, 8)); - RUN(testSShrShl32(-42, 8, 8)); - RUN(testSShrShl32(4200, 8, 8)); - RUN(testSShrShl32(-4200, 8, 8)); - RUN(testSShrShl32(4200000, 8, 8)); - RUN(testSShrShl32(-4200000, 8, 8)); - RUN(testSShrShl32(420000000, 8, 8)); - RUN(testSShrShl32(-420000000, 8, 8)); - - RUN(testSShrShl64(42, 56, 56)); - RUN(testSShrShl64(-42, 56, 56)); - RUN(testSShrShl64(4200, 56, 56)); - RUN(testSShrShl64(-4200, 56, 56)); - RUN(testSShrShl64(4200000, 56, 56)); - RUN(testSShrShl64(-4200000, 56, 56)); - RUN(testSShrShl64(420000000, 56, 56)); - RUN(testSShrShl64(-420000000, 56, 56)); - RUN(testSShrShl64(42000000000, 56, 56)); - RUN(testSShrShl64(-42000000000, 56, 56)); - - RUN(testSShrShl64(42, 48, 48)); - RUN(testSShrShl64(-42, 48, 48)); - RUN(testSShrShl64(4200, 48, 48)); - RUN(testSShrShl64(-4200, 48, 48)); - RUN(testSShrShl64(4200000, 48, 48)); - RUN(testSShrShl64(-4200000, 48, 48)); - RUN(testSShrShl64(420000000, 48, 48)); - RUN(testSShrShl64(-420000000, 48, 48)); - RUN(testSShrShl64(42000000000, 48, 48)); - RUN(testSShrShl64(-42000000000, 48, 48)); - - RUN(testSShrShl64(42, 32, 32)); - RUN(testSShrShl64(-42, 32, 32)); - RUN(testSShrShl64(4200, 32, 32)); - RUN(testSShrShl64(-4200, 32, 32)); - RUN(testSShrShl64(4200000, 32, 32)); - RUN(testSShrShl64(-4200000, 32, 32)); - RUN(testSShrShl64(420000000, 32, 32)); - RUN(testSShrShl64(-420000000, 32, 32)); - RUN(testSShrShl64(42000000000, 32, 32)); - RUN(testSShrShl64(-42000000000, 32, 32)); - - RUN(testSShrShl64(42, 24, 24)); - RUN(testSShrShl64(-42, 24, 24)); - RUN(testSShrShl64(4200, 24, 24)); - RUN(testSShrShl64(-4200, 24, 24)); - RUN(testSShrShl64(4200000, 24, 24)); - RUN(testSShrShl64(-4200000, 24, 24)); - RUN(testSShrShl64(420000000, 24, 24)); - RUN(testSShrShl64(-420000000, 24, 24)); - RUN(testSShrShl64(42000000000, 24, 24)); - RUN(testSShrShl64(-42000000000, 24, 24)); - - RUN(testSShrShl64(42, 16, 16)); - RUN(testSShrShl64(-42, 16, 16)); - RUN(testSShrShl64(4200, 16, 16)); - RUN(testSShrShl64(-4200, 16, 16)); - RUN(testSShrShl64(4200000, 16, 16)); - RUN(testSShrShl64(-4200000, 16, 16)); - RUN(testSShrShl64(420000000, 16, 16)); - RUN(testSShrShl64(-420000000, 16, 16)); - RUN(testSShrShl64(42000000000, 16, 16)); - RUN(testSShrShl64(-42000000000, 16, 16)); - - RUN(testSShrShl64(42, 8, 8)); - RUN(testSShrShl64(-42, 8, 8)); - RUN(testSShrShl64(4200, 8, 8)); - RUN(testSShrShl64(-4200, 8, 8)); - RUN(testSShrShl64(4200000, 8, 8)); - RUN(testSShrShl64(-4200000, 8, 8)); - RUN(testSShrShl64(420000000, 8, 8)); - RUN(testSShrShl64(-420000000, 8, 8)); - RUN(testSShrShl64(42000000000, 8, 8)); - RUN(testSShrShl64(-42000000000, 8, 8)); - - RUN(testCheckMul64SShr()); - - RUN(testComputeDivisionMagic<int32_t>(2, -2147483647, 0)); - RUN(testTrivialInfiniteLoop()); - RUN(testFoldPathEqual()); - - RUN(testRShiftSelf32()); - RUN(testURShiftSelf32()); - RUN(testLShiftSelf32()); - RUN(testRShiftSelf64()); - RUN(testURShiftSelf64()); - RUN(testLShiftSelf64()); - - RUN(testPatchpointDoubleRegs()); - - if (tasks.isEmpty()) - usage(); - - Lock lock; - - Vector<ThreadIdentifier> threads; - for (unsigned i = filter ? 1 : WTF::numberOfProcessorCores(); i--;) { - threads.append( - createThread( - "testb3 thread", - [&] () { - for (;;) { - RefPtr<SharedTask<void()>> task; - { - LockHolder locker(lock); - if (tasks.isEmpty()) - return; - task = tasks.takeFirst(); - } - - task->run(); - } - })); - } - - for (ThreadIdentifier thread : threads) - waitForThreadCompletion(thread); - crashLock.lock(); -} - -} // anonymous namespace - -#else // ENABLE(B3_JIT) - -static void run(const char*) -{ - dataLog("B3 JIT is not enabled.\n"); -} - -#endif // ENABLE(B3_JIT) - -int main(int argc, char** argv) -{ - const char* filter = nullptr; - switch (argc) { - case 1: - break; - case 2: - filter = argv[1]; - break; - default: - usage(); - break; - } - - run(filter); - return 0; -} - |