| /* |
| * Copyright (C) 2015-2019 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 "testb3.h" |
| |
| #if ENABLE(B3_JIT) |
| |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, BitOr, Origin(), |
| root->appendNew<Const32Value>(proc, Origin(), a), |
| innerBitOr)); |
| |
| CHECK(compileAndRun<int>(proc, b) == (a | (b | c))); |
| } |
| |
| double bitOrDouble(double a, double b) |
| { |
| return bitwise_cast<double>(bitwise_cast<uint64_t>(a) | bitwise_cast<uint64_t>(b)); |
| } |
| |
| void testBitOrArgDouble(double a) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); |
| Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argument, argument); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc, a), bitOrDouble(a, a))); |
| } |
| |
| void testBitOrArgsDouble(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, BitOr, Origin(), argumentA, argumentB); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b))); |
| } |
| |
| void testBitOrArgImmDouble(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, BitOr, Origin(), argumentA, argumentB); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b))); |
| } |
| |
| void testBitOrImmsDouble(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, BitOr, Origin(), argumentA, argumentB); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc), bitOrDouble(a, b))); |
| } |
| |
| float bitOrFloat(float a, float b) |
| { |
| return bitwise_cast<float>(bitwise_cast<uint32_t>(a) | bitwise_cast<uint32_t>(b)); |
| } |
| |
| void testBitOrArgFloat(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, BitOr, Origin(), argument, argument); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitOrFloat(a, a))); |
| } |
| |
| void testBitOrArgsFloat(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, BitOr, Origin(), argumentA, argumentB); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b))); |
| } |
| |
| void testBitOrArgImmFloat(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, BitOr, Origin(), argumentA, argumentB); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b))); |
| } |
| |
| void testBitOrImmsFloat(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, BitOr, Origin(), argumentA, argumentB); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK(isIdentical(compileAndRun<float>(proc), bitOrFloat(a, b))); |
| } |
| |
| void testBitOrArgsFloatWithUselessDoubleConversion(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, BitOr, Origin(), argumentAasDouble, argumentBasDouble); |
| Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult); |
| root->appendNewControlValue(proc, Return, Origin(), floatResult); |
| |
| double doubleA = a; |
| double doubleB = b; |
| float expected = static_cast<float>(bitOrDouble(doubleA, doubleB)); |
| CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected)); |
| } |
| |
| void testBitXorArgs(int64_t a, int64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, BitXor, Origin(), |
| argument, |
| argument)); |
| |
| CHECK(!compileAndRun<int64_t>(proc, a)); |
| } |
| |
| void testBitXorAndAndArgs(int64_t a, int64_t b, int64_t c) |
| { |
| // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength): |
| // ((a & b) ^ (a & c)) |
| // ((a & b) ^ (c & a)) |
| // ((b & a) ^ (a & c)) |
| // ((b & a) ^ (c & a)) |
| for (int i = 0; i < 4; ++i) { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); |
| Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2); |
| Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB) |
| : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA); |
| Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC) |
| : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA); |
| root->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, BitXor, Origin(), |
| andAB, |
| andAC)); |
| |
| CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a & b) ^ (a & c))); |
| } |
| } |
| |
| void testBitXorAndAndArgs32(int32_t a, int32_t b, int32_t c) |
| { |
| // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength): |
| // ((a & b) ^ (a & c)) |
| // ((a & b) ^ (c & a)) |
| // ((b & a) ^ (a & c)) |
| // ((b & a) ^ (c & a)) |
| for (int i = 0; i < 4; ++i) { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); |
| Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); |
| Value* argC = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)); |
| Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB) |
| : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA); |
| Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC) |
| : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA); |
| root->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, BitXor, Origin(), |
| andAB, |
| andAC)); |
| |
| CHECK_EQ(compileAndRun<int32_t>(proc, a, b, c), ((a & b) ^ (a & c))); |
| } |
| } |
| |
| void testBitXorAndSameArgs(int64_t a, int64_t b) |
| { |
| // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength): |
| // ((a & b) ^ a) |
| // ((b & a) ^ a) |
| // (a ^ (a & b)) |
| // (a ^ (b & a)) |
| for (int i = 0; i < 4; ++i) { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1); |
| Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB) |
| : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA); |
| Value* result = i & 2 ? root->appendNew<Value>(proc, BitXor, Origin(), andAB, argA) |
| : root->appendNew<Value>(proc, BitXor, Origin(), argA, andAB); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK_EQ(compileAndRun<int64_t>(proc, a, b), ((a & b) ^ a)); |
| } |
| } |
| |
| void testBitXorAndSameArgs32(int32_t a, int32_t b) |
| { |
| // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength): |
| // ((a & b) ^ a) |
| // ((b & a) ^ a) |
| // (a ^ (a & b)) |
| // (a ^ (b & a)) |
| for (int i = 0; i < 4; ++i) { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); |
| Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); |
| Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB) |
| : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA); |
| Value* result = i & 2 ? root->appendNew<Value>(proc, BitXor, Origin(), andAB, argA) |
| : root->appendNew<Value>(proc, BitXor, Origin(), argA, andAB); |
| root->appendNewControlValue(proc, Return, Origin(), result); |
| |
| CHECK_EQ(compileAndRun<int32_t>(proc, a, b), ((a & b) ^ a)); |
| } |
| } |
| |
| void testBitXorImms(int64_t a, int64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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 testNotOnBooleanAndBranch32(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->appendNewControlValue( |
| proc, Branch, Origin(), |
| argsAreNotEqual, |
| FrequentedBlock(thenCase), FrequentedBlock(elseCase)); |
| |
| thenCase->appendNewControlValue( |
| proc, Return, Origin(), |
| thenCase->appendNew<Const32Value>(proc, Origin(), 42)); |
| |
| elseCase->appendNewControlValue( |
| 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 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* bitNotArgsAreEqual = root->appendNew<Value>(proc, BitXor, Origin(), |
| root->appendNew<Const32Value>(proc, Origin(), -1), |
| argsAreEqual); |
| |
| root->appendNewControlValue(proc, Branch, Origin(), |
| bitNotArgsAreEqual, FrequentedBlock(thenCase), FrequentedBlock(elseCase)); |
| |
| thenCase->appendNewControlValue(proc, Return, Origin(), |
| thenCase->appendNew<Const32Value>(proc, Origin(), 42)); |
| |
| elseCase->appendNewControlValue(proc, Return, Origin(), |
| elseCase->appendNew<Const32Value>(proc, Origin(), -42)); |
| |
| static constexpr int32_t expectedValue = 42; |
| CHECK(compileAndRun<int32_t>(proc, a, b) == expectedValue); |
| } |
| |
| void testShlArgs(int64_t a, int64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, Shl, Origin(), |
| root->appendNew<Const64Value>(proc, Origin(), a), |
| root->appendNew<Const32Value>(proc, Origin(), b))); |
| |
| b = b & 0x3f; // to avoid undefined behaviour below |
| CHECK(compileAndRun<int64_t>(proc) == (a << b)); |
| } |
| |
| void testShlArgImm(int64_t a, int64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, Shl, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), |
| root->appendNew<Const32Value>(proc, Origin(), b))); |
| |
| b = b & 0x3f; // to avoid undefined behaviour below |
| CHECK(compileAndRun<int64_t>(proc, a) == (a << b)); |
| } |
| |
| void testShlSShrArgImm(int64_t a, int64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* constB = root->appendNew<Const32Value>(proc, Origin(), b); |
| Value* innerShift = root->appendNew<Value>(proc, SShr, Origin(), argA, constB); |
| root->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, Shl, Origin(), |
| innerShift, |
| constB)); |
| |
| b = b & 0x3f; // to avoid undefined behaviour below |
| CHECK(compileAndRun<int64_t>(proc, a) == ((a >> b) << 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, Shl, Origin(), |
| root->appendNew<Const32Value>(proc, Origin(), a), |
| root->appendNew<Const32Value>(proc, Origin(), b))); |
| |
| b = b & 0x1f; // to avoid undefined behaviour below |
| CHECK(compileAndRun<int32_t>(proc) == (a << b)); |
| } |
| |
| void testShlArgImm32(int32_t a, int32_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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))); |
| |
| b = b & 0x1f; // to avoid undefined behaviour below |
| CHECK(compileAndRun<int32_t>(proc, a) == (a << b)); |
| } |
| |
| void testShlZShrArgImm32(int32_t a, int32_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argA = root->appendNew<Value>( |
| proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); |
| Value* constB = root->appendNew<Const32Value>(proc, Origin(), b); |
| Value* innerShift = root->appendNew<Value>(proc, ZShr, Origin(), argA, constB); |
| root->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, Shl, Origin(), |
| innerShift, |
| constB)); |
| |
| b = b & 0x1f; // to avoid undefined behaviour below |
| CHECK(compileAndRun<int32_t>(proc, a) == static_cast<int32_t>((static_cast<uint32_t>(a) >> b) << b)); |
| } |
| |
| static void testSShrArgs(int64_t a, int64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testSShrImms(int64_t a, int64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testSShrArgImm(int64_t a, int64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static 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->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>(proc, SShr, Origin(), value, value)); |
| |
| CHECK(compileAndRun<int32_t>(proc, a) == (a >> (a & 31))); |
| } |
| |
| static void testSShrArgs32(int32_t a, int32_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testSShrImms32(int32_t a, int32_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testSShrArgImm32(int32_t a, int32_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testZShrArgs(uint64_t a, uint64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testZShrImms(uint64_t a, uint64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testZShrArgImm(uint64_t a, uint64_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static 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->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>(proc, ZShr, Origin(), value, value)); |
| |
| CHECK(compileAndRun<uint32_t>(proc, a) == (a >> (a & 31))); |
| } |
| |
| static void testZShrArgs32(uint32_t a, uint32_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testZShrImms32(uint32_t a, uint32_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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)); |
| } |
| |
| static void testZShrArgImm32(uint32_t a, uint32_t b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(proc, Return, Origin(), clzValue); |
| CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a)); |
| } |
| |
| void testAbsArg(double a) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(proc, Return, Origin(), secondAbs); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(fabs(a)))); |
| } |
| |
| void testAbsNegArg(double a) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* neg = root->appendNew<Value>(proc, Neg, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)); |
| Value* abs = root->appendNew<Value>(proc, Abs, Origin(), neg); |
| root->appendNewControlValue(proc, Return, Origin(), abs); |
| |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(proc, Return, Origin(), secondAbs); |
| |
| CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(fabs(a))))); |
| } |
| |
| void testAbsNegArg(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* neg = root->appendNew<Value>(proc, Neg, Origin(), argument); |
| Value* abs = root->appendNew<Value>(proc, Abs, Origin(), neg); |
| root->appendNewControlValue(proc, Return, Origin(), abs); |
| |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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, static_cast<double>(fabs(a)))); |
| } |
| |
| void testCeilArg(double a) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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, static_cast<double>(ceilf(a)))); |
| } |
| |
| void testFloorArg(double a) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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, static_cast<double>(floorf(a)))); |
| } |
| |
| double correctSqrt(double value) |
| { |
| #if CPU(X86) || CPU(X86_64) |
| double result; |
| asm ("sqrtsd %1, %0" : "=x"(result) : "x"(value)); |
| return result; |
| #else |
| return sqrt(value); |
| #endif |
| } |
| |
| void testSqrtArg(double a) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| root->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>( |
| proc, Sqrt, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0))); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc, a), correctSqrt(a))); |
| } |
| |
| void testSqrtImm(double a) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a); |
| root->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>(proc, Sqrt, Origin(), argument)); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc), correctSqrt(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->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Value>(proc, Sqrt, Origin(), loadDouble)); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc, &a), correctSqrt(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->appendNewControlValue(proc, Return, Origin(), result32); |
| |
| CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(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->appendNewControlValue(proc, Return, Origin(), result32); |
| |
| CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(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->appendNewControlValue(proc, Return, Origin(), result32); |
| |
| CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(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->appendNewControlValue(proc, Return, Origin(), result32); |
| |
| CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(correctSqrt(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->appendNewControlValue(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>(correctSqrt(a))))); |
| double expected = static_cast<double>(correctSqrt(a)); |
| CHECK(isIdentical(effect, expected)); |
| } |
| |
| void testCompareTwoFloatToDouble(float a, float b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| |
| Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); |
| Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32); |
| Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float); |
| |
| Value* arg2As32 = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); |
| Value* arg2Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg2As32); |
| Value* arg2AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg2Float); |
| Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg1AsDouble, arg2AsDouble); |
| |
| root->appendNewControlValue(proc, Return, Origin(), equal); |
| |
| CHECK(compileAndRun<int64_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)) == (a == b)); |
| } |
| |
| void testCompareOneFloatToDouble(float a, double b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| |
| Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); |
| Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32); |
| Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float); |
| |
| Value* arg2AsDouble = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); |
| Value* equal = root->appendNew<Value>(proc, Equal, Origin(), arg1AsDouble, arg2AsDouble); |
| |
| root->appendNewControlValue(proc, Return, Origin(), equal); |
| |
| CHECK(compileAndRun<int64_t>(proc, bitwise_cast<int32_t>(a), b) == (a == b)); |
| } |
| |
| void testCompareFloatToDoubleThroughPhi(float a, float b) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| BasicBlock* thenCase = proc.addBlock(); |
| BasicBlock* elseCase = proc.addBlock(); |
| BasicBlock* tail = proc.addBlock(); |
| |
| Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| |
| Value* arg1As32 = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); |
| Value* arg1Float = root->appendNew<Value>(proc, BitwiseCast, Origin(), arg1As32); |
| Value* arg1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg1Float); |
| |
| Value* arg2AsDouble = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); |
| Value* arg2AsFloat = root->appendNew<Value>(proc, DoubleToFloat, Origin(), arg2AsDouble); |
| Value* arg2AsFRoundedDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), arg2AsFloat); |
| |
| root->appendNewControlValue( |
| proc, Branch, Origin(), |
| condition, |
| FrequentedBlock(thenCase), FrequentedBlock(elseCase)); |
| |
| UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), arg1AsDouble); |
| thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* elseConst = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 0.); |
| UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), elseConst); |
| elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin()); |
| thenValue->setPhi(doubleInput); |
| elseValue->setPhi(doubleInput); |
| Value* equal = tail->appendNew<Value>(proc, Equal, Origin(), doubleInput, arg2AsFRoundedDouble); |
| tail->appendNewControlValue(proc, Return, Origin(), equal); |
| |
| auto code = compileProc(proc); |
| int32_t integerA = bitwise_cast<int32_t>(a); |
| double doubleB = b; |
| CHECK(invoke<int64_t>(*code, 1, integerA, doubleB) == (a == b)); |
| CHECK(invoke<int64_t>(*code, 0, integerA, doubleB) == (b == 0)); |
| } |
| |
| void testDoubleToFloatThroughPhi(float value) |
| { |
| // Simple case of: |
| // if (a) { |
| // x = DoubleAdd(a, b) |
| // else |
| // x = DoubleAdd(a, c) |
| // DoubleToFloat(x) |
| // |
| // Both Adds can be converted to float add. |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| BasicBlock* thenCase = proc.addBlock(); |
| BasicBlock* elseCase = proc.addBlock(); |
| BasicBlock* tail = proc.addBlock(); |
| |
| Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); |
| Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); |
| Value* argAsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); |
| |
| root->appendNewControlValue( |
| proc, Branch, Origin(), |
| condition, |
| FrequentedBlock(thenCase), FrequentedBlock(elseCase)); |
| |
| Value* postitiveConst = thenCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5f); |
| Value* thenAdd = thenCase->appendNew<Value>(proc, Add, Origin(), argAsDouble, postitiveConst); |
| UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), thenAdd); |
| thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* elseConst = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), M_PI); |
| UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), elseConst); |
| elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin()); |
| thenValue->setPhi(doubleInput); |
| elseValue->setPhi(doubleInput); |
| Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleInput); |
| tail->appendNewControlValue(proc, Return, Origin(), floatResult); |
| |
| auto code = compileProc(proc); |
| CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + 42.5f)); |
| CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<float>(M_PI))); |
| } |
| |
| void testReduceFloatToDoubleValidates() |
| { |
| // Simple case of: |
| // f = DoubleToFloat(Bitcast(argGPR0)) |
| // if (a) { |
| // x = FloatConst() |
| // else |
| // x = FloatConst() |
| // p = Phi(x) |
| // a = Mul(p, p) |
| // b = Add(a, f) |
| // c = Add(p, b) |
| // Return(c) |
| // |
| // This should not crash in the validator after ReduceFloatToDouble. |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| BasicBlock* thenCase = proc.addBlock(); |
| BasicBlock* elseCase = proc.addBlock(); |
| BasicBlock* tail = proc.addBlock(); |
| |
| Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* thingy = root->appendNew<Value>(proc, BitwiseCast, Origin(), condition); |
| thingy = root->appendNew<Value>(proc, DoubleToFloat, Origin(), thingy); // Make the phase think it has work to do. |
| root->appendNewControlValue( |
| proc, Branch, Origin(), |
| condition, |
| FrequentedBlock(thenCase), FrequentedBlock(elseCase)); |
| |
| UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), |
| thenCase->appendNew<ConstFloatValue>(proc, Origin(), 11.5)); |
| thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), |
| elseCase->appendNew<ConstFloatValue>(proc, Origin(), 10.5)); |
| elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* phi = tail->appendNew<Value>(proc, Phi, Float, Origin()); |
| thenValue->setPhi(phi); |
| elseValue->setPhi(phi); |
| Value* result = tail->appendNew<Value>(proc, Mul, Origin(), |
| phi, phi); |
| result = tail->appendNew<Value>(proc, Add, Origin(), |
| result, |
| thingy); |
| result = tail->appendNew<Value>(proc, Add, Origin(), |
| phi, |
| result); |
| tail->appendNewControlValue(proc, Return, Origin(), result); |
| |
| auto code = compileProc(proc); |
| CHECK(isIdentical(invoke<float>(*code, 1), 11.5f * 11.5f + static_cast<float>(bitwise_cast<double>(static_cast<uint64_t>(1))) + 11.5f)); |
| CHECK(isIdentical(invoke<float>(*code, 0), 10.5f * 10.5f + static_cast<float>(bitwise_cast<double>(static_cast<uint64_t>(0))) + 10.5f)); |
| } |
| |
| void testDoubleProducerPhiToFloatConversion(float value) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| BasicBlock* thenCase = proc.addBlock(); |
| BasicBlock* elseCase = proc.addBlock(); |
| BasicBlock* tail = proc.addBlock(); |
| |
| Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); |
| Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); |
| |
| root->appendNewControlValue( |
| proc, Branch, Origin(), |
| condition, |
| FrequentedBlock(thenCase), FrequentedBlock(elseCase)); |
| |
| Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); |
| UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble); |
| thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5); |
| UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble); |
| elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin()); |
| thenValue->setPhi(doubleInput); |
| elseValue->setPhi(doubleInput); |
| |
| Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); |
| Value* finalAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain); |
| Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), finalAdd); |
| tail->appendNewControlValue(proc, Return, Origin(), floatResult); |
| |
| auto code = compileProc(proc); |
| CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + value)); |
| CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), 42.5f + value)); |
| } |
| |
| void testDoubleProducerPhiToFloatConversionWithDoubleConsumer(float value) |
| { |
| // In this case, the Upsilon-Phi effectively contains a Float value, but it is used |
| // as a Float and as a Double. |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| BasicBlock* thenCase = proc.addBlock(); |
| BasicBlock* elseCase = proc.addBlock(); |
| BasicBlock* tail = proc.addBlock(); |
| |
| Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); |
| Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); |
| |
| root->appendNewControlValue( |
| proc, Branch, Origin(), |
| condition, |
| FrequentedBlock(thenCase), FrequentedBlock(elseCase)); |
| |
| Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); |
| UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble); |
| thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), 42.5); |
| UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble); |
| elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin()); |
| thenValue->setPhi(doubleInput); |
| elseValue->setPhi(doubleInput); |
| |
| Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); |
| Value* floatAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain); |
| |
| // FRound. |
| Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), floatAdd); |
| Value* doubleResult = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatResult); |
| |
| // This one *cannot* be eliminated |
| Value* doubleAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, doubleResult); |
| |
| tail->appendNewControlValue(proc, Return, Origin(), doubleAdd); |
| |
| auto code = compileProc(proc); |
| CHECK(isIdentical(invoke<double>(*code, 1, bitwise_cast<int32_t>(value)), (value + value) + static_cast<double>(value))); |
| CHECK(isIdentical(invoke<double>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<double>((42.5f + value) + 42.5f))); |
| } |
| |
| void testDoubleProducerPhiWithNonFloatConst(float value, double constValue) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| BasicBlock* thenCase = proc.addBlock(); |
| BasicBlock* elseCase = proc.addBlock(); |
| BasicBlock* tail = proc.addBlock(); |
| |
| Value* condition = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); |
| Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32); |
| |
| root->appendNewControlValue( |
| proc, Branch, Origin(), |
| condition, |
| FrequentedBlock(thenCase), FrequentedBlock(elseCase)); |
| |
| Value* asDouble = thenCase->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); |
| UpsilonValue* thenValue = thenCase->appendNew<UpsilonValue>(proc, Origin(), asDouble); |
| thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* constDouble = elseCase->appendNew<ConstDoubleValue>(proc, Origin(), constValue); |
| UpsilonValue* elseValue = elseCase->appendNew<UpsilonValue>(proc, Origin(), constDouble); |
| elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); |
| |
| Value* doubleInput = tail->appendNew<Value>(proc, Phi, Double, Origin()); |
| thenValue->setPhi(doubleInput); |
| elseValue->setPhi(doubleInput); |
| |
| Value* argAsDoubleAgain = tail->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue); |
| Value* finalAdd = tail->appendNew<Value>(proc, Add, Origin(), doubleInput, argAsDoubleAgain); |
| Value* floatResult = tail->appendNew<Value>(proc, DoubleToFloat, Origin(), finalAdd); |
| tail->appendNewControlValue(proc, Return, Origin(), floatResult); |
| |
| auto code = compileProc(proc); |
| CHECK(isIdentical(invoke<float>(*code, 1, bitwise_cast<int32_t>(value)), value + value)); |
| CHECK(isIdentical(invoke<float>(*code, 0, bitwise_cast<int32_t>(value)), static_cast<float>(constValue + value))); |
| } |
| |
| void testDoubleArgToInt64BitwiseCast(double value) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0); |
| |
| root->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(proc, Return, Origin(), asDouble); |
| |
| CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(static_cast<float>(value)))); |
| } |
| |
| void testIToD64Arg() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsDouble); |
| |
| auto code = compileProc(proc); |
| for (auto testValue : int64Operands()) |
| CHECK(isIdentical(invoke<double>(*code, testValue.value), static_cast<double>(testValue.value))); |
| } |
| |
| void testIToF64Arg() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), src); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsFloat); |
| |
| auto code = compileProc(proc); |
| for (auto testValue : int64Operands()) |
| CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value))); |
| } |
| |
| void testIToD32Arg() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); |
| Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsDouble); |
| |
| auto code = compileProc(proc); |
| for (auto testValue : int32Operands()) |
| CHECK(isIdentical(invoke<double>(*code, testValue.value), static_cast<double>(testValue.value))); |
| } |
| |
| void testIToF32Arg() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); |
| Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), src); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsFloat); |
| |
| auto code = compileProc(proc); |
| for (auto testValue : int32Operands()) |
| CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value))); |
| } |
| |
| void testIToD64Mem() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); |
| Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), loadedSrc); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsDouble); |
| |
| auto code = compileProc(proc); |
| int64_t inMemoryValue; |
| for (auto testValue : int64Operands()) { |
| inMemoryValue = testValue.value; |
| CHECK(isIdentical(invoke<double>(*code, &inMemoryValue), static_cast<double>(testValue.value))); |
| CHECK(inMemoryValue == testValue.value); |
| } |
| } |
| |
| void testIToF64Mem() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address); |
| Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), loadedSrc); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsFloat); |
| |
| auto code = compileProc(proc); |
| int64_t inMemoryValue; |
| for (auto testValue : int64Operands()) { |
| inMemoryValue = testValue.value; |
| CHECK(isIdentical(invoke<float>(*code, &inMemoryValue), static_cast<float>(testValue.value))); |
| CHECK(inMemoryValue == testValue.value); |
| } |
| } |
| |
| void testIToD32Mem() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); |
| Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), loadedSrc); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsDouble); |
| |
| auto code = compileProc(proc); |
| int32_t inMemoryValue; |
| for (auto testValue : int32Operands()) { |
| inMemoryValue = testValue.value; |
| CHECK(isIdentical(invoke<double>(*code, &inMemoryValue), static_cast<double>(testValue.value))); |
| CHECK(inMemoryValue == testValue.value); |
| } |
| } |
| |
| void testIToF32Mem() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address); |
| Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), loadedSrc); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsFloat); |
| |
| auto code = compileProc(proc); |
| int32_t inMemoryValue; |
| for (auto testValue : int32Operands()) { |
| inMemoryValue = testValue.value; |
| CHECK(isIdentical(invoke<float>(*code, &inMemoryValue), static_cast<float>(testValue.value))); |
| CHECK(inMemoryValue == testValue.value); |
| } |
| } |
| |
| void testIToD64Imm(int64_t value) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<Const64Value>(proc, Origin(), value); |
| Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToD, Origin(), src); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint); |
| CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value))); |
| } |
| |
| void testIToF64Imm(int64_t value) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<Const64Value>(proc, Origin(), value); |
| Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToF, Origin(), src); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint); |
| CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value))); |
| } |
| |
| void testIToD32Imm(int32_t value) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<Const32Value>(proc, Origin(), value); |
| Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToD, Origin(), src); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint); |
| CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value))); |
| } |
| |
| void testIToF32Imm(int32_t value) |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<Const32Value>(proc, Origin(), value); |
| Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToF, Origin(), src); |
| root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint); |
| CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value))); |
| } |
| |
| void testIToDReducedToIToF64Arg() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); |
| Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src); |
| Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), srcAsDouble); |
| root->appendNewControlValue(proc, Return, Origin(), floatResult); |
| |
| auto code = compileProc(proc); |
| for (auto testValue : int64Operands()) |
| CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value))); |
| } |
| |
| void testIToDReducedToIToF32Arg() |
| { |
| Procedure proc; |
| BasicBlock* root = proc.addBlock(); |
| Value* src = root->appendNew<Value>(proc, Trunc, Origin(), |
| root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); |
| Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src); |
| Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), srcAsDouble); |
| root->appendNewControlValue(proc, Return, Origin(), floatResult); |
| |
| auto code = compileProc(proc); |
| for (auto testValue : int32Operands()) |
| CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.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), 0); |
| root->appendNewControlValue( |
| 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), 0); |
| root->appendNewControlValue( |
| 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 CPU(ADDRESS64) |
| slot = (static_cast<intptr_t>(0xbaadbeef) << 32) + static_cast<intptr_t>(0xbaadbeef); |
| #else |
| slot = 0xbaadbeef; |
| #endif |
| root->appendNew<MemoryValue>( |
| proc, Store, Origin(), |
| root->appendNew<ConstPtrValue>(proc, Origin(), value), |
| root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0); |
| root->appendNewControlValue( |
| 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->resultConstraints = { 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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue(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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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->appendNewControlValue( |
| 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, 0); |
| root->appendNewControlValue( |
| proc, Return, Origin(), |
| root->appendNew<Const32Value>(proc, Origin(), 0)); |
| |
| CHECK(!compileAndRun<int>(proc, amount)); |
| CHECK(slot == 37 + amount); |
| } |
| |
| // Make sure the compiler does not try to optimize anything out. |
| static NEVER_INLINE double zero() |
| { |
| return 0.; |
| } |
| |
| static double negativeZero() |
| { |
| return -zero(); |
| } |
| |
| void addArgTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks) |
| { |
| 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_BINARY(testAddNeg1, int32Operands(), int32Operands()); |
| RUN_BINARY(testAddNeg2, int32Operands(), int32Operands()); |
| RUN(testAddArgZeroImmZDef()); |
| RUN(testAddLoadTwice()); |
| RUN_TERNARY(testAddMulMulArgs, int64Operands(), int64Operands(), int64Operands()); |
| |
| 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(testAddFPRArgsFloat, 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_BINARY(testMulImm32SignExtend, int32Operands(), int32Operands()); |
| RUN(testMulImm32SignExtend(0xFFFFFFFE, 0xFFFFFFFF)); |
| RUN(testMulImm32SignExtend(0xFFFFFFFF, 0xFFFFFFFE)); |
| RUN(testMulArgs32(1, 1)); |
| RUN(testMulArgs32(1, 2)); |
| RUN(testMulArgs32(0xFFFFFFFF, 0xFFFFFFFF)); |
| RUN(testMulArgs32(0xFFFFFFFE, 0xFFFFFFFF)); |
| RUN(testMulArgs32SignExtend(1, 1)); |
| RUN(testMulArgs32SignExtend(1, 2)); |
| RUN(testMulArgs32SignExtend(0xFFFFFFFF, 0xFFFFFFFF)); |
| RUN(testMulArgs32SignExtend(0xFFFFFFFE, 0xFFFFFFFF)); |
| RUN(testMulLoadTwice()); |
| RUN(testMulAddArgsLeft()); |
| RUN(testMulAddArgsRight()); |
| RUN(testMulAddArgsLeft32()); |
| RUN(testMulAddArgsRight32()); |
| RUN(testMulSubArgsLeft()); |
| RUN(testMulSubArgsRight()); |
| RUN(testMulSubArgsLeft32()); |
| RUN(testMulSubArgsRight32()); |
| RUN(testMulNegArgs()); |
| RUN(testMulNegArgs32()); |
| |
| RUN_BINARY(testMulArgNegArg, int64Operands(), int64Operands()) |
| RUN_BINARY(testMulNegArgArg, int64Operands(), int64Operands()) |
| 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_BINARY(testUDivArgsInt32, int32Operands(), int32Operands()); |
| RUN_BINARY(testUDivArgsInt64, int64Operands(), int64Operands()); |
| |
| 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_BINARY(testUModArgsInt32, int32Operands(), int32Operands()); |
| RUN_BINARY(testUModArgsInt64, int64Operands(), int64Operands()); |
| |
| 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_BINARY(testSubNeg, int32Operands(), int32Operands()); |
| RUN_BINARY(testNegSub, int32Operands(), int32Operands()); |
| RUN_UNARY(testNegValueSubOne, int32Operands()); |
| RUN_BINARY(testNegMulArgImm, int64Operands(), int64Operands()); |
| RUN_TERNARY(testSubMulMulArgs, int64Operands(), int64Operands(), int64Operands()); |
| |
| RUN_TERNARY(testSubSub, int32Operands(), int32Operands(), int32Operands()); |
| RUN_TERNARY(testSubSub2, int32Operands(), int32Operands(), int32Operands()); |
| RUN_TERNARY(testSubAdd, int32Operands(), int32Operands(), int32Operands()); |
| RUN_BINARY(testSubFirstNeg, int32Operands(), 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>()); |
| } |
| |
| void addCallTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks) |
| { |
| RUN(testCallSimple(1, 2)); |
| RUN(testCallRare(1, 2)); |
| RUN(testCallRareLive(1, 2, 3)); |
| RUN(testCallSimplePure(1, 2)); |
| RUN(testCallFunctionWithHellaArguments()); |
| RUN(testCallFunctionWithHellaArguments2()); |
| RUN(testCallFunctionWithHellaArguments3()); |
| |
| 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()); |
| } |
| |
| void addShrTests(const char* filter, Deque<RefPtr<SharedTask<void()>>>& tasks) |
| { |
| 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)); |
| } |
| |
| #endif // ENABLE(B3_JIT) |