2015-10-27 00:37:27 +00:00
|
|
|
// Copyright 2014 the V8 project authors. All rights reserved. Use of this
|
|
|
|
// source code is governed by a BSD-style license that can be found in the
|
|
|
|
// LICENSE file.
|
2014-07-30 13:54:45 +00:00
|
|
|
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
#include <cmath>
|
2014-07-31 07:44:29 +00:00
|
|
|
#include <functional>
|
2014-07-30 13:54:45 +00:00
|
|
|
#include <limits>
|
|
|
|
|
2014-08-14 09:07:58 +00:00
|
|
|
#include "src/base/bits.h"
|
2016-06-10 05:51:58 +00:00
|
|
|
#include "src/base/ieee754.h"
|
2015-04-21 10:21:50 +00:00
|
|
|
#include "src/base/utils/random-number-generator.h"
|
2017-10-20 09:12:46 +00:00
|
|
|
#include "src/boxed-float.h"
|
2014-10-30 09:00:58 +00:00
|
|
|
#include "src/codegen.h"
|
2017-02-23 11:46:29 +00:00
|
|
|
#include "src/objects-inl.h"
|
2016-08-22 13:50:23 +00:00
|
|
|
#include "src/utils.h"
|
2014-07-30 13:54:45 +00:00
|
|
|
#include "test/cctest/cctest.h"
|
|
|
|
#include "test/cctest/compiler/codegen-tester.h"
|
2015-10-27 00:37:27 +00:00
|
|
|
#include "test/cctest/compiler/graph-builder-tester.h"
|
2014-07-30 13:54:45 +00:00
|
|
|
#include "test/cctest/compiler/value-helper.h"
|
|
|
|
|
2015-10-30 09:16:26 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace compiler {
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-10-26 18:11:23 +00:00
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunInt32Add) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Node* add = m.Int32Add(m.Int32Constant(0), m.Int32Constant(1));
|
|
|
|
m.Return(add);
|
|
|
|
CHECK_EQ(1, m.Call());
|
|
|
|
}
|
|
|
|
|
2016-04-08 09:56:14 +00:00
|
|
|
static int RunInt32AddShift(bool is_left, int32_t add_left, int32_t add_right,
|
|
|
|
int32_t shift_left, int32_t shit_right) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Node* shift =
|
|
|
|
m.Word32Shl(m.Int32Constant(shift_left), m.Int32Constant(shit_right));
|
|
|
|
Node* add = m.Int32Add(m.Int32Constant(add_left), m.Int32Constant(add_right));
|
|
|
|
Node* lsa = is_left ? m.Int32Add(shift, add) : m.Int32Add(add, shift);
|
|
|
|
m.Return(lsa);
|
|
|
|
return m.Call();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt32AddShift) {
|
|
|
|
struct Test_case {
|
|
|
|
int32_t add_left, add_right, shift_left, shit_right, expected;
|
|
|
|
};
|
|
|
|
|
|
|
|
Test_case tc[] = {
|
|
|
|
{20, 22, 4, 2, 58},
|
|
|
|
{20, 22, 4, 1, 50},
|
|
|
|
{20, 22, 1, 6, 106},
|
|
|
|
{INT_MAX - 2, 1, 1, 1, INT_MIN}, // INT_MAX - 2 + 1 + (1 << 1), overflow.
|
|
|
|
};
|
|
|
|
const size_t tc_size = sizeof(tc) / sizeof(Test_case);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < tc_size; ++i) {
|
|
|
|
CHECK_EQ(tc[i].expected,
|
|
|
|
RunInt32AddShift(false, tc[i].add_left, tc[i].add_right,
|
|
|
|
tc[i].shift_left, tc[i].shit_right));
|
|
|
|
CHECK_EQ(tc[i].expected,
|
|
|
|
RunInt32AddShift(true, tc[i].add_left, tc[i].add_right,
|
|
|
|
tc[i].shift_left, tc[i].shit_right));
|
|
|
|
}
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2016-02-16 11:14:01 +00:00
|
|
|
TEST(RunWord32ReverseBits) {
|
|
|
|
BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
|
|
|
if (!m.machine()->Word32ReverseBits().IsSupported()) {
|
|
|
|
// We can only test the operator if it exists on the testing platform.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m.Return(m.AddNode(m.machine()->Word32ReverseBits().op(), m.Parameter(0)));
|
|
|
|
|
|
|
|
CHECK_EQ(uint32_t(0x00000000), m.Call(uint32_t(0x00000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(uint32_t(0x12345678), m.Call(uint32_t(0x1E6A2C48)));
|
|
|
|
CHECK_EQ(uint32_t(0xFEDCBA09), m.Call(uint32_t(0x905D3B7F)));
|
2016-02-16 11:14:01 +00:00
|
|
|
CHECK_EQ(uint32_t(0x01010101), m.Call(uint32_t(0x80808080)));
|
|
|
|
CHECK_EQ(uint32_t(0x01020408), m.Call(uint32_t(0x10204080)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(uint32_t(0xF0703010), m.Call(uint32_t(0x080C0E0F)));
|
|
|
|
CHECK_EQ(uint32_t(0x1F8D0A3A), m.Call(uint32_t(0x5C50B1F8)));
|
|
|
|
CHECK_EQ(uint32_t(0xFFFFFFFF), m.Call(uint32_t(0xFFFFFFFF)));
|
2016-02-16 11:14:01 +00:00
|
|
|
}
|
|
|
|
|
2016-07-29 19:31:54 +00:00
|
|
|
TEST(RunWord32ReverseBytes) {
|
|
|
|
BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2018-08-14 08:39:05 +00:00
|
|
|
m.Return(m.AddNode(m.machine()->Word32ReverseBytes(), m.Parameter(0)));
|
2016-07-29 19:31:54 +00:00
|
|
|
|
|
|
|
CHECK_EQ(uint32_t(0x00000000), m.Call(uint32_t(0x00000000)));
|
|
|
|
CHECK_EQ(uint32_t(0x12345678), m.Call(uint32_t(0x78563412)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(uint32_t(0xFEDCBA09), m.Call(uint32_t(0x09BADCFE)));
|
2016-07-29 19:31:54 +00:00
|
|
|
CHECK_EQ(uint32_t(0x01010101), m.Call(uint32_t(0x01010101)));
|
|
|
|
CHECK_EQ(uint32_t(0x01020408), m.Call(uint32_t(0x08040201)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(uint32_t(0xF0703010), m.Call(uint32_t(0x103070F0)));
|
|
|
|
CHECK_EQ(uint32_t(0x1F8D0A3A), m.Call(uint32_t(0x3A0A8D1F)));
|
|
|
|
CHECK_EQ(uint32_t(0xFFFFFFFF), m.Call(uint32_t(0xFFFFFFFF)));
|
2016-07-29 19:31:54 +00:00
|
|
|
}
|
2016-02-16 11:14:01 +00:00
|
|
|
|
2015-11-09 17:41:35 +00:00
|
|
|
TEST(RunWord32Ctz) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
|
2015-11-09 17:41:35 +00:00
|
|
|
if (!m.machine()->Word32Ctz().IsSupported()) {
|
|
|
|
// We can only test the operator if it exists on the testing platform.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m.Return(m.AddNode(m.machine()->Word32Ctz().op(), m.Parameter(0)));
|
|
|
|
|
|
|
|
CHECK_EQ(32, m.Call(uint32_t(0x00000000)));
|
|
|
|
CHECK_EQ(31, m.Call(uint32_t(0x80000000)));
|
|
|
|
CHECK_EQ(30, m.Call(uint32_t(0x40000000)));
|
|
|
|
CHECK_EQ(29, m.Call(uint32_t(0x20000000)));
|
|
|
|
CHECK_EQ(28, m.Call(uint32_t(0x10000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(27, m.Call(uint32_t(0xA8000000)));
|
|
|
|
CHECK_EQ(26, m.Call(uint32_t(0xF4000000)));
|
2015-11-09 17:41:35 +00:00
|
|
|
CHECK_EQ(25, m.Call(uint32_t(0x62000000)));
|
|
|
|
CHECK_EQ(24, m.Call(uint32_t(0x91000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(23, m.Call(uint32_t(0xCD800000)));
|
2015-11-09 17:41:35 +00:00
|
|
|
CHECK_EQ(22, m.Call(uint32_t(0x09400000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(21, m.Call(uint32_t(0xAF200000)));
|
|
|
|
CHECK_EQ(20, m.Call(uint32_t(0xAC100000)));
|
|
|
|
CHECK_EQ(19, m.Call(uint32_t(0xE0B80000)));
|
|
|
|
CHECK_EQ(18, m.Call(uint32_t(0x9CE40000)));
|
|
|
|
CHECK_EQ(17, m.Call(uint32_t(0xC7920000)));
|
|
|
|
CHECK_EQ(16, m.Call(uint32_t(0xB8F10000)));
|
|
|
|
CHECK_EQ(15, m.Call(uint32_t(0x3B9F8000)));
|
|
|
|
CHECK_EQ(14, m.Call(uint32_t(0xDB4C4000)));
|
|
|
|
CHECK_EQ(13, m.Call(uint32_t(0xE9A32000)));
|
|
|
|
CHECK_EQ(12, m.Call(uint32_t(0xFCA61000)));
|
|
|
|
CHECK_EQ(11, m.Call(uint32_t(0x6C8A7800)));
|
|
|
|
CHECK_EQ(10, m.Call(uint32_t(0x8CE5A400)));
|
|
|
|
CHECK_EQ(9, m.Call(uint32_t(0xCB7D0200)));
|
|
|
|
CHECK_EQ(8, m.Call(uint32_t(0xCB4DC100)));
|
|
|
|
CHECK_EQ(7, m.Call(uint32_t(0xDFBEC580)));
|
|
|
|
CHECK_EQ(6, m.Call(uint32_t(0x27A9DB40)));
|
|
|
|
CHECK_EQ(5, m.Call(uint32_t(0xDE3BCB20)));
|
|
|
|
CHECK_EQ(4, m.Call(uint32_t(0xD7E8A610)));
|
|
|
|
CHECK_EQ(3, m.Call(uint32_t(0x9AFDBC88)));
|
|
|
|
CHECK_EQ(2, m.Call(uint32_t(0x9AFDBC84)));
|
|
|
|
CHECK_EQ(1, m.Call(uint32_t(0x9AFDBC82)));
|
|
|
|
CHECK_EQ(0, m.Call(uint32_t(0x9AFDBC81)));
|
2015-11-09 17:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunWord32Clz) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.Word32Clz(m.Parameter(0)));
|
|
|
|
|
|
|
|
CHECK_EQ(0, m.Call(uint32_t(0x80001000)));
|
|
|
|
CHECK_EQ(1, m.Call(uint32_t(0x40000500)));
|
|
|
|
CHECK_EQ(2, m.Call(uint32_t(0x20000300)));
|
|
|
|
CHECK_EQ(3, m.Call(uint32_t(0x10000003)));
|
|
|
|
CHECK_EQ(4, m.Call(uint32_t(0x08050000)));
|
|
|
|
CHECK_EQ(5, m.Call(uint32_t(0x04006000)));
|
|
|
|
CHECK_EQ(6, m.Call(uint32_t(0x02000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(7, m.Call(uint32_t(0x010000A0)));
|
|
|
|
CHECK_EQ(8, m.Call(uint32_t(0x00800C00)));
|
2015-11-09 17:41:35 +00:00
|
|
|
CHECK_EQ(9, m.Call(uint32_t(0x00400000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(10, m.Call(uint32_t(0x0020000D)));
|
|
|
|
CHECK_EQ(11, m.Call(uint32_t(0x00100F00)));
|
2015-11-09 17:41:35 +00:00
|
|
|
CHECK_EQ(12, m.Call(uint32_t(0x00080000)));
|
|
|
|
CHECK_EQ(13, m.Call(uint32_t(0x00041000)));
|
|
|
|
CHECK_EQ(14, m.Call(uint32_t(0x00020020)));
|
|
|
|
CHECK_EQ(15, m.Call(uint32_t(0x00010300)));
|
|
|
|
CHECK_EQ(16, m.Call(uint32_t(0x00008040)));
|
|
|
|
CHECK_EQ(17, m.Call(uint32_t(0x00004005)));
|
|
|
|
CHECK_EQ(18, m.Call(uint32_t(0x00002050)));
|
|
|
|
CHECK_EQ(19, m.Call(uint32_t(0x00001700)));
|
|
|
|
CHECK_EQ(20, m.Call(uint32_t(0x00000870)));
|
|
|
|
CHECK_EQ(21, m.Call(uint32_t(0x00000405)));
|
|
|
|
CHECK_EQ(22, m.Call(uint32_t(0x00000203)));
|
|
|
|
CHECK_EQ(23, m.Call(uint32_t(0x00000101)));
|
|
|
|
CHECK_EQ(24, m.Call(uint32_t(0x00000089)));
|
|
|
|
CHECK_EQ(25, m.Call(uint32_t(0x00000041)));
|
|
|
|
CHECK_EQ(26, m.Call(uint32_t(0x00000022)));
|
|
|
|
CHECK_EQ(27, m.Call(uint32_t(0x00000013)));
|
|
|
|
CHECK_EQ(28, m.Call(uint32_t(0x00000008)));
|
|
|
|
CHECK_EQ(29, m.Call(uint32_t(0x00000004)));
|
|
|
|
CHECK_EQ(30, m.Call(uint32_t(0x00000002)));
|
|
|
|
CHECK_EQ(31, m.Call(uint32_t(0x00000001)));
|
|
|
|
CHECK_EQ(32, m.Call(uint32_t(0x00000000)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32Popcnt) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
|
2015-11-09 17:41:35 +00:00
|
|
|
if (!m.machine()->Word32Popcnt().IsSupported()) {
|
|
|
|
// We can only test the operator if it exists on the testing platform.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m.Return(m.AddNode(m.machine()->Word32Popcnt().op(), m.Parameter(0)));
|
|
|
|
|
|
|
|
CHECK_EQ(0, m.Call(uint32_t(0x00000000)));
|
|
|
|
CHECK_EQ(1, m.Call(uint32_t(0x00000001)));
|
|
|
|
CHECK_EQ(1, m.Call(uint32_t(0x80000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(32, m.Call(uint32_t(0xFFFFFFFF)));
|
|
|
|
CHECK_EQ(6, m.Call(uint32_t(0x000DC100)));
|
|
|
|
CHECK_EQ(9, m.Call(uint32_t(0xE00DC100)));
|
|
|
|
CHECK_EQ(11, m.Call(uint32_t(0xE00DC103)));
|
|
|
|
CHECK_EQ(9, m.Call(uint32_t(0x000DC107)));
|
2015-10-15 18:37:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-06 14:50:44 +00:00
|
|
|
#if V8_TARGET_ARCH_64_BIT
|
2016-02-16 11:14:01 +00:00
|
|
|
TEST(RunWord64ReverseBits) {
|
|
|
|
RawMachineAssemblerTester<uint64_t> m(MachineType::Uint64());
|
|
|
|
if (!m.machine()->Word64ReverseBits().IsSupported()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m.Return(m.AddNode(m.machine()->Word64ReverseBits().op(), m.Parameter(0)));
|
|
|
|
|
|
|
|
CHECK_EQ(uint64_t(0x0000000000000000), m.Call(uint64_t(0x0000000000000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(uint64_t(0x1234567890ABCDEF), m.Call(uint64_t(0xF7B3D5091E6A2C48)));
|
|
|
|
CHECK_EQ(uint64_t(0xFEDCBA0987654321), m.Call(uint64_t(0x84C2A6E1905D3B7F)));
|
2016-02-16 11:14:01 +00:00
|
|
|
CHECK_EQ(uint64_t(0x0101010101010101), m.Call(uint64_t(0x8080808080808080)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(uint64_t(0x0102040803060C01), m.Call(uint64_t(0x803060C010204080)));
|
|
|
|
CHECK_EQ(uint64_t(0xF0703010E060200F), m.Call(uint64_t(0xF0040607080C0E0F)));
|
|
|
|
CHECK_EQ(uint64_t(0x2F8A6DF01C21FA3B), m.Call(uint64_t(0xDC5F84380FB651F4)));
|
|
|
|
CHECK_EQ(uint64_t(0xFFFFFFFFFFFFFFFF), m.Call(uint64_t(0xFFFFFFFFFFFFFFFF)));
|
2016-02-16 11:14:01 +00:00
|
|
|
}
|
|
|
|
|
2016-07-29 19:31:54 +00:00
|
|
|
TEST(RunWord64ReverseBytes) {
|
|
|
|
BufferedRawMachineAssemblerTester<uint64_t> m(MachineType::Uint64());
|
2018-08-14 08:39:05 +00:00
|
|
|
m.Return(m.AddNode(m.machine()->Word64ReverseBytes(), m.Parameter(0)));
|
2016-07-29 19:31:54 +00:00
|
|
|
|
|
|
|
CHECK_EQ(uint64_t(0x0000000000000000), m.Call(uint64_t(0x0000000000000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(uint64_t(0x1234567890ABCDEF), m.Call(uint64_t(0xEFCDAB9078563412)));
|
|
|
|
CHECK_EQ(uint64_t(0xFEDCBA0987654321), m.Call(uint64_t(0x2143658709BADCFE)));
|
2016-07-29 19:31:54 +00:00
|
|
|
CHECK_EQ(uint64_t(0x0101010101010101), m.Call(uint64_t(0x0101010101010101)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(uint64_t(0x0102040803060C01), m.Call(uint64_t(0x010C060308040201)));
|
|
|
|
CHECK_EQ(uint64_t(0xF0703010E060200F), m.Call(uint64_t(0x0F2060E0103070F0)));
|
|
|
|
CHECK_EQ(uint64_t(0x2F8A6DF01C21FA3B), m.Call(uint64_t(0x3BFA211CF06D8A2F)));
|
|
|
|
CHECK_EQ(uint64_t(0xFFFFFFFFFFFFFFFF), m.Call(uint64_t(0xFFFFFFFFFFFFFFFF)));
|
2016-07-29 19:31:54 +00:00
|
|
|
}
|
2016-02-16 11:14:01 +00:00
|
|
|
|
2015-11-06 14:50:44 +00:00
|
|
|
TEST(RunWord64Clz) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint64());
|
2015-11-06 14:50:44 +00:00
|
|
|
m.Return(m.Word64Clz(m.Parameter(0)));
|
|
|
|
|
|
|
|
CHECK_EQ(0, m.Call(uint64_t(0x8000100000000000)));
|
|
|
|
CHECK_EQ(1, m.Call(uint64_t(0x4000050000000000)));
|
|
|
|
CHECK_EQ(2, m.Call(uint64_t(0x2000030000000000)));
|
|
|
|
CHECK_EQ(3, m.Call(uint64_t(0x1000000300000000)));
|
|
|
|
CHECK_EQ(4, m.Call(uint64_t(0x0805000000000000)));
|
|
|
|
CHECK_EQ(5, m.Call(uint64_t(0x0400600000000000)));
|
|
|
|
CHECK_EQ(6, m.Call(uint64_t(0x0200000000000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(7, m.Call(uint64_t(0x010000A000000000)));
|
|
|
|
CHECK_EQ(8, m.Call(uint64_t(0x00800C0000000000)));
|
2015-11-06 14:50:44 +00:00
|
|
|
CHECK_EQ(9, m.Call(uint64_t(0x0040000000000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(10, m.Call(uint64_t(0x0020000D00000000)));
|
|
|
|
CHECK_EQ(11, m.Call(uint64_t(0x00100F0000000000)));
|
2015-11-06 14:50:44 +00:00
|
|
|
CHECK_EQ(12, m.Call(uint64_t(0x0008000000000000)));
|
|
|
|
CHECK_EQ(13, m.Call(uint64_t(0x0004100000000000)));
|
|
|
|
CHECK_EQ(14, m.Call(uint64_t(0x0002002000000000)));
|
|
|
|
CHECK_EQ(15, m.Call(uint64_t(0x0001030000000000)));
|
|
|
|
CHECK_EQ(16, m.Call(uint64_t(0x0000804000000000)));
|
|
|
|
CHECK_EQ(17, m.Call(uint64_t(0x0000400500000000)));
|
|
|
|
CHECK_EQ(18, m.Call(uint64_t(0x0000205000000000)));
|
|
|
|
CHECK_EQ(19, m.Call(uint64_t(0x0000170000000000)));
|
|
|
|
CHECK_EQ(20, m.Call(uint64_t(0x0000087000000000)));
|
|
|
|
CHECK_EQ(21, m.Call(uint64_t(0x0000040500000000)));
|
|
|
|
CHECK_EQ(22, m.Call(uint64_t(0x0000020300000000)));
|
|
|
|
CHECK_EQ(23, m.Call(uint64_t(0x0000010100000000)));
|
|
|
|
CHECK_EQ(24, m.Call(uint64_t(0x0000008900000000)));
|
|
|
|
CHECK_EQ(25, m.Call(uint64_t(0x0000004100000000)));
|
|
|
|
CHECK_EQ(26, m.Call(uint64_t(0x0000002200000000)));
|
|
|
|
CHECK_EQ(27, m.Call(uint64_t(0x0000001300000000)));
|
|
|
|
CHECK_EQ(28, m.Call(uint64_t(0x0000000800000000)));
|
|
|
|
CHECK_EQ(29, m.Call(uint64_t(0x0000000400000000)));
|
|
|
|
CHECK_EQ(30, m.Call(uint64_t(0x0000000200000000)));
|
|
|
|
CHECK_EQ(31, m.Call(uint64_t(0x0000000100000000)));
|
|
|
|
CHECK_EQ(32, m.Call(uint64_t(0x0000000080001000)));
|
|
|
|
CHECK_EQ(33, m.Call(uint64_t(0x0000000040000500)));
|
|
|
|
CHECK_EQ(34, m.Call(uint64_t(0x0000000020000300)));
|
|
|
|
CHECK_EQ(35, m.Call(uint64_t(0x0000000010000003)));
|
|
|
|
CHECK_EQ(36, m.Call(uint64_t(0x0000000008050000)));
|
|
|
|
CHECK_EQ(37, m.Call(uint64_t(0x0000000004006000)));
|
|
|
|
CHECK_EQ(38, m.Call(uint64_t(0x0000000002000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(39, m.Call(uint64_t(0x00000000010000A0)));
|
|
|
|
CHECK_EQ(40, m.Call(uint64_t(0x0000000000800C00)));
|
2015-11-06 14:50:44 +00:00
|
|
|
CHECK_EQ(41, m.Call(uint64_t(0x0000000000400000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(42, m.Call(uint64_t(0x000000000020000D)));
|
|
|
|
CHECK_EQ(43, m.Call(uint64_t(0x0000000000100F00)));
|
2015-11-06 14:50:44 +00:00
|
|
|
CHECK_EQ(44, m.Call(uint64_t(0x0000000000080000)));
|
|
|
|
CHECK_EQ(45, m.Call(uint64_t(0x0000000000041000)));
|
|
|
|
CHECK_EQ(46, m.Call(uint64_t(0x0000000000020020)));
|
|
|
|
CHECK_EQ(47, m.Call(uint64_t(0x0000000000010300)));
|
|
|
|
CHECK_EQ(48, m.Call(uint64_t(0x0000000000008040)));
|
|
|
|
CHECK_EQ(49, m.Call(uint64_t(0x0000000000004005)));
|
|
|
|
CHECK_EQ(50, m.Call(uint64_t(0x0000000000002050)));
|
|
|
|
CHECK_EQ(51, m.Call(uint64_t(0x0000000000001700)));
|
|
|
|
CHECK_EQ(52, m.Call(uint64_t(0x0000000000000870)));
|
|
|
|
CHECK_EQ(53, m.Call(uint64_t(0x0000000000000405)));
|
|
|
|
CHECK_EQ(54, m.Call(uint64_t(0x0000000000000203)));
|
|
|
|
CHECK_EQ(55, m.Call(uint64_t(0x0000000000000101)));
|
|
|
|
CHECK_EQ(56, m.Call(uint64_t(0x0000000000000089)));
|
|
|
|
CHECK_EQ(57, m.Call(uint64_t(0x0000000000000041)));
|
|
|
|
CHECK_EQ(58, m.Call(uint64_t(0x0000000000000022)));
|
|
|
|
CHECK_EQ(59, m.Call(uint64_t(0x0000000000000013)));
|
|
|
|
CHECK_EQ(60, m.Call(uint64_t(0x0000000000000008)));
|
|
|
|
CHECK_EQ(61, m.Call(uint64_t(0x0000000000000004)));
|
|
|
|
CHECK_EQ(62, m.Call(uint64_t(0x0000000000000002)));
|
|
|
|
CHECK_EQ(63, m.Call(uint64_t(0x0000000000000001)));
|
|
|
|
CHECK_EQ(64, m.Call(uint64_t(0x0000000000000000)));
|
|
|
|
}
|
2015-11-10 08:42:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord64Ctz) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Uint64());
|
2015-11-10 08:42:17 +00:00
|
|
|
if (!m.machine()->Word64Ctz().IsSupported()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m.Return(m.AddNode(m.machine()->Word64Ctz().op(), m.Parameter(0)));
|
|
|
|
|
|
|
|
CHECK_EQ(64, m.Call(uint64_t(0x0000000000000000)));
|
|
|
|
CHECK_EQ(63, m.Call(uint64_t(0x8000000000000000)));
|
|
|
|
CHECK_EQ(62, m.Call(uint64_t(0x4000000000000000)));
|
|
|
|
CHECK_EQ(61, m.Call(uint64_t(0x2000000000000000)));
|
|
|
|
CHECK_EQ(60, m.Call(uint64_t(0x1000000000000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(59, m.Call(uint64_t(0xA800000000000000)));
|
|
|
|
CHECK_EQ(58, m.Call(uint64_t(0xF400000000000000)));
|
2015-11-10 08:42:17 +00:00
|
|
|
CHECK_EQ(57, m.Call(uint64_t(0x6200000000000000)));
|
|
|
|
CHECK_EQ(56, m.Call(uint64_t(0x9100000000000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(55, m.Call(uint64_t(0xCD80000000000000)));
|
2015-11-10 08:42:17 +00:00
|
|
|
CHECK_EQ(54, m.Call(uint64_t(0x0940000000000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(53, m.Call(uint64_t(0xAF20000000000000)));
|
|
|
|
CHECK_EQ(52, m.Call(uint64_t(0xAC10000000000000)));
|
|
|
|
CHECK_EQ(51, m.Call(uint64_t(0xE0B8000000000000)));
|
|
|
|
CHECK_EQ(50, m.Call(uint64_t(0x9CE4000000000000)));
|
|
|
|
CHECK_EQ(49, m.Call(uint64_t(0xC792000000000000)));
|
|
|
|
CHECK_EQ(48, m.Call(uint64_t(0xB8F1000000000000)));
|
|
|
|
CHECK_EQ(47, m.Call(uint64_t(0x3B9F800000000000)));
|
|
|
|
CHECK_EQ(46, m.Call(uint64_t(0xDB4C400000000000)));
|
|
|
|
CHECK_EQ(45, m.Call(uint64_t(0xE9A3200000000000)));
|
|
|
|
CHECK_EQ(44, m.Call(uint64_t(0xFCA6100000000000)));
|
|
|
|
CHECK_EQ(43, m.Call(uint64_t(0x6C8A780000000000)));
|
|
|
|
CHECK_EQ(42, m.Call(uint64_t(0x8CE5A40000000000)));
|
|
|
|
CHECK_EQ(41, m.Call(uint64_t(0xCB7D020000000000)));
|
|
|
|
CHECK_EQ(40, m.Call(uint64_t(0xCB4DC10000000000)));
|
|
|
|
CHECK_EQ(39, m.Call(uint64_t(0xDFBEC58000000000)));
|
|
|
|
CHECK_EQ(38, m.Call(uint64_t(0x27A9DB4000000000)));
|
|
|
|
CHECK_EQ(37, m.Call(uint64_t(0xDE3BCB2000000000)));
|
|
|
|
CHECK_EQ(36, m.Call(uint64_t(0xD7E8A61000000000)));
|
|
|
|
CHECK_EQ(35, m.Call(uint64_t(0x9AFDBC8800000000)));
|
|
|
|
CHECK_EQ(34, m.Call(uint64_t(0x9AFDBC8400000000)));
|
|
|
|
CHECK_EQ(33, m.Call(uint64_t(0x9AFDBC8200000000)));
|
|
|
|
CHECK_EQ(32, m.Call(uint64_t(0x9AFDBC8100000000)));
|
2015-11-10 08:42:17 +00:00
|
|
|
CHECK_EQ(31, m.Call(uint64_t(0x0000000080000000)));
|
|
|
|
CHECK_EQ(30, m.Call(uint64_t(0x0000000040000000)));
|
|
|
|
CHECK_EQ(29, m.Call(uint64_t(0x0000000020000000)));
|
|
|
|
CHECK_EQ(28, m.Call(uint64_t(0x0000000010000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(27, m.Call(uint64_t(0x00000000A8000000)));
|
|
|
|
CHECK_EQ(26, m.Call(uint64_t(0x00000000F4000000)));
|
2015-11-10 08:42:17 +00:00
|
|
|
CHECK_EQ(25, m.Call(uint64_t(0x0000000062000000)));
|
|
|
|
CHECK_EQ(24, m.Call(uint64_t(0x0000000091000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(23, m.Call(uint64_t(0x00000000CD800000)));
|
2015-11-10 08:42:17 +00:00
|
|
|
CHECK_EQ(22, m.Call(uint64_t(0x0000000009400000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(21, m.Call(uint64_t(0x00000000AF200000)));
|
|
|
|
CHECK_EQ(20, m.Call(uint64_t(0x00000000AC100000)));
|
|
|
|
CHECK_EQ(19, m.Call(uint64_t(0x00000000E0B80000)));
|
|
|
|
CHECK_EQ(18, m.Call(uint64_t(0x000000009CE40000)));
|
|
|
|
CHECK_EQ(17, m.Call(uint64_t(0x00000000C7920000)));
|
|
|
|
CHECK_EQ(16, m.Call(uint64_t(0x00000000B8F10000)));
|
|
|
|
CHECK_EQ(15, m.Call(uint64_t(0x000000003B9F8000)));
|
|
|
|
CHECK_EQ(14, m.Call(uint64_t(0x00000000DB4C4000)));
|
|
|
|
CHECK_EQ(13, m.Call(uint64_t(0x00000000E9A32000)));
|
|
|
|
CHECK_EQ(12, m.Call(uint64_t(0x00000000FCA61000)));
|
|
|
|
CHECK_EQ(11, m.Call(uint64_t(0x000000006C8A7800)));
|
|
|
|
CHECK_EQ(10, m.Call(uint64_t(0x000000008CE5A400)));
|
|
|
|
CHECK_EQ(9, m.Call(uint64_t(0x00000000CB7D0200)));
|
|
|
|
CHECK_EQ(8, m.Call(uint64_t(0x00000000CB4DC100)));
|
|
|
|
CHECK_EQ(7, m.Call(uint64_t(0x00000000DFBEC580)));
|
|
|
|
CHECK_EQ(6, m.Call(uint64_t(0x0000000027A9DB40)));
|
|
|
|
CHECK_EQ(5, m.Call(uint64_t(0x00000000DE3BCB20)));
|
|
|
|
CHECK_EQ(4, m.Call(uint64_t(0x00000000D7E8A610)));
|
|
|
|
CHECK_EQ(3, m.Call(uint64_t(0x000000009AFDBC88)));
|
|
|
|
CHECK_EQ(2, m.Call(uint64_t(0x000000009AFDBC84)));
|
|
|
|
CHECK_EQ(1, m.Call(uint64_t(0x000000009AFDBC82)));
|
|
|
|
CHECK_EQ(0, m.Call(uint64_t(0x000000009AFDBC81)));
|
2015-11-10 08:42:17 +00:00
|
|
|
}
|
2015-11-10 20:38:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord64Popcnt) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint64());
|
2015-11-10 20:38:02 +00:00
|
|
|
if (!m.machine()->Word64Popcnt().IsSupported()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m.Return(m.AddNode(m.machine()->Word64Popcnt().op(), m.Parameter(0)));
|
|
|
|
|
|
|
|
CHECK_EQ(0, m.Call(uint64_t(0x0000000000000000)));
|
|
|
|
CHECK_EQ(1, m.Call(uint64_t(0x0000000000000001)));
|
|
|
|
CHECK_EQ(1, m.Call(uint64_t(0x8000000000000000)));
|
2017-12-02 00:30:37 +00:00
|
|
|
CHECK_EQ(64, m.Call(uint64_t(0xFFFFFFFFFFFFFFFF)));
|
|
|
|
CHECK_EQ(12, m.Call(uint64_t(0x000DC100000DC100)));
|
|
|
|
CHECK_EQ(18, m.Call(uint64_t(0xE00DC100E00DC100)));
|
|
|
|
CHECK_EQ(22, m.Call(uint64_t(0xE00DC103E00DC103)));
|
|
|
|
CHECK_EQ(18, m.Call(uint64_t(0x000DC107000DC107)));
|
2015-11-10 20:38:02 +00:00
|
|
|
}
|
2015-11-06 14:50:44 +00:00
|
|
|
#endif // V8_TARGET_ARCH_64_BIT
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
static Node* Int32Input(RawMachineAssemblerTester<int32_t>* m, int index) {
|
|
|
|
switch (index) {
|
|
|
|
case 0:
|
|
|
|
return m->Parameter(0);
|
|
|
|
case 1:
|
|
|
|
return m->Parameter(1);
|
|
|
|
case 2:
|
|
|
|
return m->Int32Constant(0);
|
|
|
|
case 3:
|
|
|
|
return m->Int32Constant(1);
|
|
|
|
case 4:
|
|
|
|
return m->Int32Constant(-1);
|
|
|
|
case 5:
|
2017-12-02 00:30:37 +00:00
|
|
|
return m->Int32Constant(0xFF);
|
2014-07-30 13:54:45 +00:00
|
|
|
case 6:
|
|
|
|
return m->Int32Constant(0x01234567);
|
|
|
|
case 7:
|
2017-10-13 16:33:03 +00:00
|
|
|
return m->Load(MachineType::Int32(), m->PointerConstant(nullptr));
|
2014-07-30 13:54:45 +00:00
|
|
|
default:
|
2017-10-13 16:33:03 +00:00
|
|
|
return nullptr;
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(CodeGenInt32Binop) {
|
|
|
|
RawMachineAssemblerTester<void> m;
|
|
|
|
|
2014-10-14 11:57:06 +00:00
|
|
|
const Operator* kOps[] = {
|
2014-11-03 10:04:37 +00:00
|
|
|
m.machine()->Word32And(), m.machine()->Word32Or(),
|
|
|
|
m.machine()->Word32Xor(), m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr(), m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Equal(), m.machine()->Int32Add(),
|
|
|
|
m.machine()->Int32Sub(), m.machine()->Int32Mul(),
|
|
|
|
m.machine()->Int32MulHigh(), m.machine()->Int32Div(),
|
|
|
|
m.machine()->Uint32Div(), m.machine()->Int32Mod(),
|
|
|
|
m.machine()->Uint32Mod(), m.machine()->Uint32MulHigh(),
|
|
|
|
m.machine()->Int32LessThan(), m.machine()->Int32LessThanOrEqual(),
|
|
|
|
m.machine()->Uint32LessThan(), m.machine()->Uint32LessThanOrEqual()};
|
2014-10-14 11:57:06 +00:00
|
|
|
|
|
|
|
for (size_t i = 0; i < arraysize(kOps); ++i) {
|
2014-07-30 13:54:45 +00:00
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
for (int k = 0; k < 8; k++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
|
|
|
|
MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* a = Int32Input(&m, j);
|
|
|
|
Node* b = Int32Input(&m, k);
|
2015-09-23 09:08:15 +00:00
|
|
|
m.Return(m.AddNode(kOps[i], a, b));
|
2014-07-30 13:54:45 +00:00
|
|
|
m.GenerateCode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-04 13:13:54 +00:00
|
|
|
TEST(CodeGenNop) {
|
|
|
|
RawMachineAssemblerTester<void> m;
|
|
|
|
m.Return(m.Int32Constant(0));
|
|
|
|
m.GenerateCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-10 07:17:16 +00:00
|
|
|
#if V8_TARGET_ARCH_64_BIT
|
2015-07-03 05:13:57 +00:00
|
|
|
static Node* Int64Input(RawMachineAssemblerTester<int64_t>* m, int index) {
|
|
|
|
switch (index) {
|
|
|
|
case 0:
|
|
|
|
return m->Parameter(0);
|
|
|
|
case 1:
|
|
|
|
return m->Parameter(1);
|
|
|
|
case 2:
|
|
|
|
return m->Int64Constant(0);
|
|
|
|
case 3:
|
|
|
|
return m->Int64Constant(1);
|
|
|
|
case 4:
|
|
|
|
return m->Int64Constant(-1);
|
|
|
|
case 5:
|
2017-12-02 00:30:37 +00:00
|
|
|
return m->Int64Constant(0xFF);
|
2015-07-03 05:13:57 +00:00
|
|
|
case 6:
|
2017-12-02 00:30:37 +00:00
|
|
|
return m->Int64Constant(0x0123456789ABCDEFLL);
|
2015-07-03 05:13:57 +00:00
|
|
|
case 7:
|
2017-10-13 16:33:03 +00:00
|
|
|
return m->Load(MachineType::Int64(), m->PointerConstant(nullptr));
|
2015-07-03 05:13:57 +00:00
|
|
|
default:
|
2017-10-13 16:33:03 +00:00
|
|
|
return nullptr;
|
2015-07-03 05:13:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(CodeGenInt64Binop) {
|
|
|
|
RawMachineAssemblerTester<void> m;
|
|
|
|
|
|
|
|
const Operator* kOps[] = {
|
|
|
|
m.machine()->Word64And(), m.machine()->Word64Or(),
|
|
|
|
m.machine()->Word64Xor(), m.machine()->Word64Shl(),
|
|
|
|
m.machine()->Word64Shr(), m.machine()->Word64Sar(),
|
|
|
|
m.machine()->Word64Equal(), m.machine()->Int64Add(),
|
|
|
|
m.machine()->Int64Sub(), m.machine()->Int64Mul(), m.machine()->Int64Div(),
|
|
|
|
m.machine()->Uint64Div(), m.machine()->Int64Mod(),
|
|
|
|
m.machine()->Uint64Mod(), m.machine()->Int64LessThan(),
|
|
|
|
m.machine()->Int64LessThanOrEqual(), m.machine()->Uint64LessThan(),
|
|
|
|
m.machine()->Uint64LessThanOrEqual()};
|
|
|
|
|
|
|
|
for (size_t i = 0; i < arraysize(kOps); ++i) {
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
for (int k = 0; k < 8; k++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int64_t> m(MachineType::Int64(),
|
|
|
|
MachineType::Int64());
|
2015-07-03 05:13:57 +00:00
|
|
|
Node* a = Int64Input(&m, j);
|
|
|
|
Node* b = Int64Input(&m, k);
|
2015-09-23 09:08:15 +00:00
|
|
|
m.Return(m.AddNode(kOps[i], a, b));
|
2015-07-03 05:13:57 +00:00
|
|
|
m.GenerateCode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-24 18:50:37 +00:00
|
|
|
TEST(RunInt64AddWithOverflowP) {
|
|
|
|
int64_t actual_val = -1;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int64BinopTester bt(&m);
|
|
|
|
Node* add = m.Int64AddWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
|
|
|
|
bt.AddReturn(ovf);
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
FOR_INT64_INPUTS(j) {
|
|
|
|
int64_t expected_val;
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedAddOverflow64(*i, *j, &expected_val);
|
2015-12-24 18:50:37 +00:00
|
|
|
CHECK_EQ(expected_ovf, bt.call(*i, *j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt64AddWithOverflowImm) {
|
|
|
|
int64_t actual_val = -1, expected_val = 0;
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int64());
|
|
|
|
Node* add = m.Int64AddWithOverflow(m.Int64Constant(*i), m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
|
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT64_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedAddOverflow64(*i, *j, &expected_val);
|
2015-12-24 18:50:37 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int64());
|
|
|
|
Node* add = m.Int64AddWithOverflow(m.Parameter(0), m.Int64Constant(*i));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
|
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT64_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedAddOverflow64(*i, *j, &expected_val);
|
2015-12-24 18:50:37 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FOR_INT64_INPUTS(j) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Node* add =
|
|
|
|
m.Int64AddWithOverflow(m.Int64Constant(*i), m.Int64Constant(*j));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
|
|
|
|
m.Return(ovf);
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedAddOverflow64(*i, *j, &expected_val);
|
2015-12-24 18:50:37 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call());
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt64AddWithOverflowInBranchP) {
|
|
|
|
int constant = 911777;
|
|
|
|
RawMachineLabel blocka, blockb;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int64BinopTester bt(&m);
|
|
|
|
Node* add = m.Int64AddWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.Branch(ovf, &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int64Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* truncated = m.TruncateInt64ToInt32(val);
|
|
|
|
bt.AddReturn(truncated);
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
FOR_INT64_INPUTS(j) {
|
|
|
|
int32_t expected = constant;
|
|
|
|
int64_t result;
|
2017-08-11 11:22:28 +00:00
|
|
|
if (!base::bits::SignedAddOverflow64(*i, *j, &result)) {
|
2015-12-24 18:50:37 +00:00
|
|
|
expected = static_cast<int32_t>(result);
|
|
|
|
}
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt64SubWithOverflowP) {
|
|
|
|
int64_t actual_val = -1;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int64BinopTester bt(&m);
|
|
|
|
Node* add = m.Int64SubWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
|
|
|
|
bt.AddReturn(ovf);
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
FOR_INT64_INPUTS(j) {
|
|
|
|
int64_t expected_val;
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedSubOverflow64(*i, *j, &expected_val);
|
2015-12-24 18:50:37 +00:00
|
|
|
CHECK_EQ(expected_ovf, bt.call(*i, *j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt64SubWithOverflowImm) {
|
|
|
|
int64_t actual_val = -1, expected_val = 0;
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int64());
|
|
|
|
Node* add = m.Int64SubWithOverflow(m.Int64Constant(*i), m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
|
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT64_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedSubOverflow64(*i, *j, &expected_val);
|
2015-12-24 18:50:37 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int64());
|
|
|
|
Node* add = m.Int64SubWithOverflow(m.Parameter(0), m.Int64Constant(*i));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
|
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT64_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedSubOverflow64(*j, *i, &expected_val);
|
2015-12-24 18:50:37 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FOR_INT64_INPUTS(j) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Node* add =
|
|
|
|
m.Int64SubWithOverflow(m.Int64Constant(*i), m.Int64Constant(*j));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
|
|
|
|
m.Return(ovf);
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedSubOverflow64(*i, *j, &expected_val);
|
2015-12-24 18:50:37 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call());
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt64SubWithOverflowInBranchP) {
|
|
|
|
int constant = 911999;
|
|
|
|
RawMachineLabel blocka, blockb;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int64BinopTester bt(&m);
|
|
|
|
Node* sub = m.Int64SubWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* ovf = m.Projection(1, sub);
|
|
|
|
m.Branch(ovf, &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int64Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
Node* val = m.Projection(0, sub);
|
|
|
|
Node* truncated = m.TruncateInt64ToInt32(val);
|
|
|
|
bt.AddReturn(truncated);
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
FOR_INT64_INPUTS(j) {
|
|
|
|
int32_t expected = constant;
|
|
|
|
int64_t result;
|
2017-08-11 11:22:28 +00:00
|
|
|
if (!base::bits::SignedSubOverflow64(*i, *j, &result)) {
|
2015-12-24 18:50:37 +00:00
|
|
|
expected = static_cast<int32_t>(result);
|
|
|
|
}
|
|
|
|
CHECK_EQ(expected, static_cast<int32_t>(bt.call(*i, *j)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-08 09:56:14 +00:00
|
|
|
static int64_t RunInt64AddShift(bool is_left, int64_t add_left,
|
|
|
|
int64_t add_right, int64_t shift_left,
|
|
|
|
int64_t shit_right) {
|
|
|
|
RawMachineAssemblerTester<int64_t> m;
|
|
|
|
Node* shift = m.Word64Shl(m.Int64Constant(4), m.Int64Constant(2));
|
|
|
|
Node* add = m.Int64Add(m.Int64Constant(20), m.Int64Constant(22));
|
|
|
|
Node* dlsa = is_left ? m.Int64Add(shift, add) : m.Int64Add(add, shift);
|
|
|
|
m.Return(dlsa);
|
|
|
|
return m.Call();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt64AddShift) {
|
|
|
|
struct Test_case {
|
|
|
|
int64_t add_left, add_right, shift_left, shit_right, expected;
|
|
|
|
};
|
|
|
|
|
|
|
|
Test_case tc[] = {
|
|
|
|
{20, 22, 4, 2, 58},
|
|
|
|
{20, 22, 4, 1, 50},
|
|
|
|
{20, 22, 1, 6, 106},
|
|
|
|
{INT64_MAX - 2, 1, 1, 1,
|
|
|
|
INT64_MIN}, // INT64_MAX - 2 + 1 + (1 << 1), overflow.
|
|
|
|
};
|
|
|
|
const size_t tc_size = sizeof(tc) / sizeof(Test_case);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < tc_size; ++i) {
|
|
|
|
CHECK_EQ(58, RunInt64AddShift(false, tc[i].add_left, tc[i].add_right,
|
|
|
|
tc[i].shift_left, tc[i].shit_right));
|
|
|
|
CHECK_EQ(58, RunInt64AddShift(true, tc[i].add_left, tc[i].add_right,
|
|
|
|
tc[i].shift_left, tc[i].shit_right));
|
|
|
|
}
|
|
|
|
}
|
2015-12-24 18:50:37 +00:00
|
|
|
|
2015-07-03 05:13:57 +00:00
|
|
|
// TODO(titzer): add tests that run 64-bit integer operations.
|
2015-08-10 07:17:16 +00:00
|
|
|
#endif // V8_TARGET_ARCH_64_BIT
|
2015-07-03 05:13:57 +00:00
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunGoto) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int constant = 99999;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel next;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Goto(&next);
|
|
|
|
m.Bind(&next);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunGotoMultiple) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int constant = 9999977;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel labels[10];
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t i = 0; i < arraysize(labels); i++) {
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Goto(&labels[i]);
|
|
|
|
m.Bind(&labels[i]);
|
|
|
|
}
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunBranch) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int constant = 999777;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Int32Constant(0), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDiamond2) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
int constant = 995666;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Int32Constant(0), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&end);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoop) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int constant = 999555;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, exit;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Goto(&header);
|
|
|
|
m.Bind(&header);
|
|
|
|
m.Branch(m.Int32Constant(0), &body, &exit);
|
|
|
|
m.Bind(&body);
|
|
|
|
m.Goto(&header);
|
|
|
|
m.Bind(&exit);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename R>
|
|
|
|
static void BuildDiamondPhi(RawMachineAssemblerTester<R>* m, Node* cond_node,
|
2015-12-10 09:03:30 +00:00
|
|
|
MachineRepresentation rep, Node* true_node,
|
2014-09-05 11:44:31 +00:00
|
|
|
Node* false_node) {
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
m->Branch(cond_node, &blocka, &blockb);
|
|
|
|
m->Bind(&blocka);
|
2015-06-10 17:37:31 +00:00
|
|
|
m->Goto(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
m->Bind(&blockb);
|
2015-06-10 17:37:31 +00:00
|
|
|
m->Goto(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m->Bind(&end);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m->Phi(rep, true_node, false_node);
|
2014-07-30 13:54:45 +00:00
|
|
|
m->Return(phi);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDiamondPhiConst) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
int false_val = 0xFF666;
|
|
|
|
int true_val = 0x00DDD;
|
|
|
|
Node* true_node = m.Int32Constant(true_val);
|
|
|
|
Node* false_node = m.Int32Constant(false_val);
|
2015-12-10 09:03:30 +00:00
|
|
|
BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kWord32, true_node,
|
|
|
|
false_node);
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(false_val, m.Call(0));
|
|
|
|
CHECK_EQ(true_val, m.Call(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDiamondPhiNumber) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<Object*> m(MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
double false_val = -11.1;
|
|
|
|
double true_val = 200.1;
|
|
|
|
Node* true_node = m.NumberConstant(true_val);
|
|
|
|
Node* false_node = m.NumberConstant(false_val);
|
2015-12-10 09:03:30 +00:00
|
|
|
BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kTagged, true_node,
|
|
|
|
false_node);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.CheckNumber(false_val, m.Call(0));
|
|
|
|
m.CheckNumber(true_val, m.Call(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDiamondPhiString) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<Object*> m(MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
const char* false_val = "false";
|
|
|
|
const char* true_val = "true";
|
|
|
|
Node* true_node = m.StringConstant(true_val);
|
|
|
|
Node* false_node = m.StringConstant(false_val);
|
2015-12-10 09:03:30 +00:00
|
|
|
BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kTagged, true_node,
|
|
|
|
false_node);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.CheckString(false_val, m.Call(0));
|
|
|
|
m.CheckString(true_val, m.Call(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDiamondPhiParam) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
|
|
|
|
BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kWord32,
|
|
|
|
m.Parameter(1), m.Parameter(2));
|
2017-12-02 00:30:37 +00:00
|
|
|
int32_t c1 = 0x260CB75A;
|
|
|
|
int32_t c2 = 0xCD3E9C8B;
|
2014-07-30 13:54:45 +00:00
|
|
|
int result = m.Call(0, c1, c2);
|
|
|
|
CHECK_EQ(c2, result);
|
|
|
|
result = m.Call(1, c1, c2);
|
|
|
|
CHECK_EQ(c1, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoopPhiConst) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int true_val = 0x44000;
|
|
|
|
int false_val = 0x00888;
|
|
|
|
|
|
|
|
Node* cond_node = m.Int32Constant(0);
|
|
|
|
Node* true_node = m.Int32Constant(true_val);
|
|
|
|
Node* false_node = m.Int32Constant(false_val);
|
|
|
|
|
|
|
|
// x = false_val; while(false) { x = true_val; } return x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel body, header, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kWord32, false_node, true_node);
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(cond_node, &body, &end);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Bind(&body);
|
|
|
|
m.Goto(&header);
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(phi);
|
|
|
|
|
|
|
|
CHECK_EQ(false_val, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoopPhiParam) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Goto(&blocka);
|
|
|
|
|
|
|
|
m.Bind(&blocka);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi =
|
|
|
|
m.Phi(MachineRepresentation::kWord32, m.Parameter(1), m.Parameter(2));
|
|
|
|
Node* cond =
|
|
|
|
m.Phi(MachineRepresentation::kWord32, m.Parameter(0), m.Int32Constant(0));
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(cond, &blockb, &end);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Goto(&blocka);
|
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(phi);
|
|
|
|
|
2017-12-02 00:30:37 +00:00
|
|
|
int32_t c1 = 0xA81903B4;
|
|
|
|
int32_t c2 = 0x5A1207DA;
|
2014-07-30 13:54:45 +00:00
|
|
|
int result = m.Call(0, c1, c2);
|
|
|
|
CHECK_EQ(c1, result);
|
|
|
|
result = m.Call(1, c1, c2);
|
|
|
|
CHECK_EQ(c2, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoopPhiInduction) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
int false_val = 0x10777;
|
|
|
|
|
|
|
|
// x = false_val; while(false) { x++; } return x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* false_node = m.Int32Constant(false_val);
|
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kWord32, false_node, false_node);
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(m.Int32Constant(0), &body, &end);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
Node* add = m.Int32Add(phi, m.Int32Constant(1));
|
|
|
|
phi->ReplaceInput(1, add);
|
|
|
|
m.Goto(&header);
|
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(phi);
|
|
|
|
|
|
|
|
CHECK_EQ(false_val, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoopIncrement) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
|
|
|
|
// x = 0; while(x ^ param) { x++; } return x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* zero = m.Int32Constant(0);
|
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero);
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(m.WordXor(phi, bt.param0), &body, &end);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
|
|
|
|
m.Goto(&header);
|
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(phi);
|
|
|
|
|
|
|
|
CHECK_EQ(11, bt.call(11, 0));
|
|
|
|
CHECK_EQ(110, bt.call(110, 0));
|
|
|
|
CHECK_EQ(176, bt.call(176, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoopIncrement2) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
|
|
|
|
// x = 0; while(x < param) { x++; } return x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* zero = m.Int32Constant(0);
|
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero);
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(m.Int32LessThan(phi, bt.param0), &body, &end);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
|
|
|
|
m.Goto(&header);
|
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(phi);
|
|
|
|
|
|
|
|
CHECK_EQ(11, bt.call(11, 0));
|
|
|
|
CHECK_EQ(110, bt.call(110, 0));
|
|
|
|
CHECK_EQ(176, bt.call(176, 0));
|
|
|
|
CHECK_EQ(0, bt.call(-200, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoopIncrement3) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
|
|
|
|
// x = 0; while(x < param) { x++; } return x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* zero = m.Int32Constant(0);
|
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero);
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(m.Uint32LessThan(phi, bt.param0), &body, &end);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
|
|
|
|
m.Goto(&header);
|
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(phi);
|
|
|
|
|
|
|
|
CHECK_EQ(11, bt.call(11, 0));
|
|
|
|
CHECK_EQ(110, bt.call(110, 0));
|
|
|
|
CHECK_EQ(176, bt.call(176, 0));
|
|
|
|
CHECK_EQ(200, bt.call(200, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoopDecrement) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
|
|
|
|
// x = param; while(x) { x--; } return x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi =
|
|
|
|
m.Phi(MachineRepresentation::kWord32, bt.param0, m.Int32Constant(0));
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(phi, &body, &end);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
phi->ReplaceInput(1, m.Int32Sub(phi, m.Int32Constant(1)));
|
|
|
|
m.Goto(&header);
|
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(phi);
|
|
|
|
|
|
|
|
CHECK_EQ(0, bt.call(11, 0));
|
|
|
|
CHECK_EQ(0, bt.call(110, 0));
|
|
|
|
CHECK_EQ(0, bt.call(197, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-30 07:33:46 +00:00
|
|
|
TEST(RunLoopIncrementFloat32) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
// x = -3.0f; while(x < 10f) { x = x + 0.5f; } return (int) (double) x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2015-03-30 07:33:46 +00:00
|
|
|
Node* minus_3 = m.Float32Constant(-3.0f);
|
|
|
|
Node* ten = m.Float32Constant(10.0f);
|
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kFloat32, minus_3, ten);
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(m.Float32LessThan(phi, ten), &body, &end);
|
2015-03-30 07:33:46 +00:00
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
phi->ReplaceInput(1, m.Float32Add(phi, m.Float32Constant(0.5f)));
|
|
|
|
m.Goto(&header);
|
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2015-03-30 07:33:46 +00:00
|
|
|
m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(phi)));
|
|
|
|
|
|
|
|
CHECK_EQ(10, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunLoopIncrementFloat64) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
// x = -3.0; while(x < 10) { x = x + 0.5; } return (int) x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* minus_3 = m.Float64Constant(-3.0);
|
|
|
|
Node* ten = m.Float64Constant(10.0);
|
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kFloat64, minus_3, ten);
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Branch(m.Float64LessThan(phi, ten), &body, &end);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
phi->ReplaceInput(1, m.Float64Add(phi, m.Float64Constant(0.5)));
|
|
|
|
m.Goto(&header);
|
|
|
|
|
2015-06-10 17:37:31 +00:00
|
|
|
m.Bind(&end);
|
2014-08-01 10:54:58 +00:00
|
|
|
m.Return(m.ChangeFloat64ToInt32(phi));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
CHECK_EQ(10, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-09 08:56:01 +00:00
|
|
|
TEST(RunSwitch1) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
int constant = 11223344;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel block0, block1, def, end;
|
|
|
|
RawMachineLabel* case_labels[] = {&block0, &block1};
|
2015-02-17 13:29:31 +00:00
|
|
|
int32_t case_values[] = {0, 1};
|
|
|
|
m.Switch(m.Int32Constant(0), &def, case_values, case_labels,
|
|
|
|
arraysize(case_labels));
|
2015-02-09 08:56:01 +00:00
|
|
|
m.Bind(&block0);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&block1);
|
|
|
|
m.Goto(&end);
|
2015-02-17 13:29:31 +00:00
|
|
|
m.Bind(&def);
|
|
|
|
m.Goto(&end);
|
2015-02-09 08:56:01 +00:00
|
|
|
m.Bind(&end);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunSwitch2) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2015-02-09 08:56:01 +00:00
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, blockc;
|
|
|
|
RawMachineLabel* case_labels[] = {&blocka, &blockb};
|
2015-02-17 13:29:31 +00:00
|
|
|
int32_t case_values[] = {std::numeric_limits<int32_t>::min(),
|
|
|
|
std::numeric_limits<int32_t>::max()};
|
|
|
|
m.Switch(m.Parameter(0), &blockc, case_values, case_labels,
|
|
|
|
arraysize(case_labels));
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(-1));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(1));
|
|
|
|
m.Bind(&blockc);
|
|
|
|
m.Return(m.Int32Constant(0));
|
|
|
|
|
|
|
|
CHECK_EQ(1, m.Call(std::numeric_limits<int32_t>::max()));
|
|
|
|
CHECK_EQ(-1, m.Call(std::numeric_limits<int32_t>::min()));
|
|
|
|
for (int i = -100; i < 100; i += 25) {
|
|
|
|
CHECK_EQ(0, m.Call(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunSwitch3) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2015-02-17 13:29:31 +00:00
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, blockc;
|
|
|
|
RawMachineLabel* case_labels[] = {&blocka, &blockb};
|
2015-02-17 13:29:31 +00:00
|
|
|
int32_t case_values[] = {std::numeric_limits<int32_t>::min() + 0,
|
|
|
|
std::numeric_limits<int32_t>::min() + 1};
|
|
|
|
m.Switch(m.Parameter(0), &blockc, case_values, case_labels,
|
|
|
|
arraysize(case_labels));
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(0));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(1));
|
|
|
|
m.Bind(&blockc);
|
|
|
|
m.Return(m.Int32Constant(2));
|
|
|
|
|
|
|
|
CHECK_EQ(0, m.Call(std::numeric_limits<int32_t>::min() + 0));
|
|
|
|
CHECK_EQ(1, m.Call(std::numeric_limits<int32_t>::min() + 1));
|
|
|
|
for (int i = -100; i < 100; i += 25) {
|
|
|
|
CHECK_EQ(2, m.Call(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunSwitch4) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2015-02-17 13:29:31 +00:00
|
|
|
|
|
|
|
const size_t kNumCases = 512;
|
|
|
|
const size_t kNumValues = kNumCases + 1;
|
|
|
|
int32_t values[kNumValues];
|
2015-02-09 08:56:01 +00:00
|
|
|
m.main_isolate()->random_number_generator()->NextBytes(values,
|
|
|
|
sizeof(values));
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel end, def;
|
2015-02-17 13:29:31 +00:00
|
|
|
int32_t case_values[kNumCases];
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel* case_labels[kNumCases];
|
2015-02-17 13:29:31 +00:00
|
|
|
Node* results[kNumValues];
|
2015-02-09 08:56:01 +00:00
|
|
|
for (size_t i = 0; i < kNumCases; ++i) {
|
2015-02-17 13:29:31 +00:00
|
|
|
case_values[i] = static_cast<int32_t>(i);
|
2015-11-30 11:28:50 +00:00
|
|
|
case_labels[i] =
|
|
|
|
new (m.main_zone()->New(sizeof(RawMachineLabel))) RawMachineLabel;
|
2015-02-09 08:56:01 +00:00
|
|
|
}
|
2015-02-17 13:29:31 +00:00
|
|
|
m.Switch(m.Parameter(0), &def, case_values, case_labels,
|
|
|
|
arraysize(case_labels));
|
2015-02-09 08:56:01 +00:00
|
|
|
for (size_t i = 0; i < kNumCases; ++i) {
|
2015-02-17 13:29:31 +00:00
|
|
|
m.Bind(case_labels[i]);
|
2015-02-09 08:56:01 +00:00
|
|
|
results[i] = m.Int32Constant(values[i]);
|
|
|
|
m.Goto(&end);
|
|
|
|
}
|
2015-02-17 13:29:31 +00:00
|
|
|
m.Bind(&def);
|
|
|
|
results[kNumCases] = m.Int32Constant(values[kNumCases]);
|
|
|
|
m.Goto(&end);
|
2015-02-09 08:56:01 +00:00
|
|
|
m.Bind(&end);
|
|
|
|
const int num_results = static_cast<int>(arraysize(results));
|
|
|
|
Node* phi =
|
2015-12-10 09:03:30 +00:00
|
|
|
m.AddNode(m.common()->Phi(MachineRepresentation::kWord32, num_results),
|
|
|
|
num_results, results);
|
2015-02-09 08:56:01 +00:00
|
|
|
m.Return(phi);
|
|
|
|
|
2015-02-17 13:29:31 +00:00
|
|
|
for (size_t i = 0; i < kNumValues; ++i) {
|
2015-02-09 08:56:01 +00:00
|
|
|
CHECK_EQ(values[i], m.Call(static_cast<int>(i)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunInt32AddP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Int32Add(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
2018-04-17 00:59:05 +00:00
|
|
|
int expected = static_cast<int32_t>(static_cast<uint32_t>(*i) +
|
|
|
|
static_cast<uint32_t>(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-23 10:22:06 +00:00
|
|
|
TEST(RunInt32AddAndWord32EqualP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
|
2014-10-23 10:22:06 +00:00
|
|
|
m.Return(m.Int32Add(m.Parameter(0),
|
|
|
|
m.Word32Equal(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t const expected =
|
|
|
|
bit_cast<int32_t>(bit_cast<uint32_t>(*i) + (*j == *k));
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
|
2014-10-23 10:22:06 +00:00
|
|
|
m.Return(m.Int32Add(m.Word32Equal(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t const expected =
|
|
|
|
bit_cast<int32_t>((*i == *j) + bit_cast<uint32_t>(*k));
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddAndWord32EqualImm) {
|
|
|
|
{
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
|
|
|
|
MachineType::Int32());
|
2014-10-23 10:22:06 +00:00
|
|
|
m.Return(m.Int32Add(m.Int32Constant(*i),
|
|
|
|
m.Word32Equal(m.Parameter(0), m.Parameter(1))));
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t const expected =
|
|
|
|
bit_cast<int32_t>(bit_cast<uint32_t>(*i) + (*j == *k));
|
|
|
|
CHECK_EQ(expected, m.Call(*j, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
|
|
|
|
MachineType::Int32());
|
2014-10-23 10:22:06 +00:00
|
|
|
m.Return(m.Int32Add(m.Word32Equal(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Parameter(1)));
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t const expected =
|
|
|
|
bit_cast<int32_t>((*i == *j) + bit_cast<uint32_t>(*k));
|
|
|
|
CHECK_EQ(expected, m.Call(*j, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddAndWord32NotEqualP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
|
2014-10-23 10:22:06 +00:00
|
|
|
m.Return(m.Int32Add(m.Parameter(0),
|
|
|
|
m.Word32NotEqual(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t const expected =
|
|
|
|
bit_cast<int32_t>(bit_cast<uint32_t>(*i) + (*j != *k));
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
|
2014-10-23 10:22:06 +00:00
|
|
|
m.Return(m.Int32Add(m.Word32NotEqual(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t const expected =
|
|
|
|
bit_cast<int32_t>((*i != *j) + bit_cast<uint32_t>(*k));
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddAndWord32NotEqualImm) {
|
|
|
|
{
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
|
|
|
|
MachineType::Int32());
|
2014-10-23 10:22:06 +00:00
|
|
|
m.Return(m.Int32Add(m.Int32Constant(*i),
|
|
|
|
m.Word32NotEqual(m.Parameter(0), m.Parameter(1))));
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t const expected =
|
|
|
|
bit_cast<int32_t>(bit_cast<uint32_t>(*i) + (*j != *k));
|
|
|
|
CHECK_EQ(expected, m.Call(*j, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
|
|
|
|
MachineType::Int32());
|
2014-10-23 10:22:06 +00:00
|
|
|
m.Return(m.Int32Add(m.Word32NotEqual(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Parameter(1)));
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t const expected =
|
|
|
|
bit_cast<int32_t>((*i != *j) + bit_cast<uint32_t>(*k));
|
|
|
|
CHECK_EQ(expected, m.Call(*j, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunInt32AddAndWord32SarP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Add(m.Parameter(0),
|
|
|
|
m.Word32Sar(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t expected = *i + (*j >> shift);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Add(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t expected = (*i >> shift) + *k;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddAndWord32ShlP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Add(m.Parameter(0),
|
|
|
|
m.Word32Shl(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t expected = *i + (*j << shift);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Add(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t expected = (*i << shift) + *k;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddAndWord32ShrP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Add(m.Parameter(0),
|
|
|
|
m.Word32Shr(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t expected = *i + (*j >> shift);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Add(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t expected = (*i >> shift) + *k;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddInBranch) {
|
|
|
|
static const int32_t constant = 987654321;
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Int32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32Equal(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i + *j) == 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Int32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32NotEqual(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i + *j) != 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i + *j) == 0 ? constant : 0 - constant;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32NotEqual(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i + *j) != 0 ? constant : 0 - constant;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<void> m;
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* shops[] = {m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr()};
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t n = 0; n < arraysize(shops); n++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Int32Add(m.Parameter(0),
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(shops[n], m.Parameter(1),
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Parameter(2))),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t right;
|
|
|
|
switch (shops[n]->opcode()) {
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
case IrOpcode::kWord32Sar:
|
|
|
|
right = *j >> shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shl:
|
|
|
|
right = *j << shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shr:
|
|
|
|
right = static_cast<uint32_t>(*j) >> shift;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int32_t expected = ((*i + right) == 0) ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddInComparison) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i + *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Constant(0), m.Int32Add(bt.param0, bt.param1)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i + *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i + *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Int32Add(m.Parameter(0), m.Int32Constant(*i)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*j + *i) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<void> m;
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* shops[] = {m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr()};
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t n = 0; n < arraysize(shops); n++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(
|
|
|
|
m.Int32Add(m.Parameter(0),
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(shops[n], m.Parameter(1), m.Parameter(2))),
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t right;
|
|
|
|
switch (shops[n]->opcode()) {
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
case IrOpcode::kWord32Sar:
|
|
|
|
right = *j >> shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shl:
|
|
|
|
right = *j << shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shr:
|
|
|
|
right = static_cast<uint32_t>(*j) >> shift;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int32_t expected = (*i + right) == 0;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32SubP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Return(m.Int32Sub(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2018-04-17 00:59:05 +00:00
|
|
|
uint32_t expected = *i - *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt32SubImm) {
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = *i - *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = *j - *i;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-08 11:44:46 +00:00
|
|
|
TEST(RunInt32SubImm2) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> r;
|
|
|
|
r.Return(r.Int32Sub(r.Int32Constant(-1), r.Int32Constant(0)));
|
|
|
|
CHECK_EQ(-1, r.Call());
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
TEST(RunInt32SubAndWord32SarP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Sub(m.Parameter(0),
|
|
|
|
m.Word32Sar(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = *i - (*j >> shift);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Sub(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(k) {
|
|
|
|
int32_t expected = (*i >> shift) - *k;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32SubAndWord32ShlP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Sub(m.Parameter(0),
|
|
|
|
m.Word32Shl(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = *i - (*j << shift);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Sub(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int32_t expected = (*i << shift) - *k;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32SubAndWord32ShrP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Sub(m.Parameter(0),
|
|
|
|
m.Word32Shr(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
2015-01-30 09:29:25 +00:00
|
|
|
uint32_t expected = *i - (*j >> shift);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Sub(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(k) {
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
2015-01-30 09:29:25 +00:00
|
|
|
uint32_t expected = (*i >> shift) - *k;
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32SubInBranch) {
|
|
|
|
static const int constant = 987654321;
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Int32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32Equal(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i - *j) == 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Int32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32NotEqual(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i - *j) != 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2015-01-30 09:29:25 +00:00
|
|
|
uint32_t expected = (*i - *j) == 0 ? constant : 0 - constant;
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32NotEqual(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i - *j) != 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<void> m;
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* shops[] = {m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr()};
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t n = 0; n < arraysize(shops); n++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Int32Sub(m.Parameter(0),
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(shops[n], m.Parameter(1),
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Parameter(2))),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t right;
|
|
|
|
switch (shops[n]->opcode()) {
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
case IrOpcode::kWord32Sar:
|
|
|
|
right = *j >> shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shl:
|
|
|
|
right = *j << shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shr:
|
|
|
|
right = static_cast<uint32_t>(*j) >> shift;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int32_t expected = ((*i - right) == 0) ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32SubInComparison) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i - *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Constant(0), m.Int32Sub(bt.param0, bt.param1)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i - *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i - *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*j - *i) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<void> m;
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* shops[] = {m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr()};
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t n = 0; n < arraysize(shops); n++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(
|
|
|
|
m.Int32Sub(m.Parameter(0),
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(shops[n], m.Parameter(1), m.Parameter(2))),
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t right;
|
|
|
|
switch (shops[n]->opcode()) {
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
case IrOpcode::kWord32Sar:
|
|
|
|
right = *j >> shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shl:
|
|
|
|
right = *j << shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shr:
|
|
|
|
right = static_cast<uint32_t>(*j) >> shift;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int32_t expected = (*i - right) == 0;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32MulP) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Int32Mul(bt.param0, bt.param1));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int expected = static_cast<int32_t>(*i * *j);
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(m.Int32Mul(bt.param0, bt.param1));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = *i * *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-14 11:57:06 +00:00
|
|
|
TEST(RunInt32MulHighP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Int32MulHigh(bt.param0, bt.param1));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected = static_cast<int32_t>(
|
|
|
|
(static_cast<int64_t>(*i) * static_cast<int64_t>(*j)) >> 32);
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunInt32MulImm) {
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Mul(m.Int32Constant(*i), m.Parameter(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = *i * *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant(*i)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = *j * *i;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt32MulAndInt32AddP) {
|
2014-10-01 10:47:14 +00:00
|
|
|
{
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-10-01 10:47:14 +00:00
|
|
|
int32_t p0 = *i;
|
|
|
|
int32_t p1 = *j;
|
|
|
|
m.Return(m.Int32Add(m.Int32Constant(p0),
|
|
|
|
m.Int32Mul(m.Parameter(0), m.Int32Constant(p1))));
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
int32_t p2 = *k;
|
|
|
|
int expected = p0 + static_cast<int32_t>(p1 * p2);
|
|
|
|
CHECK_EQ(expected, m.Call(p2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(
|
|
|
|
m.Int32Add(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
int32_t p0 = *i;
|
|
|
|
int32_t p1 = *j;
|
|
|
|
int32_t p2 = *k;
|
|
|
|
int expected = p0 + static_cast<int32_t>(p1 * p2);
|
|
|
|
CHECK_EQ(expected, m.Call(p0, p1, p2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(
|
|
|
|
m.Int32Add(m.Int32Mul(m.Parameter(0), m.Parameter(1)), m.Parameter(2)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
int32_t p0 = *i;
|
|
|
|
int32_t p1 = *j;
|
|
|
|
int32_t p2 = *k;
|
|
|
|
int expected = static_cast<int32_t>(p0 * p1) + p2;
|
|
|
|
CHECK_EQ(expected, m.Call(p0, p1, p2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Int32Add(m.Int32Constant(*i), m.Int32Mul(bt.param0, bt.param1)));
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
int32_t p0 = *j;
|
|
|
|
int32_t p1 = *k;
|
|
|
|
int expected = *i + static_cast<int32_t>(p0 * p1);
|
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32MulAndInt32SubP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(
|
|
|
|
m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
uint32_t p0 = *i;
|
|
|
|
int32_t p1 = *j;
|
|
|
|
int32_t p2 = *k;
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int expected = p0 - static_cast<uint32_t>(p1 * p2);
|
|
|
|
CHECK_EQ(expected, m.Call(p0, p1, p2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Int32Sub(m.Int32Constant(*i), m.Int32Mul(bt.param0, bt.param1)));
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
int32_t p0 = *j;
|
|
|
|
int32_t p1 = *k;
|
|
|
|
// Use uint32_t because signed overflow is UB in C.
|
|
|
|
int expected = *i - static_cast<uint32_t>(p0 * p1);
|
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-03 10:04:37 +00:00
|
|
|
TEST(RunUint32MulHighP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Uint32MulHigh(bt.param0, bt.param1));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = bit_cast<int32_t>(static_cast<uint32_t>(
|
|
|
|
(static_cast<uint64_t>(*i) * static_cast<uint64_t>(*j)) >> 32));
|
|
|
|
CHECK_EQ(expected, bt.call(bit_cast<int32_t>(*i), bit_cast<int32_t>(*j)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunInt32DivP) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Int32Div(bt.param0, bt.param1));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int p0 = *i;
|
|
|
|
int p1 = *j;
|
|
|
|
if (p1 != 0 && (static_cast<uint32_t>(p0) != 0x80000000 || p1 != -1)) {
|
|
|
|
int expected = static_cast<int32_t>(p0 / p1);
|
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Int32Add(bt.param0, m.Int32Div(bt.param0, bt.param1)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int p0 = *i;
|
|
|
|
int p1 = *j;
|
|
|
|
if (p1 != 0 && (static_cast<uint32_t>(p0) != 0x80000000 || p1 != -1)) {
|
|
|
|
int expected = static_cast<int32_t>(p0 + (p0 / p1));
|
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-01 10:39:11 +00:00
|
|
|
TEST(RunUint32DivP) {
|
2014-07-30 13:54:45 +00:00
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2014-10-01 10:39:11 +00:00
|
|
|
bt.AddReturn(m.Uint32Div(bt.param0, bt.param1));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t p0 = *i;
|
|
|
|
uint32_t p1 = *j;
|
|
|
|
if (p1 != 0) {
|
2015-01-30 09:29:25 +00:00
|
|
|
int32_t expected = bit_cast<int32_t>(p0 / p1);
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2014-10-01 10:39:11 +00:00
|
|
|
bt.AddReturn(m.Int32Add(bt.param0, m.Uint32Div(bt.param0, bt.param1)));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t p0 = *i;
|
|
|
|
uint32_t p1 = *j;
|
|
|
|
if (p1 != 0) {
|
2015-01-30 09:29:25 +00:00
|
|
|
int32_t expected = bit_cast<int32_t>(p0 + (p0 / p1));
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32ModP) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Int32Mod(bt.param0, bt.param1));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int p0 = *i;
|
|
|
|
int p1 = *j;
|
|
|
|
if (p1 != 0 && (static_cast<uint32_t>(p0) != 0x80000000 || p1 != -1)) {
|
|
|
|
int expected = static_cast<int32_t>(p0 % p1);
|
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Int32Add(bt.param0, m.Int32Mod(bt.param0, bt.param1)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int p0 = *i;
|
|
|
|
int p1 = *j;
|
|
|
|
if (p1 != 0 && (static_cast<uint32_t>(p0) != 0x80000000 || p1 != -1)) {
|
|
|
|
int expected = static_cast<int32_t>(p0 + (p0 % p1));
|
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-01 10:39:11 +00:00
|
|
|
TEST(RunUint32ModP) {
|
2014-07-30 13:54:45 +00:00
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-10-01 10:39:11 +00:00
|
|
|
bt.AddReturn(m.Uint32Mod(bt.param0, bt.param1));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t p0 = *i;
|
|
|
|
uint32_t p1 = *j;
|
|
|
|
if (p1 != 0) {
|
|
|
|
uint32_t expected = static_cast<uint32_t>(p0 % p1);
|
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-10-01 10:39:11 +00:00
|
|
|
bt.AddReturn(m.Int32Add(bt.param0, m.Uint32Mod(bt.param0, bt.param1)));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t p0 = *i;
|
|
|
|
uint32_t p1 = *j;
|
|
|
|
if (p1 != 0) {
|
|
|
|
uint32_t expected = static_cast<uint32_t>(p0 + (p0 % p1));
|
|
|
|
CHECK_EQ(expected, bt.call(p0, p1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32AndP) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Word32And(bt.param0, bt.param1));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2015-01-30 09:29:25 +00:00
|
|
|
int32_t expected = *i & *j;
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2018-08-13 13:36:15 +00:00
|
|
|
bt.AddReturn(m.Word32And(bt.param0, m.Word32BitwiseNot(bt.param1)));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2015-01-30 09:29:25 +00:00
|
|
|
int32_t expected = *i & ~(*j);
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2018-08-13 13:36:15 +00:00
|
|
|
bt.AddReturn(m.Word32And(m.Word32BitwiseNot(bt.param0), bt.param1));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2015-01-30 09:29:25 +00:00
|
|
|
int32_t expected = ~(*i) & *j;
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32AndAndWord32ShlP) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Word32Shl(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1F))));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
uint32_t expected = *i << (*j & 0x1F);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Word32Shl(bt.param0, m.Word32And(m.Int32Constant(0x1F), bt.param1)));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
uint32_t expected = *i << (0x1F & *j);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32AndAndWord32ShrP) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Word32Shr(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1F))));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
uint32_t expected = *i >> (*j & 0x1F);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Word32Shr(bt.param0, m.Word32And(m.Int32Constant(0x1F), bt.param1)));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
uint32_t expected = *i >> (0x1F & *j);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32AndAndWord32SarP) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Word32Sar(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1F))));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
int32_t expected = *i >> (*j & 0x1F);
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Word32Sar(bt.param0, m.Word32And(m.Int32Constant(0x1F), bt.param1)));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
int32_t expected = *i >> (0x1F & *j);
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32AndImm) {
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32And(m.Int32Constant(*i), m.Parameter(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *i & *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2018-08-13 13:36:15 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32And(m.Int32Constant(*i), m.Word32BitwiseNot(m.Parameter(0))));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *i & ~(*j);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32AndInBranch) {
|
|
|
|
static const int constant = 987654321;
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Int32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32Equal(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i & *j) == 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Int32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32NotEqual(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i & *j) != 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i & *j) == 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32NotEqual(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i & *j) != 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<void> m;
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* shops[] = {m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr()};
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t n = 0; n < arraysize(shops); n++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Word32And(m.Parameter(0),
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(shops[n], m.Parameter(1),
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Parameter(2))),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t right;
|
|
|
|
switch (shops[n]->opcode()) {
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
case IrOpcode::kWord32Sar:
|
|
|
|
right = *j >> shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shl:
|
|
|
|
right = *j << shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shr:
|
|
|
|
right = static_cast<uint32_t>(*j) >> shift;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int32_t expected = ((*i & right) == 0) ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32AndInComparison) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i & *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Constant(0), m.Word32And(bt.param0, bt.param1)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i & *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i & *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Word32And(m.Parameter(0), m.Int32Constant(*i)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*j & *i) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32OrP) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(m.Word32Or(bt.param0, bt.param1));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *i | *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2018-08-13 13:36:15 +00:00
|
|
|
bt.AddReturn(m.Word32Or(bt.param0, m.Word32BitwiseNot(bt.param1)));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *i | ~(*j);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2018-08-13 13:36:15 +00:00
|
|
|
bt.AddReturn(m.Word32Or(m.Word32BitwiseNot(bt.param0), bt.param1));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = ~(*i) | *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32OrImm) {
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *i | *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2018-08-13 13:36:15 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Or(m.Int32Constant(*i), m.Word32BitwiseNot(m.Parameter(0))));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *i | ~(*j);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32OrInBranch) {
|
|
|
|
static const int constant = 987654321;
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32Equal(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = (*i | *j) == 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32NotEqual(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = (*i | *j) != 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = (*i | *j) == 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32NotEqual(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = (*i | *j) != 0 ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<void> m;
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* shops[] = {m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr()};
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t n = 0; n < arraysize(shops); n++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Word32Or(m.Parameter(0),
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(shops[n], m.Parameter(1),
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Parameter(2))),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t right;
|
|
|
|
switch (shops[n]->opcode()) {
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
case IrOpcode::kWord32Sar:
|
|
|
|
right = *j >> shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shl:
|
|
|
|
right = *j << shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shr:
|
|
|
|
right = static_cast<uint32_t>(*j) >> shift;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int32_t expected = ((*i | right) == 0) ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32OrInComparison) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Int32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i | *j) == 0;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-01-30 09:29:25 +00:00
|
|
|
Int32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Constant(0), m.Word32Or(bt.param0, bt.param1)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
int32_t expected = (*i | *j) == 0;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i | *j) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Word32Or(m.Parameter(0), m.Int32Constant(*i)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*j | *i) == 0;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32XorP) {
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *i ^ *j;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(m.Word32Xor(bt.param0, bt.param1));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2015-01-30 09:29:25 +00:00
|
|
|
uint32_t expected = *i ^ *j;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2018-08-13 13:36:15 +00:00
|
|
|
bt.AddReturn(m.Word32Xor(bt.param0, m.Word32BitwiseNot(bt.param1)));
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected = *i ^ ~(*j);
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2018-08-13 13:36:15 +00:00
|
|
|
bt.AddReturn(m.Word32Xor(m.Word32BitwiseNot(bt.param0), bt.param1));
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected = ~(*i) ^ *j;
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2018-08-13 13:36:15 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Xor(m.Int32Constant(*i), m.Word32BitwiseNot(m.Parameter(0))));
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *i ^ ~(*j);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32XorInBranch) {
|
2014-08-14 09:19:54 +00:00
|
|
|
static const uint32_t constant = 987654321;
|
2014-07-30 13:54:45 +00:00
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32Equal(m.Word32Xor(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32NotEqual(m.Word32Xor(bt.param0, bt.param1), m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
bt.AddReturn(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(
|
|
|
|
m.Word32NotEqual(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-14 09:19:54 +00:00
|
|
|
uint32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<void> m;
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* shops[] = {m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr()};
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t n = 0; n < arraysize(shops); n++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Word32Equal(m.Word32Xor(m.Parameter(0),
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(shops[n], m.Parameter(1),
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Parameter(2))),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t right;
|
|
|
|
switch (shops[n]->opcode()) {
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
case IrOpcode::kWord32Sar:
|
|
|
|
right = *j >> shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shl:
|
|
|
|
right = *j << shift;
|
|
|
|
break;
|
|
|
|
case IrOpcode::kWord32Shr:
|
|
|
|
right = static_cast<uint32_t>(*j) >> shift;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int32_t expected = ((*i ^ right) == 0) ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32ShlP) {
|
|
|
|
{
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Shl(m.Parameter(0), m.Int32Constant(shift)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *j << shift;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(m.Word32Shl(bt.param0, bt.param1));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
uint32_t expected = *i << shift;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-18 11:10:01 +00:00
|
|
|
TEST(RunWord32ShlInComparison) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Uint32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Word32Shl(bt.param0, bt.param1), m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
|
|
|
uint32_t expected = 0 == (*i << shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Uint32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Constant(0), m.Word32Shl(bt.param0, bt.param1)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
|
|
|
uint32_t expected = 0 == (*i << shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-08-18 11:10:01 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Equal(m.Int32Constant(0),
|
|
|
|
m.Word32Shl(m.Parameter(0), m.Int32Constant(shift))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
uint32_t expected = 0 == (*i << shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-08-18 11:10:01 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Equal(m.Word32Shl(m.Parameter(0), m.Int32Constant(shift)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
uint32_t expected = 0 == (*i << shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunWord32ShrP) {
|
|
|
|
{
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint32_t expected = *j >> shift;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
bt.AddReturn(m.Word32Shr(bt.param0, bt.param1));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
uint32_t expected = *i >> shift;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(0x00010000u, bt.call(0x80000000, 15));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Reland "[turbofan][x64] Reduce compare-zero followed by flags-setting binop"
On IA architecture, arithmetic and shifting operations set the flags
according to the computation result.
subl rsi,0x1
REX.W movq rbx,[rbx+0x17]
cmpl rsi, 0 <-- TO BE REDUCED
jnz 0x3f54d2dcef0
==>
REX.W movq rbx,[rbx+0x17]
subl rsi,0x1
jnz 0x3f54d2dcef0
&
orl rdx,rbx
cmpl rdx,0x0 <-- TO BE REDUCED
jnz 0x3f54d22b0f5
==>
orl rdx,rbx
jnz 0x3f54d22b0f5
Bug: chromium:842497, chromium:842501
Change-Id: I4e2c40861b76ac3f508b01ee27249e85eab3222f
Reviewed-on: https://chromium-review.googlesource.com/1057351
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Kanghua Yu <kanghua.yu@intel.com>
Cr-Commit-Position: refs/heads/master@{#53171}
2018-05-14 16:28:37 +00:00
|
|
|
TEST(RunWordShiftInBranch) {
|
|
|
|
static const uint32_t constant = 987654321;
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
|
|
|
RawMachineLabel blocka, blockb;
|
|
|
|
m.Branch(m.Word32Equal(m.Word32Shl(m.Parameter(0), m.Int32Constant(shift)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
uint32_t expected = ((*i << shift) == 0) ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
|
|
|
RawMachineLabel blocka, blockb;
|
|
|
|
m.Branch(m.Word32Equal(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
uint32_t expected = ((*i >> shift) == 0) ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
|
|
|
RawMachineLabel blocka, blockb;
|
|
|
|
m.Branch(m.Word32Equal(m.Word32Sar(m.Parameter(0), m.Int32Constant(shift)),
|
|
|
|
m.Int32Constant(0)),
|
|
|
|
&blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(0 - constant));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
int32_t expected = ((*i >> shift) == 0) ? constant : 0 - constant;
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2014-08-18 11:10:01 +00:00
|
|
|
TEST(RunWord32ShrInComparison) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Uint32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Word32Shr(bt.param0, bt.param1), m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
|
|
|
uint32_t expected = 0 == (*i >> shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Uint32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Constant(0), m.Word32Shr(bt.param0, bt.param1)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
|
|
|
uint32_t expected = 0 == (*i >> shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-08-18 11:10:01 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Equal(m.Int32Constant(0),
|
|
|
|
m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
uint32_t expected = 0 == (*i >> shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-08-18 11:10:01 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Equal(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
uint32_t expected = 0 == (*i >> shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunWord32SarP) {
|
|
|
|
{
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_INT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Sar(m.Parameter(0), m.Int32Constant(shift)));
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected = *j >> shift;
|
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Word32Sar(bt.param0, bt.param1));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_INT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = *i >> shift;
|
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
|
|
|
}
|
|
|
|
}
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(bit_cast<int32_t>(0xFFFF0000), bt.call(0x80000000, 15));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-18 11:10:01 +00:00
|
|
|
TEST(RunWord32SarInComparison) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Word32Sar(bt.param0, bt.param1), m.Int32Constant(0)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_SHIFTS(shift) {
|
|
|
|
int32_t expected = 0 == (*i >> shift);
|
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Constant(0), m.Word32Sar(bt.param0, bt.param1)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_SHIFTS(shift) {
|
|
|
|
int32_t expected = 0 == (*i >> shift);
|
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_INT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-08-18 11:10:01 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Equal(m.Int32Constant(0),
|
|
|
|
m.Word32Sar(m.Parameter(0), m.Int32Constant(shift))));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
int32_t expected = 0 == (*i >> shift);
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_INT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-08-18 11:10:01 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Equal(m.Word32Sar(m.Parameter(0), m.Int32Constant(shift)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2015-01-30 09:29:25 +00:00
|
|
|
int32_t expected = 0 == (*i >> shift);
|
2014-08-18 11:10:01 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-14 09:07:58 +00:00
|
|
|
TEST(RunWord32RorP) {
|
|
|
|
{
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
|
2014-08-14 09:07:58 +00:00
|
|
|
m.Return(m.Word32Ror(m.Parameter(0), m.Int32Constant(shift)));
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int32_t expected = base::bits::RotateRight32(*j, shift);
|
2014-08-14 09:07:58 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-14 09:19:54 +00:00
|
|
|
Uint32BinopTester bt(&m);
|
2014-08-14 09:07:58 +00:00
|
|
|
bt.AddReturn(m.Word32Ror(bt.param0, bt.param1));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2017-08-11 11:22:28 +00:00
|
|
|
uint32_t expected = base::bits::RotateRight32(*i, shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-08-14 09:07:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-18 11:10:01 +00:00
|
|
|
TEST(RunWord32RorInComparison) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Uint32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Word32Ror(bt.param0, bt.param1), m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2017-08-11 11:22:28 +00:00
|
|
|
uint32_t expected = 0 == base::bits::RotateRight32(*i, shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Uint32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(
|
|
|
|
m.Word32Equal(m.Int32Constant(0), m.Word32Ror(bt.param0, bt.param1)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2017-08-11 11:22:28 +00:00
|
|
|
uint32_t expected = 0 == base::bits::RotateRight32(*i, shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, shift));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-08-18 11:10:01 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Equal(m.Int32Constant(0),
|
|
|
|
m.Word32Ror(m.Parameter(0), m.Int32Constant(shift))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2017-08-11 11:22:28 +00:00
|
|
|
uint32_t expected = 0 == base::bits::RotateRight32(*i, shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
2014-08-18 11:10:01 +00:00
|
|
|
m.Return(
|
|
|
|
m.Word32Equal(m.Word32Ror(m.Parameter(0), m.Int32Constant(shift)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2017-08-11 11:22:28 +00:00
|
|
|
uint32_t expected = 0 == base::bits::RotateRight32(*i, shift);
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
2014-08-18 11:10:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-13 13:36:15 +00:00
|
|
|
TEST(RunWord32BitwiseNotP) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2018-08-13 13:36:15 +00:00
|
|
|
m.Return(m.Word32BitwiseNot(m.Parameter(0)));
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int expected = ~(*i);
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32NegP) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Neg(m.Parameter(0)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
int expected = -*i;
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32EqualAndWord32SarP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Parameter(0),
|
|
|
|
m.Word32Sar(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = (*i == (*j >> shift));
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Int32(), MachineType::Uint32(), MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_INT32_INPUTS(k) {
|
|
|
|
int32_t expected = ((*i >> shift) == *k);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32EqualAndWord32ShlP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Parameter(0),
|
|
|
|
m.Word32Shl(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = (*i == (*j << shift));
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(k) {
|
|
|
|
int32_t expected = ((*i << shift) == *k);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunWord32EqualAndWord32ShrP) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Parameter(0),
|
|
|
|
m.Word32Shr(m.Parameter(1), m.Parameter(2))));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t expected = (*i == (*j >> shift));
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j, shift));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Word32Equal(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
2014-08-13 10:30:00 +00:00
|
|
|
FOR_UINT32_SHIFTS(shift) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_UINT32_INPUTS(k) {
|
|
|
|
int32_t expected = ((*i >> shift) == *k);
|
|
|
|
CHECK_EQ(expected, m.Call(*i, shift, *k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDeadNodes) {
|
|
|
|
for (int i = 0; true; i++) {
|
2018-01-16 09:26:02 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m_v;
|
|
|
|
RawMachineAssemblerTester<int32_t> m_i(MachineType::Int32());
|
|
|
|
RawMachineAssemblerTester<int32_t>& m = i == 5 ? m_i : m_v;
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
int constant = 0x55 + i;
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
m.Int32Constant(44);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
m.StringConstant("unused");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
m.NumberConstant(11.1);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
m.PointerConstant(&constant);
|
|
|
|
break;
|
|
|
|
case 4:
|
2015-12-10 09:03:30 +00:00
|
|
|
m.LoadFromPointer(&constant, MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
m.Parameter(0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
if (i != 5) {
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
} else {
|
|
|
|
CHECK_EQ(constant, m.Call(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDeadInt32Binops) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
2014-10-14 11:57:06 +00:00
|
|
|
const Operator* kOps[] = {
|
2014-11-03 10:04:37 +00:00
|
|
|
m.machine()->Word32And(), m.machine()->Word32Or(),
|
|
|
|
m.machine()->Word32Xor(), m.machine()->Word32Shl(),
|
|
|
|
m.machine()->Word32Shr(), m.machine()->Word32Sar(),
|
|
|
|
m.machine()->Word32Ror(), m.machine()->Word32Equal(),
|
|
|
|
m.machine()->Int32Add(), m.machine()->Int32Sub(),
|
|
|
|
m.machine()->Int32Mul(), m.machine()->Int32MulHigh(),
|
|
|
|
m.machine()->Int32Div(), m.machine()->Uint32Div(),
|
|
|
|
m.machine()->Int32Mod(), m.machine()->Uint32Mod(),
|
|
|
|
m.machine()->Uint32MulHigh(), m.machine()->Int32LessThan(),
|
|
|
|
m.machine()->Int32LessThanOrEqual(), m.machine()->Uint32LessThan(),
|
|
|
|
m.machine()->Uint32LessThanOrEqual()};
|
2014-10-14 11:57:06 +00:00
|
|
|
|
|
|
|
for (size_t i = 0; i < arraysize(kOps); ++i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
|
|
|
|
MachineType::Int32());
|
2014-10-14 11:57:06 +00:00
|
|
|
int32_t constant = static_cast<int32_t>(0x55555 + i);
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(kOps[i], m.Parameter(0), m.Parameter(1));
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
|
|
|
|
CHECK_EQ(constant, m.Call(1, 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat32Add) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
|
|
|
|
MachineType::Float32());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float32Add(m.Parameter(0), m.Parameter(1)));
|
2015-03-30 07:33:46 +00:00
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i + *j, m.Call(*i, *j)); }
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-30 07:33:46 +00:00
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat32Sub) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
|
|
|
|
MachineType::Float32());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float32Sub(m.Parameter(0), m.Parameter(1)));
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i - *j, m.Call(*i, *j)); }
|
2015-03-30 07:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-27 11:20:32 +00:00
|
|
|
TEST(RunFloat32Neg) {
|
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
|
2016-08-05 18:49:15 +00:00
|
|
|
m.Return(m.AddNode(m.machine()->Float32Neg(), m.Parameter(0)));
|
2016-05-27 11:20:32 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(-0.0f - *i, m.Call(*i)); }
|
|
|
|
}
|
2015-03-30 07:33:46 +00:00
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat32Mul) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
|
|
|
|
MachineType::Float32());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float32Mul(m.Parameter(0), m.Parameter(1)));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i * *j, m.Call(*i, *j)); }
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat32Div) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
|
|
|
|
MachineType::Float32());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float32Div(m.Parameter(0), m.Parameter(1)));
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i / *j, m.Call(*i, *j)); }
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64Add) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
|
|
|
|
MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Add(m.Parameter(0), m.Parameter(1)));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_DOUBLE_EQ(*i + *j, m.Call(*i, *j)); }
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64Sub) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
|
|
|
|
MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Sub(m.Parameter(0), m.Parameter(1)));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_DOUBLE_EQ(*i - *j, m.Call(*i, *j)); }
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-27 11:20:32 +00:00
|
|
|
TEST(RunFloat64Neg) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2016-08-05 18:49:15 +00:00
|
|
|
m.Return(m.AddNode(m.machine()->Float64Neg(), m.Parameter(0)));
|
2016-05-27 11:20:32 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_FLOAT_EQ(-0.0 - *i, m.Call(*i)); }
|
|
|
|
}
|
2015-11-02 19:19:14 +00:00
|
|
|
|
|
|
|
TEST(RunFloat64Mul) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
|
|
|
|
MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Mul(m.Parameter(0), m.Parameter(1)));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_DOUBLE_EQ(*i * *j, m.Call(*i, *j)); }
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64Div) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
|
|
|
|
MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Div(m.Parameter(0), m.Parameter(1)));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_DOUBLE_EQ(*i / *j, m.Call(*i, *j)); }
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64Mod) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
|
|
|
|
MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Mod(m.Parameter(0), m.Parameter(1)));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2017-10-19 12:21:50 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_DOUBLE_EQ(Modulo(*i, *j), m.Call(*i, *j)); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-30 07:33:46 +00:00
|
|
|
TEST(RunDeadFloat32Binops) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
const Operator* ops[] = {m.machine()->Float32Add(), m.machine()->Float32Sub(),
|
|
|
|
m.machine()->Float32Mul(), m.machine()->Float32Div(),
|
2017-10-13 16:33:03 +00:00
|
|
|
nullptr};
|
2015-03-30 07:33:46 +00:00
|
|
|
|
2017-10-13 16:33:03 +00:00
|
|
|
for (int i = 0; ops[i] != nullptr; i++) {
|
2015-03-30 07:33:46 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int constant = 0x53355 + i;
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(ops[i], m.Float32Constant(0.1f), m.Float32Constant(1.11f));
|
2015-03-30 07:33:46 +00:00
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunDeadFloat64Binops) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* ops[] = {m.machine()->Float64Add(), m.machine()->Float64Sub(),
|
|
|
|
m.machine()->Float64Mul(), m.machine()->Float64Div(),
|
2017-10-13 16:33:03 +00:00
|
|
|
m.machine()->Float64Mod(), nullptr};
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2017-10-13 16:33:03 +00:00
|
|
|
for (int i = 0; ops[i] != nullptr; i++) {
|
2014-07-30 13:54:45 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int constant = 0x53355 + i;
|
2015-09-23 09:08:15 +00:00
|
|
|
m.AddNode(ops[i], m.Float64Constant(0.1), m.Float64Constant(1.11));
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(constant));
|
|
|
|
CHECK_EQ(constant, m.Call());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-30 07:33:46 +00:00
|
|
|
TEST(RunFloat32AddP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float32BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Float32Add(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(pl) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(pr) { CHECK_FLOAT_EQ(*pl + *pr, bt.call(*pl, *pr)); }
|
2015-03-30 07:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunFloat64AddP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Float64Add(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(pr) { CHECK_DOUBLE_EQ(*pl + *pr, bt.call(*pl, *pr)); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-04 21:02:50 +00:00
|
|
|
TEST(RunFloat64MaxP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Float64Max(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
|
|
|
FOR_FLOAT64_INPUTS(pr) {
|
2016-08-22 13:50:23 +00:00
|
|
|
CHECK_DOUBLE_EQ(JSMax(*pl, *pr), bt.call(*pl, *pr));
|
2015-11-04 21:02:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64MinP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Float64Min(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
|
|
|
FOR_FLOAT64_INPUTS(pr) {
|
2016-08-22 13:50:23 +00:00
|
|
|
CHECK_DOUBLE_EQ(JSMin(*pl, *pr), bt.call(*pl, *pr));
|
2015-11-04 21:02:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-22 13:50:23 +00:00
|
|
|
TEST(RunFloat32Max) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Float32Max(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(pl) {
|
|
|
|
FOR_FLOAT32_INPUTS(pr) {
|
|
|
|
CHECK_FLOAT_EQ(JSMax(*pl, *pr), bt.call(*pl, *pr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunFloat32Min) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float32BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Float32Min(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(pl) {
|
|
|
|
FOR_FLOAT32_INPUTS(pr) {
|
|
|
|
CHECK_FLOAT_EQ(JSMin(*pl, *pr), bt.call(*pl, *pr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-04 21:02:50 +00:00
|
|
|
|
2016-12-06 10:16:13 +00:00
|
|
|
TEST(RunFloat64Max) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Float64Max(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
|
|
|
FOR_FLOAT64_INPUTS(pr) {
|
|
|
|
CHECK_DOUBLE_EQ(JSMax(*pl, *pr), bt.call(*pl, *pr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunFloat64Min) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
|
|
|
bt.AddReturn(m.Float64Min(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
|
|
|
FOR_FLOAT64_INPUTS(pr) {
|
|
|
|
CHECK_DOUBLE_EQ(JSMin(*pl, *pr), bt.call(*pl, *pr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-30 07:33:46 +00:00
|
|
|
TEST(RunFloat32SubP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float32BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Float32Sub(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(pl) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(pr) { CHECK_FLOAT_EQ(*pl - *pr, bt.call(*pl, *pr)); }
|
2015-03-30 07:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-07 07:34:55 +00:00
|
|
|
TEST(RunFloat32SubImm1) {
|
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float32Sub(m.Float32Constant(*i), m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i - *j, m.Call(*j)); }
|
2015-04-07 07:34:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat32SubImm2) {
|
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float32Sub(m.Parameter(0), m.Float32Constant(*i)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*j - *i, m.Call(*j)); }
|
2015-04-07 07:34:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat64SubImm1) {
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Sub(m.Float64Constant(*i), m.Parameter(0)));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_FLOAT_EQ(*i - *j, m.Call(*j)); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat64SubImm2) {
|
2014-07-30 13:54:45 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Sub(m.Parameter(0), m.Float64Constant(*i)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_FLOAT_EQ(*j - *i, m.Call(*j)); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat64SubP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
bt.AddReturn(m.Float64Sub(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
|
|
|
FOR_FLOAT64_INPUTS(pr) {
|
|
|
|
double expected = *pl - *pr;
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ(expected, bt.call(*pl, *pr));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-30 07:33:46 +00:00
|
|
|
TEST(RunFloat32MulP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float32BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Float32Mul(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(pl) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(pr) { CHECK_FLOAT_EQ(*pl * *pr, bt.call(*pl, *pr)); }
|
2015-03-30 07:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunFloat64MulP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Float64Mul(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
|
|
|
FOR_FLOAT64_INPUTS(pr) {
|
|
|
|
double expected = *pl * *pr;
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ(expected, bt.call(*pl, *pr));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat64MulAndFloat64Add1) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(
|
|
|
|
MachineType::Float64(), MachineType::Float64(), MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Add(m.Float64Mul(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
FOR_FLOAT64_INPUTS(j) {
|
|
|
|
FOR_FLOAT64_INPUTS(k) {
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ((*i * *j) + *k, m.Call(*i, *j, *k));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64MulAndFloat64Add2) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(
|
|
|
|
MachineType::Float64(), MachineType::Float64(), MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Add(m.Parameter(0),
|
|
|
|
m.Float64Mul(m.Parameter(1), m.Parameter(2))));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
FOR_FLOAT64_INPUTS(j) {
|
|
|
|
FOR_FLOAT64_INPUTS(k) {
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ(*i + (*j * *k), m.Call(*i, *j, *k));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat64MulAndFloat64Sub1) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(
|
|
|
|
MachineType::Float64(), MachineType::Float64(), MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Sub(m.Float64Mul(m.Parameter(0), m.Parameter(1)),
|
|
|
|
m.Parameter(2)));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
FOR_FLOAT64_INPUTS(j) {
|
|
|
|
FOR_FLOAT64_INPUTS(k) {
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ((*i * *j) - *k, m.Call(*i, *j, *k));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
TEST(RunFloat64MulAndFloat64Sub2) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(
|
|
|
|
MachineType::Float64(), MachineType::Float64(), MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Sub(m.Parameter(0),
|
|
|
|
m.Float64Mul(m.Parameter(1), m.Parameter(2))));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
FOR_FLOAT64_INPUTS(j) {
|
|
|
|
FOR_FLOAT64_INPUTS(k) {
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ(*i - (*j * *k), m.Call(*i, *j, *k));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64MulImm1) {
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Mul(m.Float64Constant(*i), m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_FLOAT_EQ(*i * *j, m.Call(*j)); }
|
2015-11-02 19:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64MulImm2) {
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.Float64Mul(m.Parameter(0), m.Float64Constant(*i)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_FLOAT_EQ(*j * *i, m.Call(*j)); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-30 07:33:46 +00:00
|
|
|
TEST(RunFloat32DivP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float32BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Float32Div(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(pl) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(pr) { CHECK_FLOAT_EQ(*pl / *pr, bt.call(*pl, *pr)); }
|
2015-03-30 07:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunFloat64DivP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Float64Div(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(pr) { CHECK_DOUBLE_EQ(*pl / *pr, bt.call(*pl, *pr)); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64ModP) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Float64BinopTester bt(&m);
|
|
|
|
|
|
|
|
bt.AddReturn(m.Float64Mod(bt.param0, bt.param1));
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2017-10-19 12:21:50 +00:00
|
|
|
FOR_FLOAT64_INPUTS(j) { CHECK_DOUBLE_EQ(Modulo(*i, *j), bt.call(*i, *j)); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-01 10:54:58 +00:00
|
|
|
TEST(RunChangeInt32ToFloat64_A) {
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t magic = 0x986234;
|
2015-11-02 19:19:14 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m;
|
|
|
|
m.Return(m.ChangeInt32ToFloat64(m.Int32Constant(magic)));
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ(static_cast<double>(magic), m.Call());
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-01 10:54:58 +00:00
|
|
|
TEST(RunChangeInt32ToFloat64_B) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Int32());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.ChangeInt32ToFloat64(m.Parameter(0)));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_INT32_INPUTS(i) { CHECK_DOUBLE_EQ(static_cast<double>(*i), m.Call(*i)); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-09 17:41:35 +00:00
|
|
|
TEST(RunChangeUint32ToFloat64) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Uint32());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
|
2014-09-30 10:24:11 +00:00
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_UINT32_INPUTS(i) { CHECK_DOUBLE_EQ(static_cast<double>(*i), m.Call(*i)); }
|
2014-09-30 10:24:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
[turbofan] Add the TruncateFloat32ToInt32 operator to turbofan.
The new operator converts a float32 input to int32 through truncation.
I provide implementations of the new operator for x64, ia32, arm,
arm64, mips, mips64, and x87. @v8-ppc-ports, can you please take care
of the ppc implementation?
R=titzer@chromium.org, v8-arm-ports@googlegroups.com, v8-mips-ports@googlegroups.com, weiliang.lin@intel.com
Review URL: https://codereview.chromium.org/1583323004
Cr-Commit-Position: refs/heads/master@{#33346}
2016-01-16 11:40:47 +00:00
|
|
|
TEST(RunTruncateFloat32ToInt32) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Float32());
|
|
|
|
m.Return(m.TruncateFloat32ToInt32(m.Parameter(0)));
|
2016-06-30 14:29:36 +00:00
|
|
|
// The upper bound is (INT32_MAX + 1), which is the lowest float-representable
|
|
|
|
// number above INT32_MAX which cannot be represented as int32.
|
|
|
|
float upper_bound = 2147483648.0f;
|
|
|
|
// We use INT32_MIN as a lower bound because (INT32_MIN - 1) is not
|
|
|
|
// representable as float, and no number between (INT32_MIN - 1) and INT32_MIN
|
|
|
|
// is.
|
|
|
|
float lower_bound = static_cast<float>(INT32_MIN);
|
[turbofan] Add the TruncateFloat32ToInt32 operator to turbofan.
The new operator converts a float32 input to int32 through truncation.
I provide implementations of the new operator for x64, ia32, arm,
arm64, mips, mips64, and x87. @v8-ppc-ports, can you please take care
of the ppc implementation?
R=titzer@chromium.org, v8-arm-ports@googlegroups.com, v8-mips-ports@googlegroups.com, weiliang.lin@intel.com
Review URL: https://codereview.chromium.org/1583323004
Cr-Commit-Position: refs/heads/master@{#33346}
2016-01-16 11:40:47 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2016-06-30 14:29:36 +00:00
|
|
|
if (*i < upper_bound && *i >= lower_bound) {
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_FLOAT_EQ(static_cast<int32_t>(*i), m.Call(*i));
|
[turbofan] Add the TruncateFloat32ToInt32 operator to turbofan.
The new operator converts a float32 input to int32 through truncation.
I provide implementations of the new operator for x64, ia32, arm,
arm64, mips, mips64, and x87. @v8-ppc-ports, can you please take care
of the ppc implementation?
R=titzer@chromium.org, v8-arm-ports@googlegroups.com, v8-mips-ports@googlegroups.com, weiliang.lin@intel.com
Review URL: https://codereview.chromium.org/1583323004
Cr-Commit-Position: refs/heads/master@{#33346}
2016-01-16 11:40:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-06 18:08:54 +00:00
|
|
|
TEST(RunTruncateFloat32ToUint32) {
|
|
|
|
BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float32());
|
|
|
|
m.Return(m.TruncateFloat32ToUint32(m.Parameter(0)));
|
2016-06-30 14:29:36 +00:00
|
|
|
// The upper bound is (UINT32_MAX + 1), which is the lowest
|
|
|
|
// float-representable number above UINT32_MAX which cannot be represented as
|
|
|
|
// uint32.
|
|
|
|
double upper_bound = 4294967296.0f;
|
|
|
|
double lower_bound = -1.0f;
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
volatile float input = static_cast<float>(*i);
|
|
|
|
if (input < upper_bound) {
|
|
|
|
CHECK_EQ(static_cast<uint32_t>(input), m.Call(input));
|
2016-02-06 18:08:54 +00:00
|
|
|
}
|
|
|
|
}
|
2016-06-30 14:29:36 +00:00
|
|
|
FOR_FLOAT32_INPUTS(j) {
|
|
|
|
if ((*j < upper_bound) && (*j > lower_bound)) {
|
|
|
|
CHECK_FLOAT_EQ(static_cast<uint32_t>(*j), m.Call(*j));
|
2016-02-06 18:08:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-01 10:54:58 +00:00
|
|
|
TEST(RunChangeFloat64ToInt32_A) {
|
2015-11-02 19:19:14 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m;
|
|
|
|
double magic = 11.1;
|
|
|
|
m.Return(m.ChangeFloat64ToInt32(m.Float64Constant(magic)));
|
|
|
|
CHECK_EQ(static_cast<int32_t>(magic), m.Call());
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-01 10:54:58 +00:00
|
|
|
TEST(RunChangeFloat64ToInt32_B) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Float64());
|
2015-11-02 19:19:14 +00:00
|
|
|
m.Return(m.ChangeFloat64ToInt32(m.Parameter(0)));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
// Note we don't check fractional inputs, or inputs outside the range of
|
|
|
|
// int32, because these Convert operators really should be Change operators.
|
|
|
|
FOR_INT32_INPUTS(i) { CHECK_EQ(*i, m.Call(static_cast<double>(*i))); }
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-11-02 19:19:14 +00:00
|
|
|
for (int32_t n = 1; n < 31; ++n) {
|
|
|
|
CHECK_EQ(1 << n, m.Call(static_cast<double>(1 << n)));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
|
2014-07-31 11:45:22 +00:00
|
|
|
for (int32_t n = 1; n < 31; ++n) {
|
2015-11-02 19:19:14 +00:00
|
|
|
CHECK_EQ(3 << n, m.Call(static_cast<double>(3 << n)));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-09 17:41:35 +00:00
|
|
|
TEST(RunChangeFloat64ToUint32) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float64());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.ChangeFloat64ToUint32(m.Parameter(0)));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2014-07-31 11:45:22 +00:00
|
|
|
{
|
2015-11-09 17:41:35 +00:00
|
|
|
FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, m.Call(static_cast<double>(*i))); }
|
2014-07-31 11:45:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check various powers of 2.
|
|
|
|
for (int32_t n = 1; n < 31; ++n) {
|
2015-11-09 17:41:35 +00:00
|
|
|
{ CHECK_EQ(1u << n, m.Call(static_cast<double>(1u << n))); }
|
2014-07-31 11:45:22 +00:00
|
|
|
|
2015-11-09 17:41:35 +00:00
|
|
|
{ CHECK_EQ(3u << n, m.Call(static_cast<double>(3u << n))); }
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
2014-07-31 11:45:22 +00:00
|
|
|
// Note we don't check fractional inputs, because these Convert operators
|
|
|
|
// really should be Change operators.
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-09 17:41:35 +00:00
|
|
|
TEST(RunTruncateFloat64ToFloat32) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float64());
|
2014-10-13 07:12:57 +00:00
|
|
|
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
|
2014-10-13 07:12:57 +00:00
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_FLOAT_EQ(DoubleToFloat32(*i), m.Call(*i)); }
|
2014-10-13 07:12:57 +00:00
|
|
|
}
|
|
|
|
|
2016-03-16 10:56:29 +00:00
|
|
|
uint64_t ToInt64(uint32_t low, uint32_t high) {
|
|
|
|
return (static_cast<uint64_t>(high) << 32) | static_cast<uint64_t>(low);
|
2016-03-14 15:33:15 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 14:43:28 +00:00
|
|
|
#if V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_X87
|
2016-03-14 15:33:15 +00:00
|
|
|
TEST(RunInt32PairAdd) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
2016-03-16 10:56:29 +00:00
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
2016-03-14 15:33:15 +00:00
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairAdd = m.Int32PairAdd(m.Parameter(0), m.Parameter(1), m.Parameter(2),
|
|
|
|
m.Parameter(3));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairAdd));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairAdd));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
2016-03-16 10:56:29 +00:00
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
FOR_UINT64_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-03-16 10:56:29 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(*j & 0xFFFFFFFF),
|
2016-03-16 10:56:29 +00:00
|
|
|
static_cast<uint32_t>(*j >> 32));
|
2016-03-14 15:33:15 +00:00
|
|
|
CHECK_EQ(*i + *j, ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:21:03 +00:00
|
|
|
TEST(RunInt32PairAddUseOnlyHighWord) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
m.Return(m.Projection(1, m.Int32PairAdd(m.Parameter(0), m.Parameter(1),
|
|
|
|
m.Parameter(2), m.Parameter(3))));
|
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
FOR_UINT64_INPUTS(j) {
|
2016-11-10 10:02:44 +00:00
|
|
|
CHECK_EQ(
|
|
|
|
static_cast<uint32_t>((*i + *j) >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(*j & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*j >> 32))));
|
2016-10-19 16:21:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-14 15:33:15 +00:00
|
|
|
void TestInt32PairAddWithSharedInput(int a, int b, int c, int d) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairAdd = m.Int32PairAdd(m.Parameter(a), m.Parameter(b), m.Parameter(c),
|
|
|
|
m.Parameter(d));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairAdd));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairAdd));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
m.Call(*i, *j);
|
|
|
|
uint32_t inputs[] = {*i, *j};
|
|
|
|
CHECK_EQ(ToInt64(inputs[a], inputs[b]) + ToInt64(inputs[c], inputs[d]),
|
|
|
|
ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt32PairAddWithSharedInput) {
|
|
|
|
TestInt32PairAddWithSharedInput(0, 0, 0, 0);
|
|
|
|
TestInt32PairAddWithSharedInput(1, 0, 0, 0);
|
|
|
|
TestInt32PairAddWithSharedInput(0, 1, 0, 0);
|
|
|
|
TestInt32PairAddWithSharedInput(0, 0, 1, 0);
|
|
|
|
TestInt32PairAddWithSharedInput(0, 0, 0, 1);
|
|
|
|
TestInt32PairAddWithSharedInput(1, 1, 0, 0);
|
|
|
|
}
|
2016-03-14 17:22:27 +00:00
|
|
|
|
2016-03-16 10:56:29 +00:00
|
|
|
TEST(RunInt32PairSub) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairSub = m.Int32PairSub(m.Parameter(0), m.Parameter(1), m.Parameter(2),
|
|
|
|
m.Parameter(3));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairSub));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairSub));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
FOR_UINT64_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-03-16 10:56:29 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(*j & 0xFFFFFFFF),
|
2016-03-16 10:56:29 +00:00
|
|
|
static_cast<uint32_t>(*j >> 32));
|
|
|
|
CHECK_EQ(*i - *j, ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:21:03 +00:00
|
|
|
TEST(RunInt32PairSubUseOnlyHighWord) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
m.Return(m.Projection(1, m.Int32PairSub(m.Parameter(0), m.Parameter(1),
|
|
|
|
m.Parameter(2), m.Parameter(3))));
|
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
FOR_UINT64_INPUTS(j) {
|
2016-11-10 10:02:44 +00:00
|
|
|
CHECK_EQ(
|
|
|
|
static_cast<uint32_t>((*i - *j) >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(*j & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*j >> 32))));
|
2016-10-19 16:21:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-16 10:56:29 +00:00
|
|
|
void TestInt32PairSubWithSharedInput(int a, int b, int c, int d) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairSub = m.Int32PairSub(m.Parameter(a), m.Parameter(b), m.Parameter(c),
|
|
|
|
m.Parameter(d));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairSub));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairSub));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
m.Call(*i, *j);
|
|
|
|
uint32_t inputs[] = {*i, *j};
|
|
|
|
CHECK_EQ(ToInt64(inputs[a], inputs[b]) - ToInt64(inputs[c], inputs[d]),
|
|
|
|
ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt32PairSubWithSharedInput) {
|
|
|
|
TestInt32PairSubWithSharedInput(0, 0, 0, 0);
|
|
|
|
TestInt32PairSubWithSharedInput(1, 0, 0, 0);
|
|
|
|
TestInt32PairSubWithSharedInput(0, 1, 0, 0);
|
|
|
|
TestInt32PairSubWithSharedInput(0, 0, 1, 0);
|
|
|
|
TestInt32PairSubWithSharedInput(0, 0, 0, 1);
|
|
|
|
TestInt32PairSubWithSharedInput(1, 1, 0, 0);
|
|
|
|
}
|
|
|
|
|
2016-03-30 10:39:04 +00:00
|
|
|
TEST(RunInt32PairMul) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairMul = m.Int32PairMul(m.Parameter(0), m.Parameter(1), m.Parameter(2),
|
|
|
|
m.Parameter(3));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairMul));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairMul));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
FOR_UINT64_INPUTS(j) {
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-03-30 10:39:04 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(*j & 0xFFFFFFFF),
|
2016-03-30 10:39:04 +00:00
|
|
|
static_cast<uint32_t>(*j >> 32));
|
|
|
|
CHECK_EQ(*i * *j, ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:21:03 +00:00
|
|
|
TEST(RunInt32PairMulUseOnlyHighWord) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
m.Return(m.Projection(1, m.Int32PairMul(m.Parameter(0), m.Parameter(1),
|
|
|
|
m.Parameter(2), m.Parameter(3))));
|
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
FOR_UINT64_INPUTS(j) {
|
2016-11-10 10:02:44 +00:00
|
|
|
CHECK_EQ(
|
|
|
|
static_cast<uint32_t>((*i * *j) >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(*j & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*j >> 32))));
|
2016-10-19 16:21:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-30 10:39:04 +00:00
|
|
|
void TestInt32PairMulWithSharedInput(int a, int b, int c, int d) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairMul = m.Int32PairMul(m.Parameter(a), m.Parameter(b), m.Parameter(c),
|
|
|
|
m.Parameter(d));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairMul));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairMul));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
m.Call(*i, *j);
|
|
|
|
uint32_t inputs[] = {*i, *j};
|
|
|
|
CHECK_EQ(ToInt64(inputs[a], inputs[b]) * ToInt64(inputs[c], inputs[d]),
|
|
|
|
ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt32PairMulWithSharedInput) {
|
|
|
|
TestInt32PairMulWithSharedInput(0, 0, 0, 0);
|
|
|
|
TestInt32PairMulWithSharedInput(1, 0, 0, 0);
|
|
|
|
TestInt32PairMulWithSharedInput(0, 1, 0, 0);
|
|
|
|
TestInt32PairMulWithSharedInput(0, 0, 1, 0);
|
|
|
|
TestInt32PairMulWithSharedInput(0, 0, 0, 1);
|
|
|
|
TestInt32PairMulWithSharedInput(1, 1, 0, 0);
|
|
|
|
TestInt32PairMulWithSharedInput(0, 1, 1, 0);
|
|
|
|
}
|
|
|
|
|
2016-03-14 17:22:27 +00:00
|
|
|
TEST(RunWord32PairShl) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
2016-10-19 16:21:03 +00:00
|
|
|
Node* PairShl =
|
2016-03-14 17:22:27 +00:00
|
|
|
m.Word32PairShl(m.Parameter(0), m.Parameter(1), m.Parameter(2));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
2016-10-19 16:21:03 +00:00
|
|
|
m.Projection(0, PairShl));
|
2016-03-14 17:22:27 +00:00
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
2016-10-19 16:21:03 +00:00
|
|
|
m.Projection(1, PairShl));
|
2016-03-14 17:22:27 +00:00
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
2016-03-16 10:56:29 +00:00
|
|
|
FOR_UINT64_INPUTS(i) {
|
2016-03-14 17:22:27 +00:00
|
|
|
for (uint32_t j = 0; j < 64; j++) {
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-03-14 17:22:27 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32), j);
|
|
|
|
CHECK_EQ(*i << j, ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:21:03 +00:00
|
|
|
TEST(RunWord32PairShlUseOnlyHighWord) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
|
|
|
|
|
|
|
m.Return(m.Projection(
|
|
|
|
1, m.Word32PairShl(m.Parameter(0), m.Parameter(1), m.Parameter(2))));
|
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
for (uint32_t j = 0; j < 64; j++) {
|
2016-11-10 10:02:44 +00:00
|
|
|
CHECK_EQ(
|
|
|
|
static_cast<uint32_t>((*i << j) >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32), j)));
|
2016-10-19 16:21:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-14 17:22:27 +00:00
|
|
|
void TestWord32PairShlWithSharedInput(int a, int b) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
|
|
|
|
MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairAdd =
|
|
|
|
m.Word32PairShl(m.Parameter(a), m.Parameter(b), m.Parameter(1));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairAdd));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairAdd));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
for (uint32_t j = 0; j < 64; j++) {
|
|
|
|
m.Call(*i, j);
|
|
|
|
uint32_t inputs[] = {*i, j};
|
|
|
|
CHECK_EQ(ToInt64(inputs[a], inputs[b]) << j, ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunWord32PairShlWithSharedInput) {
|
|
|
|
TestWord32PairShlWithSharedInput(0, 0);
|
|
|
|
TestWord32PairShlWithSharedInput(0, 1);
|
|
|
|
TestWord32PairShlWithSharedInput(1, 0);
|
|
|
|
TestWord32PairShlWithSharedInput(1, 1);
|
|
|
|
}
|
|
|
|
|
2016-04-06 14:43:28 +00:00
|
|
|
TEST(RunWord32PairShr) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairAdd =
|
|
|
|
m.Word32PairShr(m.Parameter(0), m.Parameter(1), m.Parameter(2));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairAdd));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairAdd));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
for (uint32_t j = 0; j < 64; j++) {
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-04-06 14:43:28 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32), j);
|
|
|
|
CHECK_EQ(*i >> j, ToInt64(low, high));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:21:03 +00:00
|
|
|
TEST(RunWord32PairShrUseOnlyHighWord) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
|
|
|
|
|
|
|
m.Return(m.Projection(
|
|
|
|
1, m.Word32PairShr(m.Parameter(0), m.Parameter(1), m.Parameter(2))));
|
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
for (uint32_t j = 0; j < 64; j++) {
|
2016-11-10 10:02:44 +00:00
|
|
|
CHECK_EQ(
|
|
|
|
static_cast<uint32_t>((*i >> j) >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32), j)));
|
2016-10-19 16:21:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-06 14:43:28 +00:00
|
|
|
TEST(RunWord32PairSar) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
|
|
|
|
|
|
|
uint32_t high;
|
|
|
|
uint32_t low;
|
|
|
|
|
|
|
|
Node* PairAdd =
|
|
|
|
m.Word32PairSar(m.Parameter(0), m.Parameter(1), m.Parameter(2));
|
|
|
|
|
|
|
|
m.StoreToPointer(&low, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(0, PairAdd));
|
|
|
|
m.StoreToPointer(&high, MachineRepresentation::kWord32,
|
|
|
|
m.Projection(1, PairAdd));
|
|
|
|
m.Return(m.Int32Constant(74));
|
|
|
|
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
for (uint32_t j = 0; j < 64; j++) {
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-04-06 14:43:28 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32), j);
|
2016-11-10 10:02:44 +00:00
|
|
|
CHECK_EQ(*i >> j, static_cast<int64_t>(ToInt64(low, high)));
|
2016-04-06 14:43:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:21:03 +00:00
|
|
|
TEST(RunWord32PairSarUseOnlyHighWord) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(
|
|
|
|
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
|
|
|
|
|
|
|
|
m.Return(m.Projection(
|
|
|
|
1, m.Word32PairSar(m.Parameter(0), m.Parameter(1), m.Parameter(2))));
|
|
|
|
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
for (uint32_t j = 0; j < 64; j++) {
|
2016-11-10 10:02:44 +00:00
|
|
|
CHECK_EQ(
|
|
|
|
static_cast<uint32_t>((*i >> j) >> 32),
|
2017-12-02 00:30:37 +00:00
|
|
|
static_cast<uint32_t>(m.Call(static_cast<uint32_t>(*i & 0xFFFFFFFF),
|
2016-11-10 10:02:44 +00:00
|
|
|
static_cast<uint32_t>(*i >> 32), j)));
|
2016-10-19 16:21:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-14 15:33:15 +00:00
|
|
|
#endif
|
2014-10-13 07:12:57 +00:00
|
|
|
|
2014-08-01 10:54:58 +00:00
|
|
|
TEST(RunDeadChangeFloat64ToInt32) {
|
2014-07-30 13:54:45 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2017-12-02 00:30:37 +00:00
|
|
|
const int magic = 0x88ABCDA4;
|
2014-08-01 10:54:58 +00:00
|
|
|
m.ChangeFloat64ToInt32(m.Float64Constant(999.78));
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(magic));
|
|
|
|
CHECK_EQ(magic, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-01 10:54:58 +00:00
|
|
|
TEST(RunDeadChangeInt32ToFloat64) {
|
2014-07-30 13:54:45 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2017-12-02 00:30:37 +00:00
|
|
|
const int magic = 0x8834ABCD;
|
2014-08-01 10:54:58 +00:00
|
|
|
m.ChangeInt32ToFloat64(m.Int32Constant(magic - 6888));
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(magic));
|
|
|
|
CHECK_EQ(magic, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunLoopPhiInduction2) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
int false_val = 0x10777;
|
|
|
|
|
|
|
|
// x = false_val; while(false) { x++; } return x;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* false_node = m.Int32Constant(false_val);
|
|
|
|
m.Goto(&header);
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kWord32, false_node, false_node);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Int32Constant(0), &body, &end);
|
|
|
|
m.Bind(&body);
|
|
|
|
Node* add = m.Int32Add(phi, m.Int32Constant(1));
|
|
|
|
phi->ReplaceInput(1, add);
|
|
|
|
m.Goto(&header);
|
|
|
|
m.Bind(&end);
|
|
|
|
m.Return(phi);
|
|
|
|
|
|
|
|
CHECK_EQ(false_val, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-30 07:33:46 +00:00
|
|
|
TEST(RunFloatDiamond) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
const int magic = 99645;
|
|
|
|
float buffer = 0.1f;
|
|
|
|
float constant = 99.99f;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, end;
|
2015-03-30 07:33:46 +00:00
|
|
|
Node* k1 = m.Float32Constant(constant);
|
|
|
|
Node* k2 = m.Float32Constant(0 - constant);
|
|
|
|
m.Branch(m.Int32Constant(0), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&end);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kFloat32, k2, k1);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kFloat32, m.PointerConstant(&buffer),
|
2015-12-10 09:03:30 +00:00
|
|
|
m.IntPtrConstant(0), phi, kNoWriteBarrier);
|
2015-03-30 07:33:46 +00:00
|
|
|
m.Return(m.Int32Constant(magic));
|
|
|
|
|
|
|
|
CHECK_EQ(magic, m.Call());
|
|
|
|
CHECK(constant == buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunDoubleDiamond) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
const int magic = 99645;
|
|
|
|
double buffer = 0.1;
|
|
|
|
double constant = 99.99;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* k1 = m.Float64Constant(constant);
|
|
|
|
Node* k2 = m.Float64Constant(0 - constant);
|
|
|
|
m.Branch(m.Int32Constant(0), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&end);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kFloat64, k2, k1);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kFloat64, m.PointerConstant(&buffer),
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Int32Constant(0), phi, kNoWriteBarrier);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(magic));
|
|
|
|
|
|
|
|
CHECK_EQ(magic, m.Call());
|
|
|
|
CHECK_EQ(constant, buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunRefDiamond) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
const int magic = 99644;
|
|
|
|
Handle<String> rexpected =
|
|
|
|
CcTest::i_isolate()->factory()->InternalizeUtf8String("A");
|
|
|
|
String* buffer;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* k1 = m.StringConstant("A");
|
|
|
|
Node* k2 = m.StringConstant("B");
|
|
|
|
m.Branch(m.Int32Constant(0), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&end);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kTagged, k2, k1);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kTagged, m.PointerConstant(&buffer),
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Int32Constant(0), phi, kNoWriteBarrier);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(magic));
|
|
|
|
|
|
|
|
CHECK_EQ(magic, m.Call());
|
|
|
|
CHECK(rexpected->SameValue(buffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDoubleRefDiamond) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
const int magic = 99648;
|
|
|
|
double dbuffer = 0.1;
|
|
|
|
double dconstant = 99.99;
|
|
|
|
Handle<String> rexpected =
|
|
|
|
CcTest::i_isolate()->factory()->InternalizeUtf8String("AX");
|
|
|
|
String* rbuffer;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* d1 = m.Float64Constant(dconstant);
|
|
|
|
Node* d2 = m.Float64Constant(0 - dconstant);
|
|
|
|
Node* r1 = m.StringConstant("AX");
|
|
|
|
Node* r2 = m.StringConstant("BX");
|
|
|
|
m.Branch(m.Int32Constant(0), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&end);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* dphi = m.Phi(MachineRepresentation::kFloat64, d2, d1);
|
|
|
|
Node* rphi = m.Phi(MachineRepresentation::kTagged, r2, r1);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kFloat64, m.PointerConstant(&dbuffer),
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Int32Constant(0), dphi, kNoWriteBarrier);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kTagged, m.PointerConstant(&rbuffer),
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Int32Constant(0), rphi, kNoWriteBarrier);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(magic));
|
|
|
|
|
|
|
|
CHECK_EQ(magic, m.Call());
|
|
|
|
CHECK_EQ(dconstant, dbuffer);
|
|
|
|
CHECK(rexpected->SameValue(rbuffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDoubleRefDoubleDiamond) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
const int magic = 99649;
|
|
|
|
double dbuffer = 0.1;
|
|
|
|
double dconstant = 99.997;
|
|
|
|
Handle<String> rexpected =
|
|
|
|
CcTest::i_isolate()->factory()->InternalizeUtf8String("AD");
|
|
|
|
String* rbuffer;
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, mid, blockd, blocke, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* d1 = m.Float64Constant(dconstant);
|
|
|
|
Node* d2 = m.Float64Constant(0 - dconstant);
|
|
|
|
Node* r1 = m.StringConstant("AD");
|
|
|
|
Node* r2 = m.StringConstant("BD");
|
|
|
|
m.Branch(m.Int32Constant(0), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Goto(&mid);
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Goto(&mid);
|
|
|
|
m.Bind(&mid);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* dphi1 = m.Phi(MachineRepresentation::kFloat64, d2, d1);
|
|
|
|
Node* rphi1 = m.Phi(MachineRepresentation::kTagged, r2, r1);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Int32Constant(0), &blockd, &blocke);
|
|
|
|
|
|
|
|
m.Bind(&blockd);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&blocke);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&end);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* dphi2 = m.Phi(MachineRepresentation::kFloat64, d1, dphi1);
|
|
|
|
Node* rphi2 = m.Phi(MachineRepresentation::kTagged, r1, rphi1);
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kFloat64, m.PointerConstant(&dbuffer),
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Int32Constant(0), dphi2, kNoWriteBarrier);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kTagged, m.PointerConstant(&rbuffer),
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Int32Constant(0), rphi2, kNoWriteBarrier);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(magic));
|
|
|
|
|
|
|
|
CHECK_EQ(magic, m.Call());
|
|
|
|
CHECK_EQ(dconstant, dbuffer);
|
|
|
|
CHECK(rexpected->SameValue(rbuffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunDoubleLoopPhi) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
int magic = 99773;
|
|
|
|
double buffer = 0.99;
|
|
|
|
double dconstant = 777.1;
|
|
|
|
|
|
|
|
Node* zero = m.Int32Constant(0);
|
|
|
|
Node* dk = m.Float64Constant(dconstant);
|
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kFloat64, dk, dk);
|
2014-07-30 13:54:45 +00:00
|
|
|
phi->ReplaceInput(1, phi);
|
|
|
|
m.Branch(zero, &body, &end);
|
|
|
|
m.Bind(&body);
|
|
|
|
m.Goto(&header);
|
|
|
|
m.Bind(&end);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kFloat64, m.PointerConstant(&buffer),
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Int32Constant(0), phi, kNoWriteBarrier);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Int32Constant(magic));
|
|
|
|
|
|
|
|
CHECK_EQ(magic, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunCountToTenAccRaw) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
Node* zero = m.Int32Constant(0);
|
|
|
|
Node* ten = m.Int32Constant(10);
|
|
|
|
Node* one = m.Int32Constant(1);
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, body_cont, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* i = m.Phi(MachineRepresentation::kWord32, zero, zero);
|
|
|
|
Node* j = m.Phi(MachineRepresentation::kWord32, zero, zero);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Goto(&body);
|
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
Node* next_i = m.Int32Add(i, one);
|
|
|
|
Node* next_j = m.Int32Add(j, one);
|
|
|
|
m.Branch(m.Word32Equal(next_i, ten), &end, &body_cont);
|
|
|
|
|
|
|
|
m.Bind(&body_cont);
|
|
|
|
i->ReplaceInput(1, next_i);
|
|
|
|
j->ReplaceInput(1, next_j);
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&end);
|
|
|
|
m.Return(ten);
|
|
|
|
|
|
|
|
CHECK_EQ(10, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunCountToTenAccRaw2) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
Node* zero = m.Int32Constant(0);
|
|
|
|
Node* ten = m.Int32Constant(10);
|
|
|
|
Node* one = m.Int32Constant(1);
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel header, body, body_cont, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&header);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* i = m.Phi(MachineRepresentation::kWord32, zero, zero);
|
|
|
|
Node* j = m.Phi(MachineRepresentation::kWord32, zero, zero);
|
|
|
|
Node* k = m.Phi(MachineRepresentation::kWord32, zero, zero);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Goto(&body);
|
|
|
|
|
|
|
|
m.Bind(&body);
|
|
|
|
Node* next_i = m.Int32Add(i, one);
|
|
|
|
Node* next_j = m.Int32Add(j, one);
|
|
|
|
Node* next_k = m.Int32Add(j, one);
|
|
|
|
m.Branch(m.Word32Equal(next_i, ten), &end, &body_cont);
|
|
|
|
|
|
|
|
m.Bind(&body_cont);
|
|
|
|
i->ReplaceInput(1, next_i);
|
|
|
|
j->ReplaceInput(1, next_j);
|
|
|
|
k->ReplaceInput(1, next_k);
|
|
|
|
m.Goto(&header);
|
|
|
|
|
|
|
|
m.Bind(&end);
|
|
|
|
m.Return(ten);
|
|
|
|
|
|
|
|
CHECK_EQ(10, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunAddTree) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int32_t inputs[] = {11, 12, 13, 14, 15, 16, 17, 18};
|
|
|
|
|
|
|
|
Node* base = m.PointerConstant(inputs);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* n0 =
|
|
|
|
m.Load(MachineType::Int32(), base, m.Int32Constant(0 * sizeof(int32_t)));
|
|
|
|
Node* n1 =
|
|
|
|
m.Load(MachineType::Int32(), base, m.Int32Constant(1 * sizeof(int32_t)));
|
|
|
|
Node* n2 =
|
|
|
|
m.Load(MachineType::Int32(), base, m.Int32Constant(2 * sizeof(int32_t)));
|
|
|
|
Node* n3 =
|
|
|
|
m.Load(MachineType::Int32(), base, m.Int32Constant(3 * sizeof(int32_t)));
|
|
|
|
Node* n4 =
|
|
|
|
m.Load(MachineType::Int32(), base, m.Int32Constant(4 * sizeof(int32_t)));
|
|
|
|
Node* n5 =
|
|
|
|
m.Load(MachineType::Int32(), base, m.Int32Constant(5 * sizeof(int32_t)));
|
|
|
|
Node* n6 =
|
|
|
|
m.Load(MachineType::Int32(), base, m.Int32Constant(6 * sizeof(int32_t)));
|
|
|
|
Node* n7 =
|
|
|
|
m.Load(MachineType::Int32(), base, m.Int32Constant(7 * sizeof(int32_t)));
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
Node* i1 = m.Int32Add(n0, n1);
|
|
|
|
Node* i2 = m.Int32Add(n2, n3);
|
|
|
|
Node* i3 = m.Int32Add(n4, n5);
|
|
|
|
Node* i4 = m.Int32Add(n6, n7);
|
|
|
|
|
|
|
|
Node* i5 = m.Int32Add(i1, i2);
|
|
|
|
Node* i6 = m.Int32Add(i3, i4);
|
|
|
|
|
|
|
|
Node* i7 = m.Int32Add(i5, i6);
|
|
|
|
|
|
|
|
m.Return(i7);
|
|
|
|
|
|
|
|
CHECK_EQ(116, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const int kFloat64CompareHelperTestCases = 15;
|
|
|
|
static const int kFloat64CompareHelperNodeType = 4;
|
|
|
|
|
|
|
|
static int Float64CompareHelper(RawMachineAssemblerTester<int32_t>* m,
|
|
|
|
int test_case, int node_type, double x,
|
|
|
|
double y) {
|
|
|
|
static double buffer[2];
|
|
|
|
buffer[0] = x;
|
|
|
|
buffer[1] = y;
|
|
|
|
CHECK(0 <= test_case && test_case < kFloat64CompareHelperTestCases);
|
|
|
|
CHECK(0 <= node_type && node_type < kFloat64CompareHelperNodeType);
|
|
|
|
CHECK(x < y);
|
|
|
|
bool load_a = node_type / 2 == 1;
|
|
|
|
bool load_b = node_type % 2 == 1;
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* a =
|
|
|
|
load_a ? m->Load(MachineType::Float64(), m->PointerConstant(&buffer[0]))
|
|
|
|
: m->Float64Constant(x);
|
|
|
|
Node* b =
|
|
|
|
load_b ? m->Load(MachineType::Float64(), m->PointerConstant(&buffer[1]))
|
|
|
|
: m->Float64Constant(y);
|
2017-10-13 16:33:03 +00:00
|
|
|
Node* cmp = nullptr;
|
2014-07-30 13:54:45 +00:00
|
|
|
bool expected = false;
|
|
|
|
switch (test_case) {
|
|
|
|
// Equal tests.
|
|
|
|
case 0:
|
|
|
|
cmp = m->Float64Equal(a, b);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
cmp = m->Float64Equal(a, a);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
// LessThan tests.
|
|
|
|
case 2:
|
|
|
|
cmp = m->Float64LessThan(a, b);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
cmp = m->Float64LessThan(b, a);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
cmp = m->Float64LessThan(a, a);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
// LessThanOrEqual tests.
|
|
|
|
case 5:
|
|
|
|
cmp = m->Float64LessThanOrEqual(a, b);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
cmp = m->Float64LessThanOrEqual(b, a);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
cmp = m->Float64LessThanOrEqual(a, a);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
// NotEqual tests.
|
|
|
|
case 8:
|
|
|
|
cmp = m->Float64NotEqual(a, b);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
cmp = m->Float64NotEqual(b, a);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
cmp = m->Float64NotEqual(a, a);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
// GreaterThan tests.
|
|
|
|
case 11:
|
|
|
|
cmp = m->Float64GreaterThan(a, a);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
cmp = m->Float64GreaterThan(a, b);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
// GreaterThanOrEqual tests.
|
|
|
|
case 13:
|
|
|
|
cmp = m->Float64GreaterThanOrEqual(a, a);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
cmp = m->Float64GreaterThanOrEqual(b, a);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
m->Return(cmp);
|
|
|
|
return expected;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64Compare) {
|
2014-12-20 13:17:20 +00:00
|
|
|
double inf = V8_INFINITY;
|
2014-07-30 13:54:45 +00:00
|
|
|
// All pairs (a1, a2) are of the form a1 < a2.
|
|
|
|
double inputs[] = {0.0, 1.0, -1.0, 0.22, -1.22, 0.22,
|
|
|
|
-inf, 0.22, 0.22, inf, -inf, inf};
|
|
|
|
|
|
|
|
for (int test = 0; test < kFloat64CompareHelperTestCases; test++) {
|
|
|
|
for (int node_type = 0; node_type < kFloat64CompareHelperNodeType;
|
|
|
|
node_type++) {
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t input = 0; input < arraysize(inputs); input += 2) {
|
2014-07-30 13:54:45 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
int expected = Float64CompareHelper(&m, test, node_type, inputs[input],
|
|
|
|
inputs[input + 1]);
|
|
|
|
CHECK_EQ(expected, m.Call());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64UnorderedCompare) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
2014-09-10 12:23:45 +00:00
|
|
|
const Operator* operators[] = {m.machine()->Float64Equal(),
|
|
|
|
m.machine()->Float64LessThan(),
|
|
|
|
m.machine()->Float64LessThanOrEqual()};
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2015-01-21 14:38:49 +00:00
|
|
|
double nan = std::numeric_limits<double>::quiet_NaN();
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t o = 0; o < arraysize(operators); ++o) {
|
2014-07-30 13:54:45 +00:00
|
|
|
for (int j = 0; j < 2; j++) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Node* a = m.Float64Constant(*i);
|
|
|
|
Node* b = m.Float64Constant(nan);
|
|
|
|
if (j == 1) std::swap(a, b);
|
2015-09-23 09:08:15 +00:00
|
|
|
m.Return(m.AddNode(operators[o], a, b));
|
2014-07-30 13:54:45 +00:00
|
|
|
CHECK_EQ(0, m.Call());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64Equal) {
|
|
|
|
double input_a = 0.0;
|
|
|
|
double input_b = 0.0;
|
|
|
|
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* a = m.LoadFromPointer(&input_a, MachineType::Float64());
|
|
|
|
Node* b = m.LoadFromPointer(&input_b, MachineType::Float64());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Float64Equal(a, b));
|
|
|
|
|
|
|
|
CompareWrapper cmp(IrOpcode::kFloat64Equal);
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
|
|
|
FOR_FLOAT64_INPUTS(pr) {
|
|
|
|
input_a = *pl;
|
|
|
|
input_b = *pr;
|
|
|
|
int32_t expected = cmp.Float64Compare(input_a, input_b) ? 1 : 0;
|
|
|
|
CHECK_EQ(expected, m.Call());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64LessThan) {
|
|
|
|
double input_a = 0.0;
|
|
|
|
double input_b = 0.0;
|
|
|
|
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* a = m.LoadFromPointer(&input_a, MachineType::Float64());
|
|
|
|
Node* b = m.LoadFromPointer(&input_b, MachineType::Float64());
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(m.Float64LessThan(a, b));
|
|
|
|
|
|
|
|
CompareWrapper cmp(IrOpcode::kFloat64LessThan);
|
|
|
|
FOR_FLOAT64_INPUTS(pl) {
|
|
|
|
FOR_FLOAT64_INPUTS(pr) {
|
|
|
|
input_a = *pl;
|
|
|
|
input_b = *pr;
|
|
|
|
int32_t expected = cmp.Float64Compare(input_a, input_b) ? 1 : 0;
|
|
|
|
CHECK_EQ(expected, m.Call());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void IntPtrCompare(intptr_t left, intptr_t right) {
|
|
|
|
for (int test = 0; test < 7; test++) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<bool> m(MachineType::Pointer(),
|
|
|
|
MachineType::Pointer());
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* p0 = m.Parameter(0);
|
|
|
|
Node* p1 = m.Parameter(1);
|
2017-10-13 16:33:03 +00:00
|
|
|
Node* res = nullptr;
|
2014-07-30 13:54:45 +00:00
|
|
|
bool expected = false;
|
|
|
|
switch (test) {
|
|
|
|
case 0:
|
|
|
|
res = m.IntPtrLessThan(p0, p1);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
res = m.IntPtrLessThanOrEqual(p0, p1);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
res = m.IntPtrEqual(p0, p1);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
res = m.IntPtrGreaterThanOrEqual(p0, p1);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
res = m.IntPtrGreaterThan(p0, p1);
|
|
|
|
expected = false;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
res = m.IntPtrEqual(p0, p0);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
res = m.IntPtrNotEqual(p0, p1);
|
|
|
|
expected = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
m.Return(res);
|
|
|
|
CHECK_EQ(expected, m.Call(reinterpret_cast<int32_t*>(left),
|
|
|
|
reinterpret_cast<int32_t*>(right)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunIntPtrCompare) {
|
|
|
|
intptr_t min = std::numeric_limits<intptr_t>::min();
|
|
|
|
intptr_t max = std::numeric_limits<intptr_t>::max();
|
|
|
|
// An ascending chain of intptr_t
|
|
|
|
intptr_t inputs[] = {min, min / 2, -1, 0, 1, max / 2, max};
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t i = 0; i < arraysize(inputs) - 1; i++) {
|
2014-07-30 13:54:45 +00:00
|
|
|
IntPtrCompare(inputs[i], inputs[i + 1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunTestIntPtrArithmetic) {
|
|
|
|
static const int kInputSize = 10;
|
|
|
|
int32_t inputs[kInputSize];
|
|
|
|
int32_t outputs[kInputSize];
|
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
|
|
|
inputs[i] = i;
|
|
|
|
outputs[i] = -1;
|
|
|
|
}
|
|
|
|
RawMachineAssemblerTester<int32_t*> m;
|
|
|
|
Node* input = m.PointerConstant(&inputs[0]);
|
|
|
|
Node* output = m.PointerConstant(&outputs[kInputSize - 1]);
|
2015-05-29 14:05:39 +00:00
|
|
|
Node* elem_size = m.IntPtrConstant(sizeof(inputs[0]));
|
2014-07-30 13:54:45 +00:00
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
2015-12-11 15:34:00 +00:00
|
|
|
m.Store(MachineRepresentation::kWord32, output,
|
|
|
|
m.Load(MachineType::Int32(), input), kNoWriteBarrier);
|
2014-07-30 13:54:45 +00:00
|
|
|
input = m.IntPtrAdd(input, elem_size);
|
|
|
|
output = m.IntPtrSub(output, elem_size);
|
|
|
|
}
|
|
|
|
m.Return(input);
|
|
|
|
CHECK_EQ(&inputs[kInputSize], m.Call());
|
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
|
|
|
CHECK_EQ(i, inputs[i]);
|
|
|
|
CHECK_EQ(kInputSize - i - 1, outputs[i]);
|
|
|
|
}
|
2014-07-31 07:44:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
TEST(RunSpillLotsOfThings) {
|
|
|
|
static const int kInputSize = 1000;
|
2015-06-01 15:54:53 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-07-30 13:54:45 +00:00
|
|
|
Node* accs[kInputSize];
|
|
|
|
int32_t outputs[kInputSize];
|
|
|
|
Node* one = m.Int32Constant(1);
|
|
|
|
Node* acc = one;
|
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
|
|
|
acc = m.Int32Add(acc, one);
|
|
|
|
accs[i] = acc;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&outputs[i], MachineRepresentation::kWord32, accs[i]);
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
m.Return(one);
|
|
|
|
m.Call();
|
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
|
|
|
CHECK_EQ(outputs[i], i + 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunSpillConstantsAndParameters) {
|
2014-07-30 16:21:36 +00:00
|
|
|
static const int kInputSize = 1000;
|
2014-07-30 13:54:45 +00:00
|
|
|
static const int32_t kBase = 987;
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
|
|
|
|
MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
int32_t outputs[kInputSize];
|
|
|
|
Node* csts[kInputSize];
|
|
|
|
Node* accs[kInputSize];
|
|
|
|
Node* acc = m.Int32Constant(0);
|
2014-07-30 16:21:36 +00:00
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
2014-07-30 13:54:45 +00:00
|
|
|
csts[i] = m.Int32Constant(static_cast<int32_t>(kBase + i));
|
|
|
|
}
|
2014-07-30 16:21:36 +00:00
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
2014-07-30 13:54:45 +00:00
|
|
|
acc = m.Int32Add(acc, csts[i]);
|
|
|
|
accs[i] = acc;
|
|
|
|
}
|
2014-07-30 16:21:36 +00:00
|
|
|
for (int i = 0; i < kInputSize; i++) {
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&outputs[i], MachineRepresentation::kWord32, accs[i]);
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
|
|
|
m.Return(m.Int32Add(acc, m.Int32Add(m.Parameter(0), m.Parameter(1))));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected = *i + *j;
|
2014-07-30 16:21:36 +00:00
|
|
|
for (int k = 0; k < kInputSize; k++) {
|
2014-07-30 13:54:45 +00:00
|
|
|
expected += kBase + k;
|
|
|
|
}
|
|
|
|
CHECK_EQ(expected, m.Call(*i, *j));
|
|
|
|
expected = 0;
|
2014-07-30 16:21:36 +00:00
|
|
|
for (int k = 0; k < kInputSize; k++) {
|
2014-07-30 13:54:45 +00:00
|
|
|
expected += kBase + k;
|
|
|
|
CHECK_EQ(expected, outputs[k]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunNewSpaceConstantsInPhi) {
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<Object*> m(MachineType::Int32());
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
|
|
Handle<HeapNumber> true_val = isolate->factory()->NewHeapNumber(11.2);
|
|
|
|
Handle<HeapNumber> false_val = isolate->factory()->NewHeapNumber(11.3);
|
|
|
|
Node* true_node = m.HeapConstant(true_val);
|
|
|
|
Node* false_node = m.HeapConstant(false_val);
|
|
|
|
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb, end;
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Branch(m.Parameter(0), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Goto(&end);
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Goto(&end);
|
|
|
|
|
|
|
|
m.Bind(&end);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = m.Phi(MachineRepresentation::kTagged, true_node, false_node);
|
2014-07-30 13:54:45 +00:00
|
|
|
m.Return(phi);
|
|
|
|
|
|
|
|
CHECK_EQ(*false_val, m.Call(0));
|
|
|
|
CHECK_EQ(*true_val, m.Call(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-01 09:32:58 +00:00
|
|
|
TEST(RunInt32AddWithOverflowP) {
|
|
|
|
int32_t actual_val = -1;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add = m.Int32AddWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
2014-08-01 09:32:58 +00:00
|
|
|
bt.AddReturn(ovf);
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected_val;
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedAddOverflow32(*i, *j, &expected_val);
|
2014-08-01 09:32:58 +00:00
|
|
|
CHECK_EQ(expected_ovf, bt.call(*i, *j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddWithOverflowImm) {
|
|
|
|
int32_t actual_val = -1, expected_val = 0;
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add = m.Int32AddWithOverflow(m.Int32Constant(*i), m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
2014-08-01 09:32:58 +00:00
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedAddOverflow32(*i, *j, &expected_val);
|
2014-08-01 09:32:58 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add = m.Int32AddWithOverflow(m.Parameter(0), m.Int32Constant(*i));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
2014-08-01 09:32:58 +00:00
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedAddOverflow32(*i, *j, &expected_val);
|
2014-08-01 09:32:58 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add =
|
|
|
|
m.Int32AddWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
2014-08-01 09:32:58 +00:00
|
|
|
m.Return(ovf);
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedAddOverflow32(*i, *j, &expected_val);
|
2014-08-01 09:32:58 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call());
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32AddWithOverflowInBranchP) {
|
2014-08-04 08:18:37 +00:00
|
|
|
int constant = 911777;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-08-01 09:32:58 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add = m.Int32AddWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2014-08-01 09:32:58 +00:00
|
|
|
m.Branch(ovf, &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
2014-08-04 08:18:37 +00:00
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
2014-08-01 09:32:58 +00:00
|
|
|
m.Bind(&blockb);
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* val = m.Projection(0, add);
|
2014-08-01 09:32:58 +00:00
|
|
|
bt.AddReturn(val);
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-01 09:32:58 +00:00
|
|
|
int32_t expected;
|
2017-08-11 11:22:28 +00:00
|
|
|
if (base::bits::SignedAddOverflow32(*i, *j, &expected))
|
|
|
|
expected = constant;
|
2014-08-01 09:32:58 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-01 12:18:20 +00:00
|
|
|
|
|
|
|
TEST(RunInt32SubWithOverflowP) {
|
|
|
|
int32_t actual_val = -1;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add = m.Int32SubWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
2014-08-01 12:18:20 +00:00
|
|
|
bt.AddReturn(ovf);
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected_val;
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedSubOverflow32(*i, *j, &expected_val);
|
2014-08-01 12:18:20 +00:00
|
|
|
CHECK_EQ(expected_ovf, bt.call(*i, *j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32SubWithOverflowImm) {
|
|
|
|
int32_t actual_val = -1, expected_val = 0;
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add = m.Int32SubWithOverflow(m.Int32Constant(*i), m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
2014-08-01 12:18:20 +00:00
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedSubOverflow32(*i, *j, &expected_val);
|
2014-08-01 12:18:20 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add = m.Int32SubWithOverflow(m.Parameter(0), m.Int32Constant(*i));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
2014-08-01 12:18:20 +00:00
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedSubOverflow32(*j, *i, &expected_val);
|
2014-08-01 12:18:20 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* add =
|
|
|
|
m.Int32SubWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
2014-08-01 12:18:20 +00:00
|
|
|
m.Return(ovf);
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedSubOverflow32(*i, *j, &expected_val);
|
2014-08-01 12:18:20 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call());
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunInt32SubWithOverflowInBranchP) {
|
2014-08-04 08:18:37 +00:00
|
|
|
int constant = 911999;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2014-08-01 12:18:20 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* sub = m.Int32SubWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* ovf = m.Projection(1, sub);
|
2014-08-01 12:18:20 +00:00
|
|
|
m.Branch(ovf, &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
2014-08-04 08:18:37 +00:00
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
2014-08-01 12:18:20 +00:00
|
|
|
m.Bind(&blockb);
|
2014-08-04 08:18:37 +00:00
|
|
|
Node* val = m.Projection(0, sub);
|
2014-08-01 12:18:20 +00:00
|
|
|
bt.AddReturn(val);
|
2014-08-14 09:19:54 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2014-08-01 12:18:20 +00:00
|
|
|
int32_t expected;
|
2017-08-11 11:22:28 +00:00
|
|
|
if (base::bits::SignedSubOverflow32(*i, *j, &expected))
|
|
|
|
expected = constant;
|
2014-08-01 12:18:20 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-14 08:53:06 +00:00
|
|
|
TEST(RunInt32MulWithOverflowP) {
|
|
|
|
int32_t actual_val = -1;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
Node* add = m.Int32MulWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
|
|
|
bt.AddReturn(ovf);
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected_val;
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedMulOverflow32(*i, *j, &expected_val);
|
2016-07-14 08:53:06 +00:00
|
|
|
CHECK_EQ(expected_ovf, bt.call(*i, *j));
|
|
|
|
if (!expected_ovf) {
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt32MulWithOverflowImm) {
|
|
|
|
int32_t actual_val = -1, expected_val = 0;
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
|
|
|
Node* add = m.Int32MulWithOverflow(m.Int32Constant(*i), m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedMulOverflow32(*i, *j, &expected_val);
|
2016-07-14 08:53:06 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
if (!expected_ovf) {
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
|
|
|
Node* add = m.Int32MulWithOverflow(m.Parameter(0), m.Int32Constant(*i));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
|
|
|
m.Return(ovf);
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf =
|
|
|
|
base::bits::SignedMulOverflow32(*i, *j, &expected_val);
|
2016-07-14 08:53:06 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call(*j));
|
|
|
|
if (!expected_ovf) {
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Node* add =
|
|
|
|
m.Int32MulWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j));
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
|
|
|
|
m.Return(ovf);
|
2017-08-11 11:22:28 +00:00
|
|
|
int expected_ovf = base::bits::SignedMulOverflow32(*i, *j, &expected_val);
|
2016-07-14 08:53:06 +00:00
|
|
|
CHECK_EQ(expected_ovf, m.Call());
|
|
|
|
if (!expected_ovf) {
|
|
|
|
CHECK_EQ(expected_val, actual_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunInt32MulWithOverflowInBranchP) {
|
|
|
|
int constant = 911777;
|
|
|
|
RawMachineLabel blocka, blockb;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
Int32BinopTester bt(&m);
|
|
|
|
Node* add = m.Int32MulWithOverflow(bt.param0, bt.param1);
|
|
|
|
Node* ovf = m.Projection(1, add);
|
|
|
|
m.Branch(ovf, &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
bt.AddReturn(m.Int32Constant(constant));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
Node* val = m.Projection(0, add);
|
|
|
|
bt.AddReturn(val);
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t expected;
|
2017-08-11 11:22:28 +00:00
|
|
|
if (base::bits::SignedMulOverflow32(*i, *j, &expected))
|
|
|
|
expected = constant;
|
2016-07-14 08:53:06 +00:00
|
|
|
CHECK_EQ(expected, bt.call(*i, *j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-19 08:48:41 +00:00
|
|
|
|
2015-02-26 07:18:26 +00:00
|
|
|
TEST(RunWord64EqualInBranchP) {
|
|
|
|
int64_t input;
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel blocka, blockb;
|
2018-01-08 15:31:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-02-26 07:18:26 +00:00
|
|
|
if (!m.machine()->Is64()) return;
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* value = m.LoadFromPointer(&input, MachineType::Int64());
|
2015-02-26 07:18:26 +00:00
|
|
|
m.Branch(m.Word64Equal(value, m.Int64Constant(0)), &blocka, &blockb);
|
|
|
|
m.Bind(&blocka);
|
|
|
|
m.Return(m.Int32Constant(1));
|
|
|
|
m.Bind(&blockb);
|
|
|
|
m.Return(m.Int32Constant(2));
|
2017-12-01 14:01:22 +00:00
|
|
|
input = int64_t{0};
|
2015-02-26 07:18:26 +00:00
|
|
|
CHECK_EQ(1, m.Call());
|
2017-12-01 14:01:22 +00:00
|
|
|
input = int64_t{1};
|
2015-02-26 07:18:26 +00:00
|
|
|
CHECK_EQ(2, m.Call());
|
2017-12-01 14:01:22 +00:00
|
|
|
input = int64_t{0x100000000};
|
2015-02-26 07:18:26 +00:00
|
|
|
CHECK_EQ(2, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-19 08:48:41 +00:00
|
|
|
TEST(RunChangeInt32ToInt64P) {
|
|
|
|
if (kPointerSize < 8) return;
|
|
|
|
int64_t actual = -1;
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual, MachineRepresentation::kWord64,
|
2015-12-10 09:03:30 +00:00
|
|
|
m.ChangeInt32ToInt64(m.Parameter(0)));
|
2014-08-19 08:48:41 +00:00
|
|
|
m.Return(m.Int32Constant(0));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
int64_t expected = *i;
|
|
|
|
CHECK_EQ(0, m.Call(*i));
|
|
|
|
CHECK_EQ(expected, actual);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunChangeUint32ToUint64P) {
|
|
|
|
if (kPointerSize < 8) return;
|
|
|
|
int64_t actual = -1;
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&actual, MachineRepresentation::kWord64,
|
2014-08-19 08:48:41 +00:00
|
|
|
m.ChangeUint32ToUint64(m.Parameter(0)));
|
|
|
|
m.Return(m.Int32Constant(0));
|
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
int64_t expected = static_cast<uint64_t>(*i);
|
|
|
|
CHECK_EQ(0, m.Call(*i));
|
|
|
|
CHECK_EQ(expected, actual);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunTruncateInt64ToInt32P) {
|
|
|
|
if (kPointerSize < 8) return;
|
|
|
|
int64_t expected = -1;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Return(m.TruncateInt64ToInt32(
|
|
|
|
m.LoadFromPointer(&expected, MachineType::Int64())));
|
2014-08-19 08:48:41 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
expected = (static_cast<uint64_t>(*j) << 32) | *i;
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK_EQ(static_cast<int32_t>(expected), m.Call());
|
2014-08-19 08:48:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-24 11:39:31 +00:00
|
|
|
TEST(RunTruncateFloat64ToWord32P) {
|
2014-08-20 04:01:00 +00:00
|
|
|
struct {
|
|
|
|
double from;
|
|
|
|
double raw;
|
|
|
|
} kValues[] = {{0, 0},
|
|
|
|
{0.5, 0},
|
|
|
|
{-0.5, 0},
|
|
|
|
{1.5, 1},
|
|
|
|
{-1.5, -1},
|
|
|
|
{5.5, 5},
|
|
|
|
{-5.0, -5},
|
2015-01-21 14:38:49 +00:00
|
|
|
{std::numeric_limits<double>::quiet_NaN(), 0},
|
2014-08-20 04:01:00 +00:00
|
|
|
{std::numeric_limits<double>::infinity(), 0},
|
2015-01-21 14:38:49 +00:00
|
|
|
{-std::numeric_limits<double>::quiet_NaN(), 0},
|
2014-08-20 04:01:00 +00:00
|
|
|
{-std::numeric_limits<double>::infinity(), 0},
|
|
|
|
{4.94065645841e-324, 0},
|
|
|
|
{-4.94065645841e-324, 0},
|
|
|
|
{0.9999999999999999, 0},
|
|
|
|
{-0.9999999999999999, 0},
|
|
|
|
{4294967296.0, 0},
|
|
|
|
{-4294967296.0, 0},
|
|
|
|
{9223372036854775000.0, 4294966272.0},
|
|
|
|
{-9223372036854775000.0, -4294966272.0},
|
|
|
|
{4.5036e+15, 372629504},
|
|
|
|
{-4.5036e+15, -372629504},
|
|
|
|
{287524199.5377777, 0x11234567},
|
|
|
|
{-287524199.5377777, -0x11234567},
|
|
|
|
{2300193596.302222, 2300193596.0},
|
|
|
|
{-2300193596.302222, -2300193596.0},
|
|
|
|
{4600387192.604444, 305419896},
|
|
|
|
{-4600387192.604444, -305419896},
|
|
|
|
{4823855600872397.0, 1737075661},
|
|
|
|
{-4823855600872397.0, -1737075661},
|
|
|
|
{4503603922337791.0, -1},
|
|
|
|
{-4503603922337791.0, 1},
|
|
|
|
{4503601774854143.0, 2147483647},
|
|
|
|
{-4503601774854143.0, -2147483647},
|
|
|
|
{9007207844675582.0, -2},
|
|
|
|
{-9007207844675582.0, 2},
|
|
|
|
{2.4178527921507624e+24, -536870912},
|
|
|
|
{-2.4178527921507624e+24, 536870912},
|
|
|
|
{2.417853945072267e+24, -536870912},
|
|
|
|
{-2.417853945072267e+24, 536870912},
|
|
|
|
{4.8357055843015248e+24, -1073741824},
|
|
|
|
{-4.8357055843015248e+24, 1073741824},
|
|
|
|
{4.8357078901445341e+24, -1073741824},
|
|
|
|
{-4.8357078901445341e+24, 1073741824},
|
|
|
|
{2147483647.0, 2147483647.0},
|
|
|
|
{-2147483648.0, -2147483648.0},
|
|
|
|
{9.6714111686030497e+24, -2147483648.0},
|
|
|
|
{-9.6714111686030497e+24, -2147483648.0},
|
|
|
|
{9.6714157802890681e+24, -2147483648.0},
|
|
|
|
{-9.6714157802890681e+24, -2147483648.0},
|
|
|
|
{1.9342813113834065e+25, 2147483648.0},
|
|
|
|
{-1.9342813113834065e+25, 2147483648.0},
|
|
|
|
{3.868562622766813e+25, 0},
|
|
|
|
{-3.868562622766813e+25, 0},
|
|
|
|
{1.7976931348623157e+308, 0},
|
|
|
|
{-1.7976931348623157e+308, 0}};
|
|
|
|
double input = -1.0;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2016-04-24 11:39:31 +00:00
|
|
|
m.Return(m.TruncateFloat64ToWord32(
|
2015-12-10 09:03:30 +00:00
|
|
|
m.LoadFromPointer(&input, MachineType::Float64())));
|
2014-08-26 09:19:24 +00:00
|
|
|
for (size_t i = 0; i < arraysize(kValues); ++i) {
|
2014-08-20 04:01:00 +00:00
|
|
|
input = kValues[i].from;
|
|
|
|
uint64_t expected = static_cast<int64_t>(kValues[i].raw);
|
|
|
|
CHECK_EQ(static_cast<int>(expected), m.Call());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-27 06:59:47 +00:00
|
|
|
TEST(RunTruncateFloat64ToWord32SignExtension) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> r;
|
|
|
|
r.Return(r.Int32Sub(r.TruncateFloat64ToWord32(r.Float64Constant(-1.0)),
|
|
|
|
r.Int32Constant(0)));
|
|
|
|
CHECK_EQ(-1, r.Call());
|
|
|
|
}
|
2014-09-24 11:08:35 +00:00
|
|
|
|
|
|
|
TEST(RunChangeFloat32ToFloat64) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float32());
|
2014-10-13 07:42:35 +00:00
|
|
|
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
|
2014-10-13 07:42:35 +00:00
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(static_cast<double>(*i), m.Call(*i));
|
|
|
|
}
|
2014-09-24 11:08:35 +00:00
|
|
|
}
|
|
|
|
|
2014-09-25 08:56:02 +00:00
|
|
|
|
|
|
|
TEST(RunFloat32Constant) {
|
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2015-11-09 17:41:35 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m;
|
|
|
|
m.Return(m.Float32Constant(*i));
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_FLOAT_EQ(*i, m.Call());
|
2014-09-25 08:56:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
|
2015-03-05 09:22:26 +00:00
|
|
|
TEST(RunFloat64ExtractLowWord32) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float64());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.Float64ExtractLowWord32(m.Parameter(0)));
|
2015-03-05 09:22:26 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-11-09 17:41:35 +00:00
|
|
|
uint32_t expected = static_cast<uint32_t>(bit_cast<uint64_t>(*i));
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
2015-03-05 09:22:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64ExtractHighWord32) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float64());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.Float64ExtractHighWord32(m.Parameter(0)));
|
2015-03-05 09:22:26 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-11-09 17:41:35 +00:00
|
|
|
uint32_t expected = static_cast<uint32_t>(bit_cast<uint64_t>(*i) >> 32);
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
2015-03-05 09:22:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64InsertLowWord32) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
|
|
|
|
MachineType::Int32());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.Float64InsertLowWord32(m.Parameter(0), m.Parameter(1)));
|
2015-03-05 09:22:26 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
FOR_INT32_INPUTS(j) {
|
2017-12-01 08:58:16 +00:00
|
|
|
double expected =
|
|
|
|
bit_cast<double>((bit_cast<uint64_t>(*i) & ~(uint64_t{0xFFFFFFFF})) |
|
|
|
|
(static_cast<uint64_t>(bit_cast<uint32_t>(*j))));
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ(expected, m.Call(*i, *j));
|
2015-03-05 09:22:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64InsertHighWord32) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
|
|
|
|
MachineType::Uint32());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.Float64InsertHighWord32(m.Parameter(0), m.Parameter(1)));
|
2015-03-05 09:22:26 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-11-09 17:41:35 +00:00
|
|
|
FOR_UINT32_INPUTS(j) {
|
|
|
|
uint64_t expected = (bit_cast<uint64_t>(*i) & 0xFFFFFFFF) |
|
|
|
|
(static_cast<uint64_t>(*j) << 32);
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
CHECK_DOUBLE_EQ(bit_cast<double>(expected), m.Call(*i, *j));
|
2015-03-05 09:22:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-08 11:54:53 +00:00
|
|
|
TEST(RunFloat32Abs) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.Float32Abs(m.Parameter(0)));
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(std::abs(*i), m.Call(*i)); }
|
2015-04-08 11:54:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64Abs) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-11-09 17:41:35 +00:00
|
|
|
m.Return(m.Float64Abs(m.Parameter(0)));
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(std::abs(*i), m.Call(*i)); }
|
2015-04-08 11:54:53 +00:00
|
|
|
}
|
|
|
|
|
[builtins] Unify most of the remaining Math builtins.
Import fdlibm versions of acos, acosh, asin and asinh, which are more
precise and produce the same result across platforms (we were using
libm versions for asin and acos so far, where both speed and precision
depended on the operating system so far). Introduce appropriate TurboFan
operators for these functions and use them both for inlining and for the
generic builtin.
Also migrate the Math.imul and Math.fround builtins to TurboFan builtins
to ensure that their behavior is always exactly the same as the inlined
TurboFan version (i.e. C++ truncation semantics for double to float
don't necessarily meet the JavaScript semantics).
For completeness, also migrate Math.sign, which can even get some nice
love in TurboFan.
Drive-by-fix: Some alpha-sorting on the Math related functions, and
cleanup the list of Math intrinsics that we have to export via the
native context currently.
BUG=v8:3266,v8:3496,v8:3509,v8:3952,v8:5169,v8:5170,v8:5171,v8:5172
TBR=rossberg@chromium.org
R=franzih@chromium.org
Review-Url: https://codereview.chromium.org/2116753002
Cr-Commit-Position: refs/heads/master@{#37476}
2016-07-01 11:11:33 +00:00
|
|
|
TEST(RunFloat64Acos) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Acos(m.Parameter(0)));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::acos(*i), m.Call(*i));
|
|
|
|
}
|
[builtins] Unify most of the remaining Math builtins.
Import fdlibm versions of acos, acosh, asin and asinh, which are more
precise and produce the same result across platforms (we were using
libm versions for asin and acos so far, where both speed and precision
depended on the operating system so far). Introduce appropriate TurboFan
operators for these functions and use them both for inlining and for the
generic builtin.
Also migrate the Math.imul and Math.fround builtins to TurboFan builtins
to ensure that their behavior is always exactly the same as the inlined
TurboFan version (i.e. C++ truncation semantics for double to float
don't necessarily meet the JavaScript semantics).
For completeness, also migrate Math.sign, which can even get some nice
love in TurboFan.
Drive-by-fix: Some alpha-sorting on the Math related functions, and
cleanup the list of Math intrinsics that we have to export via the
native context currently.
BUG=v8:3266,v8:3496,v8:3509,v8:3952,v8:5169,v8:5170,v8:5171,v8:5172
TBR=rossberg@chromium.org
R=franzih@chromium.org
Review-Url: https://codereview.chromium.org/2116753002
Cr-Commit-Position: refs/heads/master@{#37476}
2016-07-01 11:11:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunFloat64Acosh) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Acosh(m.Parameter(0)));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::acosh(*i), m.Call(*i));
|
|
|
|
}
|
[builtins] Unify most of the remaining Math builtins.
Import fdlibm versions of acos, acosh, asin and asinh, which are more
precise and produce the same result across platforms (we were using
libm versions for asin and acos so far, where both speed and precision
depended on the operating system so far). Introduce appropriate TurboFan
operators for these functions and use them both for inlining and for the
generic builtin.
Also migrate the Math.imul and Math.fround builtins to TurboFan builtins
to ensure that their behavior is always exactly the same as the inlined
TurboFan version (i.e. C++ truncation semantics for double to float
don't necessarily meet the JavaScript semantics).
For completeness, also migrate Math.sign, which can even get some nice
love in TurboFan.
Drive-by-fix: Some alpha-sorting on the Math related functions, and
cleanup the list of Math intrinsics that we have to export via the
native context currently.
BUG=v8:3266,v8:3496,v8:3509,v8:3952,v8:5169,v8:5170,v8:5171,v8:5172
TBR=rossberg@chromium.org
R=franzih@chromium.org
Review-Url: https://codereview.chromium.org/2116753002
Cr-Commit-Position: refs/heads/master@{#37476}
2016-07-01 11:11:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunFloat64Asin) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Asin(m.Parameter(0)));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::asin(*i), m.Call(*i));
|
|
|
|
}
|
[builtins] Unify most of the remaining Math builtins.
Import fdlibm versions of acos, acosh, asin and asinh, which are more
precise and produce the same result across platforms (we were using
libm versions for asin and acos so far, where both speed and precision
depended on the operating system so far). Introduce appropriate TurboFan
operators for these functions and use them both for inlining and for the
generic builtin.
Also migrate the Math.imul and Math.fround builtins to TurboFan builtins
to ensure that their behavior is always exactly the same as the inlined
TurboFan version (i.e. C++ truncation semantics for double to float
don't necessarily meet the JavaScript semantics).
For completeness, also migrate Math.sign, which can even get some nice
love in TurboFan.
Drive-by-fix: Some alpha-sorting on the Math related functions, and
cleanup the list of Math intrinsics that we have to export via the
native context currently.
BUG=v8:3266,v8:3496,v8:3509,v8:3952,v8:5169,v8:5170,v8:5171,v8:5172
TBR=rossberg@chromium.org
R=franzih@chromium.org
Review-Url: https://codereview.chromium.org/2116753002
Cr-Commit-Position: refs/heads/master@{#37476}
2016-07-01 11:11:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunFloat64Asinh) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Asinh(m.Parameter(0)));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::asinh(*i), m.Call(*i));
|
|
|
|
}
|
[builtins] Unify most of the remaining Math builtins.
Import fdlibm versions of acos, acosh, asin and asinh, which are more
precise and produce the same result across platforms (we were using
libm versions for asin and acos so far, where both speed and precision
depended on the operating system so far). Introduce appropriate TurboFan
operators for these functions and use them both for inlining and for the
generic builtin.
Also migrate the Math.imul and Math.fround builtins to TurboFan builtins
to ensure that their behavior is always exactly the same as the inlined
TurboFan version (i.e. C++ truncation semantics for double to float
don't necessarily meet the JavaScript semantics).
For completeness, also migrate Math.sign, which can even get some nice
love in TurboFan.
Drive-by-fix: Some alpha-sorting on the Math related functions, and
cleanup the list of Math intrinsics that we have to export via the
native context currently.
BUG=v8:3266,v8:3496,v8:3509,v8:3952,v8:5169,v8:5170,v8:5171,v8:5172
TBR=rossberg@chromium.org
R=franzih@chromium.org
Review-Url: https://codereview.chromium.org/2116753002
Cr-Commit-Position: refs/heads/master@{#37476}
2016-07-01 11:11:33 +00:00
|
|
|
}
|
|
|
|
|
2016-06-13 07:06:49 +00:00
|
|
|
TEST(RunFloat64Atan) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Atan(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK_DOUBLE_EQ(-0.0, m.Call(-0.0));
|
|
|
|
CHECK_DOUBLE_EQ(0.0, m.Call(0.0));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::atan(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-13 07:06:49 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 09:13:22 +00:00
|
|
|
TEST(RunFloat64Atanh) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Atanh(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(), m.Call(1.0));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-1.0));
|
|
|
|
CHECK_DOUBLE_EQ(-0.0, m.Call(-0.0));
|
|
|
|
CHECK_DOUBLE_EQ(0.0, m.Call(0.0));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::atanh(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-17 09:13:22 +00:00
|
|
|
}
|
|
|
|
|
[builtins] Unify most of the remaining Math builtins.
Import fdlibm versions of acos, acosh, asin and asinh, which are more
precise and produce the same result across platforms (we were using
libm versions for asin and acos so far, where both speed and precision
depended on the operating system so far). Introduce appropriate TurboFan
operators for these functions and use them both for inlining and for the
generic builtin.
Also migrate the Math.imul and Math.fround builtins to TurboFan builtins
to ensure that their behavior is always exactly the same as the inlined
TurboFan version (i.e. C++ truncation semantics for double to float
don't necessarily meet the JavaScript semantics).
For completeness, also migrate Math.sign, which can even get some nice
love in TurboFan.
Drive-by-fix: Some alpha-sorting on the Math related functions, and
cleanup the list of Math intrinsics that we have to export via the
native context currently.
BUG=v8:3266,v8:3496,v8:3509,v8:3952,v8:5169,v8:5170,v8:5171,v8:5172
TBR=rossberg@chromium.org
R=franzih@chromium.org
Review-Url: https://codereview.chromium.org/2116753002
Cr-Commit-Position: refs/heads/master@{#37476}
2016-07-01 11:11:33 +00:00
|
|
|
TEST(RunFloat64Atan2) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
|
|
|
|
MachineType::Float64());
|
|
|
|
m.Return(m.Float64Atan2(m.Parameter(0), m.Parameter(1)));
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
FOR_FLOAT64_INPUTS(j) {
|
2017-08-11 11:22:28 +00:00
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::atan2(*i, *j), m.Call(*i, *j));
|
[builtins] Unify most of the remaining Math builtins.
Import fdlibm versions of acos, acosh, asin and asinh, which are more
precise and produce the same result across platforms (we were using
libm versions for asin and acos so far, where both speed and precision
depended on the operating system so far). Introduce appropriate TurboFan
operators for these functions and use them both for inlining and for the
generic builtin.
Also migrate the Math.imul and Math.fround builtins to TurboFan builtins
to ensure that their behavior is always exactly the same as the inlined
TurboFan version (i.e. C++ truncation semantics for double to float
don't necessarily meet the JavaScript semantics).
For completeness, also migrate Math.sign, which can even get some nice
love in TurboFan.
Drive-by-fix: Some alpha-sorting on the Math related functions, and
cleanup the list of Math intrinsics that we have to export via the
native context currently.
BUG=v8:3266,v8:3496,v8:3509,v8:3952,v8:5169,v8:5170,v8:5171,v8:5172
TBR=rossberg@chromium.org
R=franzih@chromium.org
Review-Url: https://codereview.chromium.org/2116753002
Cr-Commit-Position: refs/heads/master@{#37476}
2016-07-01 11:11:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-17 15:21:48 +00:00
|
|
|
TEST(RunFloat64Cos) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Cos(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(base::ieee754::cos(*i), m.Call(*i)); }
|
2016-06-17 15:21:48 +00:00
|
|
|
}
|
|
|
|
|
2016-06-30 08:41:05 +00:00
|
|
|
TEST(RunFloat64Cosh) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Cosh(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::cosh(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-30 08:41:05 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 05:19:35 +00:00
|
|
|
TEST(RunFloat64Exp) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Exp(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK_EQ(0.0, m.Call(-std::numeric_limits<double>::infinity()));
|
|
|
|
CHECK_DOUBLE_EQ(1.0, m.Call(-0.0));
|
|
|
|
CHECK_DOUBLE_EQ(1.0, m.Call(0.0));
|
|
|
|
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
|
|
|
|
m.Call(std::numeric_limits<double>::infinity()));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(base::ieee754::exp(*i), m.Call(*i)); }
|
2016-06-17 05:19:35 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 09:13:22 +00:00
|
|
|
TEST(RunFloat64Expm1) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Expm1(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK_EQ(-1.0, m.Call(-std::numeric_limits<double>::infinity()));
|
|
|
|
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
|
|
|
|
m.Call(std::numeric_limits<double>::infinity()));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::expm1(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-17 09:13:22 +00:00
|
|
|
}
|
|
|
|
|
2016-06-03 09:47:25 +00:00
|
|
|
TEST(RunFloat64Log) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Log(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(-std::numeric_limits<double>::infinity())));
|
|
|
|
CHECK(std::isnan(m.Call(-1.0)));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-0.0));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(0.0));
|
|
|
|
CHECK_DOUBLE_EQ(0.0, m.Call(1.0));
|
|
|
|
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
|
|
|
|
m.Call(std::numeric_limits<double>::infinity()));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(base::ieee754::log(*i), m.Call(*i)); }
|
2016-06-03 09:47:25 +00:00
|
|
|
}
|
2015-04-08 11:54:53 +00:00
|
|
|
|
2016-06-13 05:46:38 +00:00
|
|
|
TEST(RunFloat64Log1p) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Log1p(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(-std::numeric_limits<double>::infinity())));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-1.0));
|
|
|
|
CHECK_DOUBLE_EQ(0.0, m.Call(0.0));
|
|
|
|
CHECK_DOUBLE_EQ(-0.0, m.Call(-0.0));
|
|
|
|
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
|
|
|
|
m.Call(std::numeric_limits<double>::infinity()));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::log1p(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-13 05:46:38 +00:00
|
|
|
}
|
|
|
|
|
2016-06-16 11:22:32 +00:00
|
|
|
TEST(RunFloat64Log2) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Log2(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(-std::numeric_limits<double>::infinity())));
|
|
|
|
CHECK(std::isnan(m.Call(-1.0)));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-0.0));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(0.0));
|
|
|
|
CHECK_DOUBLE_EQ(0.0, m.Call(1.0));
|
|
|
|
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
|
|
|
|
m.Call(std::numeric_limits<double>::infinity()));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::log2(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-16 11:22:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(RunFloat64Log10) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Log10(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(-std::numeric_limits<double>::infinity())));
|
|
|
|
CHECK(std::isnan(m.Call(-1.0)));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-0.0));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(0.0));
|
|
|
|
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
|
|
|
|
m.Call(std::numeric_limits<double>::infinity()));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::log10(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-16 11:22:32 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 09:13:22 +00:00
|
|
|
TEST(RunFloat64Cbrt) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Cbrt(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
|
|
|
CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
|
|
|
|
m.Call(std::numeric_limits<double>::infinity()));
|
|
|
|
CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(),
|
|
|
|
m.Call(-std::numeric_limits<double>::infinity()));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::cbrt(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-17 09:13:22 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 15:21:48 +00:00
|
|
|
TEST(RunFloat64Sin) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Sin(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(base::ieee754::sin(*i), m.Call(*i)); }
|
2016-06-17 15:21:48 +00:00
|
|
|
}
|
|
|
|
|
2016-06-30 08:41:05 +00:00
|
|
|
TEST(RunFloat64Sinh) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Sinh(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::sinh(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-30 08:41:05 +00:00
|
|
|
}
|
|
|
|
|
2016-06-20 05:51:37 +00:00
|
|
|
TEST(RunFloat64Tan) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Tan(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(base::ieee754::tan(*i), m.Call(*i)); }
|
2016-06-20 05:51:37 +00:00
|
|
|
}
|
|
|
|
|
2016-06-30 08:41:05 +00:00
|
|
|
TEST(RunFloat64Tanh) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
|
|
|
m.Return(m.Float64Tanh(m.Parameter(0)));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
|
|
|
|
CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
|
2017-08-11 11:22:28 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
|
|
|
CHECK_DOUBLE_EQ(base::ieee754::tanh(*i), m.Call(*i));
|
|
|
|
}
|
2016-06-30 08:41:05 +00:00
|
|
|
}
|
|
|
|
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
static double two_30 = 1 << 30; // 2^30 is a smi boundary.
|
|
|
|
static double two_52 = two_30 * (1 << 22); // 2^52 is a precision boundary.
|
|
|
|
static double kValues[] = {0.1,
|
|
|
|
0.2,
|
|
|
|
0.49999999999999994,
|
|
|
|
0.5,
|
|
|
|
0.7,
|
|
|
|
1.0 - std::numeric_limits<double>::epsilon(),
|
|
|
|
-0.1,
|
|
|
|
-0.49999999999999994,
|
|
|
|
-0.5,
|
|
|
|
-0.7,
|
|
|
|
1.1,
|
|
|
|
1.0 + std::numeric_limits<double>::epsilon(),
|
|
|
|
1.5,
|
|
|
|
1.7,
|
|
|
|
-1,
|
|
|
|
-1 + std::numeric_limits<double>::epsilon(),
|
|
|
|
-1 - std::numeric_limits<double>::epsilon(),
|
|
|
|
-1.1,
|
|
|
|
-1.5,
|
|
|
|
-1.7,
|
|
|
|
std::numeric_limits<double>::min(),
|
|
|
|
-std::numeric_limits<double>::min(),
|
|
|
|
std::numeric_limits<double>::max(),
|
|
|
|
-std::numeric_limits<double>::max(),
|
|
|
|
std::numeric_limits<double>::infinity(),
|
|
|
|
-std::numeric_limits<double>::infinity(),
|
|
|
|
two_30,
|
|
|
|
two_30 + 0.1,
|
|
|
|
two_30 + 0.5,
|
|
|
|
two_30 + 0.7,
|
|
|
|
two_30 - 1,
|
|
|
|
two_30 - 1 + 0.1,
|
|
|
|
two_30 - 1 + 0.5,
|
|
|
|
two_30 - 1 + 0.7,
|
|
|
|
-two_30,
|
|
|
|
-two_30 + 0.1,
|
|
|
|
-two_30 + 0.5,
|
|
|
|
-two_30 + 0.7,
|
|
|
|
-two_30 + 1,
|
|
|
|
-two_30 + 1 + 0.1,
|
|
|
|
-two_30 + 1 + 0.5,
|
|
|
|
-two_30 + 1 + 0.7,
|
|
|
|
two_52,
|
|
|
|
two_52 + 0.1,
|
|
|
|
two_52 + 0.5,
|
|
|
|
two_52 + 0.5,
|
|
|
|
two_52 + 0.7,
|
|
|
|
two_52 + 0.7,
|
|
|
|
two_52 - 1,
|
|
|
|
two_52 - 1 + 0.1,
|
|
|
|
two_52 - 1 + 0.5,
|
|
|
|
two_52 - 1 + 0.7,
|
|
|
|
-two_52,
|
|
|
|
-two_52 + 0.1,
|
|
|
|
-two_52 + 0.5,
|
|
|
|
-two_52 + 0.7,
|
|
|
|
-two_52 + 1,
|
|
|
|
-two_52 + 1 + 0.1,
|
|
|
|
-two_52 + 1 + 0.5,
|
|
|
|
-two_52 + 1 + 0.7,
|
|
|
|
two_30,
|
|
|
|
two_30 - 0.1,
|
|
|
|
two_30 - 0.5,
|
|
|
|
two_30 - 0.7,
|
|
|
|
two_30 - 1,
|
|
|
|
two_30 - 1 - 0.1,
|
|
|
|
two_30 - 1 - 0.5,
|
|
|
|
two_30 - 1 - 0.7,
|
|
|
|
-two_30,
|
|
|
|
-two_30 - 0.1,
|
|
|
|
-two_30 - 0.5,
|
|
|
|
-two_30 - 0.7,
|
|
|
|
-two_30 + 1,
|
|
|
|
-two_30 + 1 - 0.1,
|
|
|
|
-two_30 + 1 - 0.5,
|
|
|
|
-two_30 + 1 - 0.7,
|
|
|
|
two_52,
|
|
|
|
two_52 - 0.1,
|
|
|
|
two_52 - 0.5,
|
|
|
|
two_52 - 0.5,
|
|
|
|
two_52 - 0.7,
|
|
|
|
two_52 - 0.7,
|
|
|
|
two_52 - 1,
|
|
|
|
two_52 - 1 - 0.1,
|
|
|
|
two_52 - 1 - 0.5,
|
|
|
|
two_52 - 1 - 0.7,
|
|
|
|
-two_52,
|
|
|
|
-two_52 - 0.1,
|
|
|
|
-two_52 - 0.5,
|
|
|
|
-two_52 - 0.7,
|
|
|
|
-two_52 + 1,
|
|
|
|
-two_52 + 1 - 0.1,
|
|
|
|
-two_52 + 1 - 0.5,
|
|
|
|
-two_52 + 1 - 0.7};
|
|
|
|
|
|
|
|
|
2015-11-25 11:05:22 +00:00
|
|
|
TEST(RunFloat32RoundDown) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
|
2015-11-25 11:05:22 +00:00
|
|
|
if (!m.machine()->Float32RoundDown().IsSupported()) return;
|
|
|
|
|
|
|
|
m.Return(m.Float32RoundDown(m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(floorf(*i), m.Call(*i)); }
|
2015-11-25 11:05:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-10 08:42:47 +00:00
|
|
|
TEST(RunFloat64RoundDown1) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-06-23 10:35:33 +00:00
|
|
|
if (!m.machine()->Float64RoundDown().IsSupported()) return;
|
2015-11-09 17:41:35 +00:00
|
|
|
|
|
|
|
m.Return(m.Float64RoundDown(m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(floor(*i), m.Call(*i)); }
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-10 08:42:47 +00:00
|
|
|
TEST(RunFloat64RoundDown2) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-06-23 10:35:33 +00:00
|
|
|
if (!m.machine()->Float64RoundDown().IsSupported()) return;
|
2015-11-16 10:37:24 +00:00
|
|
|
m.Return(m.Float64Sub(m.Float64Constant(-0.0),
|
|
|
|
m.Float64RoundDown(m.Float64Sub(m.Float64Constant(-0.0),
|
|
|
|
m.Parameter(0)))));
|
|
|
|
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
for (size_t i = 0; i < arraysize(kValues); ++i) {
|
2015-11-25 19:28:42 +00:00
|
|
|
CHECK_EQ(ceil(kValues[i]), m.Call(kValues[i]));
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-25 11:07:50 +00:00
|
|
|
TEST(RunFloat32RoundUp) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
|
2015-11-25 11:07:50 +00:00
|
|
|
if (!m.machine()->Float32RoundUp().IsSupported()) return;
|
|
|
|
m.Return(m.Float32RoundUp(m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(ceilf(*i), m.Call(*i)); }
|
2015-11-25 11:07:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-16 10:37:24 +00:00
|
|
|
TEST(RunFloat64RoundUp) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-11-16 10:37:24 +00:00
|
|
|
if (!m.machine()->Float64RoundUp().IsSupported()) return;
|
|
|
|
m.Return(m.Float64RoundUp(m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ceil(*i), m.Call(*i)); }
|
2015-11-16 10:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-25 21:12:44 +00:00
|
|
|
TEST(RunFloat32RoundTiesEven) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
|
2015-11-25 21:12:44 +00:00
|
|
|
if (!m.machine()->Float32RoundTiesEven().IsSupported()) return;
|
|
|
|
m.Return(m.Float32RoundTiesEven(m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(nearbyint(*i), m.Call(*i)); }
|
2015-11-25 21:12:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
[turbofan] Added the optional Float64RoundTiesEven operator to turbofan.
The TiesEven rounding mode rounds float64 numbers to the nearest
integer. If there are two nearest integers, then the number is rounded
to the even one. This is the default rounding mode according to
IEEE~754.
I implemented the operator on ia32, x64, arm, arm64, mips, and mips64.
I think there is a bug in the current implementation of the ppc
simulator, which kept me from implementing the operator on ppc.
According to my understanding of the ppc instruction manual, the FRIN
instruction provides the right behavior for Float64RoundTiesEven. In the
simulator, however, FRIN provides a different semantics. If there are
two nearest integers, then the simulator returns the one which is
further away form 0.
Review URL: https://codereview.chromium.org/1440293002
Cr-Commit-Position: refs/heads/master@{#32005}
2015-11-16 11:31:18 +00:00
|
|
|
TEST(RunFloat64RoundTiesEven) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
[turbofan] Added the optional Float64RoundTiesEven operator to turbofan.
The TiesEven rounding mode rounds float64 numbers to the nearest
integer. If there are two nearest integers, then the number is rounded
to the even one. This is the default rounding mode according to
IEEE~754.
I implemented the operator on ia32, x64, arm, arm64, mips, and mips64.
I think there is a bug in the current implementation of the ppc
simulator, which kept me from implementing the operator on ppc.
According to my understanding of the ppc instruction manual, the FRIN
instruction provides the right behavior for Float64RoundTiesEven. In the
simulator, however, FRIN provides a different semantics. If there are
two nearest integers, then the simulator returns the one which is
further away form 0.
Review URL: https://codereview.chromium.org/1440293002
Cr-Commit-Position: refs/heads/master@{#32005}
2015-11-16 11:31:18 +00:00
|
|
|
if (!m.machine()->Float64RoundTiesEven().IsSupported()) return;
|
|
|
|
m.Return(m.Float64RoundTiesEven(m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(nearbyint(*i), m.Call(*i)); }
|
[turbofan] Added the optional Float64RoundTiesEven operator to turbofan.
The TiesEven rounding mode rounds float64 numbers to the nearest
integer. If there are two nearest integers, then the number is rounded
to the even one. This is the default rounding mode according to
IEEE~754.
I implemented the operator on ia32, x64, arm, arm64, mips, and mips64.
I think there is a bug in the current implementation of the ppc
simulator, which kept me from implementing the operator on ppc.
According to my understanding of the ppc instruction manual, the FRIN
instruction provides the right behavior for Float64RoundTiesEven. In the
simulator, however, FRIN provides a different semantics. If there are
two nearest integers, then the simulator returns the one which is
further away form 0.
Review URL: https://codereview.chromium.org/1440293002
Cr-Commit-Position: refs/heads/master@{#32005}
2015-11-16 11:31:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-25 19:28:42 +00:00
|
|
|
TEST(RunFloat32RoundTruncate) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
|
2015-11-25 19:28:42 +00:00
|
|
|
if (!m.machine()->Float32RoundTruncate().IsSupported()) return;
|
|
|
|
|
|
|
|
m.Return(m.Float32RoundTruncate(m.Parameter(0)));
|
|
|
|
|
2016-03-07 12:29:06 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(truncf(*i), m.Call(*i)); }
|
2015-11-25 19:28:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
TEST(RunFloat64RoundTruncate) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-06-23 10:35:33 +00:00
|
|
|
if (!m.machine()->Float64RoundTruncate().IsSupported()) return;
|
2015-11-16 10:37:24 +00:00
|
|
|
m.Return(m.Float64RoundTruncate(m.Parameter(0)));
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
for (size_t i = 0; i < arraysize(kValues); ++i) {
|
2015-11-16 10:37:24 +00:00
|
|
|
CHECK_EQ(trunc(kValues[i]), m.Call(kValues[i]));
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunFloat64RoundTiesAway) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
|
2015-06-23 10:35:33 +00:00
|
|
|
if (!m.machine()->Float64RoundTiesAway().IsSupported()) return;
|
2015-11-16 10:37:24 +00:00
|
|
|
m.Return(m.Float64RoundTiesAway(m.Parameter(0)));
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
for (size_t i = 0; i < arraysize(kValues); ++i) {
|
2015-11-16 10:37:24 +00:00
|
|
|
CHECK_EQ(round(kValues[i]), m.Call(kValues[i]));
|
Add floor, ceil, round (truncate) instructions for ia32, x64 (if SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
R=bmeurer@chromium.org, dcarney@chromium.org, mstarzinger@chromium.org, rodolph.perfetta@arm.com
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
Cr-Commit-Position: refs/heads/master@{#25018}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-10-30 14:15:20 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-26 07:18:26 +00:00
|
|
|
|
2015-06-25 08:32:06 +00:00
|
|
|
|
|
|
|
#if !USE_SIMULATOR
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2017-12-02 00:30:37 +00:00
|
|
|
int32_t const kMagicFoo0 = 0xDEADBEEF;
|
2015-06-25 08:32:06 +00:00
|
|
|
|
|
|
|
int32_t foo0() { return kMagicFoo0; }
|
|
|
|
|
|
|
|
|
|
|
|
int32_t foo1(int32_t x) { return x; }
|
|
|
|
|
|
|
|
|
|
|
|
int32_t foo2(int32_t x, int32_t y) { return x - y; }
|
|
|
|
|
|
|
|
|
|
|
|
int32_t foo8(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f,
|
|
|
|
int32_t g, int32_t h) {
|
|
|
|
return a + b + c + d + e + f + g + h;
|
|
|
|
}
|
|
|
|
|
2017-04-21 09:30:14 +00:00
|
|
|
int32_t foo9(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f,
|
|
|
|
int32_t g, int32_t h, int32_t i) {
|
|
|
|
return a + b + c + d + e + f + g + h + i;
|
|
|
|
}
|
|
|
|
|
2015-06-25 08:32:06 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunCallCFunction0) {
|
|
|
|
auto* foo0_ptr = &foo0;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* function = m.LoadFromPointer(&foo0_ptr, MachineType::Pointer());
|
|
|
|
m.Return(m.CallCFunction0(MachineType::Int32(), function));
|
2015-06-25 08:32:06 +00:00
|
|
|
CHECK_EQ(kMagicFoo0, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunCallCFunction1) {
|
|
|
|
auto* foo1_ptr = &foo1;
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
|
|
|
Node* function = m.LoadFromPointer(&foo1_ptr, MachineType::Pointer());
|
|
|
|
m.Return(m.CallCFunction1(MachineType::Int32(), MachineType::Int32(),
|
|
|
|
function, m.Parameter(0)));
|
2015-06-25 08:32:06 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
int32_t const expected = *i;
|
|
|
|
CHECK_EQ(expected, m.Call(expected));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunCallCFunction2) {
|
|
|
|
auto* foo2_ptr = &foo2;
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
|
|
|
|
MachineType::Int32());
|
|
|
|
Node* function = m.LoadFromPointer(&foo2_ptr, MachineType::Pointer());
|
|
|
|
m.Return(m.CallCFunction2(MachineType::Int32(), MachineType::Int32(),
|
|
|
|
MachineType::Int32(), function, m.Parameter(0),
|
|
|
|
m.Parameter(1)));
|
2015-06-25 08:32:06 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
int32_t const x = *i;
|
|
|
|
FOR_INT32_INPUTS(j) {
|
|
|
|
int32_t const y = *j;
|
|
|
|
CHECK_EQ(x - y, m.Call(x, y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunCallCFunction8) {
|
|
|
|
auto* foo8_ptr = &foo8;
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
|
|
|
Node* function = m.LoadFromPointer(&foo8_ptr, MachineType::Pointer());
|
2015-06-25 08:32:06 +00:00
|
|
|
Node* param = m.Parameter(0);
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Return(m.CallCFunction8(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
|
|
|
|
function, param, param, param, param, param, param, param, param));
|
2015-06-25 08:32:06 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
int32_t const x = *i;
|
|
|
|
CHECK_EQ(x * 8, m.Call(x));
|
|
|
|
}
|
|
|
|
}
|
2017-04-21 09:30:14 +00:00
|
|
|
|
|
|
|
TEST(RunCallCFunction9) {
|
|
|
|
auto* foo9_ptr = &foo9;
|
|
|
|
RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
|
|
|
Node* function = m.LoadFromPointer(&foo9_ptr, MachineType::Pointer());
|
|
|
|
Node* param = m.Parameter(0);
|
|
|
|
m.Return(m.CallCFunction9(
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
|
|
|
|
MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
|
|
|
|
MachineType::Int32(), function, param,
|
|
|
|
m.Int32Add(param, m.Int32Constant(1)),
|
|
|
|
m.Int32Add(param, m.Int32Constant(2)),
|
|
|
|
m.Int32Add(param, m.Int32Constant(3)),
|
|
|
|
m.Int32Add(param, m.Int32Constant(4)),
|
|
|
|
m.Int32Add(param, m.Int32Constant(5)),
|
|
|
|
m.Int32Add(param, m.Int32Constant(6)),
|
|
|
|
m.Int32Add(param, m.Int32Constant(7)),
|
|
|
|
m.Int32Add(param, m.Int32Constant(8))));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
int32_t const x = *i;
|
|
|
|
CHECK_EQ(x * 9 + 36, m.Call(x));
|
|
|
|
}
|
|
|
|
}
|
2015-06-25 08:32:06 +00:00
|
|
|
#endif // USE_SIMULATOR
|
2015-09-03 10:45:35 +00:00
|
|
|
|
|
|
|
#if V8_TARGET_ARCH_64_BIT
|
2015-09-23 11:04:44 +00:00
|
|
|
// TODO(titzer): run int64 tests on all platforms when supported.
|
2015-09-21 14:00:51 +00:00
|
|
|
|
[turbofan] Initial Word64 support in representation selection.
This adds support to TurboFan's representation selection for the Word64
representation, and makes use of that to handle indices for memory access
and allocation instructions (i.e. LoadElement, StoreElement, Allocate,
etc.). These instructions had previously used Word32 as representation
for the indices / sizes, and then internally converted it to the correct
representation (aka Word64 on 64-bit architectures) later on, but that
was kind of brittle, and sometimes led to weird generated code.
The change thus only adds support to convert integer values in the safe
integer range from all kinds of representations to Word64 (on 64-bit
architectures). We don't yet handle the opposite direction and none of
the representation selection heuristics for the numeric operations were
changed so far. This will be done in follow-up CLs.
This CL itself is supposed to be neutral wrt. functionality, and only
serves as a starting point, and a cleanup for the (weird) implicit
Word64 index/size handling.
Bug: v8:7881, v8:8015, v8:8171
Design-Document: http://bit.ly/turbofan-word64
Change-Id: I3c6961a0e96cbc3fb8ac9d3e1be8f2e5c89bfd25
Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel
Reviewed-on: https://chromium-review.googlesource.com/1224932
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55886}
2018-09-14 07:32:02 +00:00
|
|
|
TEST(RunChangeFloat64ToInt64) {
|
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
|
|
|
|
m.Return(m.ChangeFloat64ToInt64(m.Parameter(0)));
|
|
|
|
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
double input = static_cast<double>(*i);
|
|
|
|
if (static_cast<int64_t>(input) == *i) {
|
|
|
|
CHECK_EQ(static_cast<int64_t>(input), m.Call(input));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-14 15:28:42 +00:00
|
|
|
TEST(RunChangeInt64ToFloat64) {
|
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Int64());
|
|
|
|
m.Return(m.ChangeInt64ToFloat64(m.Parameter(0)));
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
double output = static_cast<double>(*i);
|
|
|
|
if (static_cast<int64_t>(output) == *i) {
|
|
|
|
CHECK_EQ(output, m.Call(*i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-21 14:00:51 +00:00
|
|
|
TEST(RunBitcastInt64ToFloat64) {
|
|
|
|
int64_t input = 1;
|
2017-10-20 09:12:46 +00:00
|
|
|
Float64 output;
|
2015-09-21 14:00:51 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
m.StoreToPointer(
|
2017-10-20 09:12:46 +00:00
|
|
|
output.get_bits_address(), MachineRepresentation::kFloat64,
|
2015-12-10 09:03:30 +00:00
|
|
|
m.BitcastInt64ToFloat64(m.LoadFromPointer(&input, MachineType::Int64())));
|
2015-09-21 14:00:51 +00:00
|
|
|
m.Return(m.Int32Constant(11));
|
2015-09-23 11:04:44 +00:00
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
input = *i;
|
2015-09-21 14:00:51 +00:00
|
|
|
CHECK_EQ(11, m.Call());
|
2017-10-20 09:12:46 +00:00
|
|
|
Float64 expected = Float64::FromBits(input);
|
|
|
|
CHECK_EQ(expected.get_bits(), output.get_bits());
|
2015-09-21 14:00:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunBitcastFloat64ToInt64) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
|
2015-11-19 08:26:40 +00:00
|
|
|
|
|
|
|
m.Return(m.BitcastFloat64ToInt64(m.Parameter(0)));
|
|
|
|
FOR_FLOAT64_INPUTS(i) { CHECK_EQ(bit_cast<int64_t>(*i), m.Call(*i)); }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-10 08:12:14 +00:00
|
|
|
TEST(RunTryTruncateFloat32ToInt64WithoutCheck) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float32());
|
2015-12-10 08:12:14 +00:00
|
|
|
m.Return(m.TryTruncateFloat32ToInt64(m.Parameter(0)));
|
2015-11-26 10:28:21 +00:00
|
|
|
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
float input = static_cast<float>(*i);
|
2015-12-16 15:34:24 +00:00
|
|
|
if (input < static_cast<float>(INT64_MAX) &&
|
|
|
|
input >= static_cast<float>(INT64_MIN)) {
|
2015-11-26 10:28:21 +00:00
|
|
|
CHECK_EQ(static_cast<int64_t>(input), m.Call(input));
|
|
|
|
}
|
|
|
|
}
|
2015-12-10 08:12:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunTryTruncateFloat32ToInt64WithCheck) {
|
|
|
|
int64_t success = 0;
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float32());
|
2015-12-10 08:12:14 +00:00
|
|
|
Node* trunc = m.TryTruncateFloat32ToInt64(m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, trunc);
|
|
|
|
Node* check = m.Projection(1, trunc);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&success, MachineRepresentation::kWord64, check);
|
2015-12-10 08:12:14 +00:00
|
|
|
m.Return(val);
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2015-12-16 15:34:24 +00:00
|
|
|
if (*i < static_cast<float>(INT64_MAX) &&
|
|
|
|
*i >= static_cast<float>(INT64_MIN)) {
|
2015-12-10 08:12:14 +00:00
|
|
|
CHECK_EQ(static_cast<int64_t>(*i), m.Call(*i));
|
|
|
|
CHECK_NE(0, success);
|
|
|
|
} else {
|
|
|
|
m.Call(*i);
|
|
|
|
CHECK_EQ(0, success);
|
2015-11-26 10:28:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-07 12:12:19 +00:00
|
|
|
TEST(RunTryTruncateFloat64ToInt64WithoutCheck) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
|
2015-12-07 12:12:19 +00:00
|
|
|
m.Return(m.TryTruncateFloat64ToInt64(m.Parameter(0)));
|
2015-11-19 08:26:40 +00:00
|
|
|
|
|
|
|
FOR_INT64_INPUTS(i) {
|
|
|
|
double input = static_cast<double>(*i);
|
|
|
|
CHECK_EQ(static_cast<int64_t>(input), m.Call(input));
|
2015-09-21 14:00:51 +00:00
|
|
|
}
|
|
|
|
}
|
2015-11-03 15:46:00 +00:00
|
|
|
|
|
|
|
|
2015-12-07 12:12:19 +00:00
|
|
|
TEST(RunTryTruncateFloat64ToInt64WithCheck) {
|
|
|
|
int64_t success = 0;
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
|
2015-12-07 12:12:19 +00:00
|
|
|
Node* trunc = m.TryTruncateFloat64ToInt64(m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, trunc);
|
|
|
|
Node* check = m.Projection(1, trunc);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&success, MachineRepresentation::kWord64, check);
|
2015-12-07 12:12:19 +00:00
|
|
|
m.Return(val);
|
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-12-16 15:34:24 +00:00
|
|
|
if (*i < static_cast<double>(INT64_MAX) &&
|
|
|
|
*i >= static_cast<double>(INT64_MIN)) {
|
2015-12-09 11:15:18 +00:00
|
|
|
// Conversions within this range should succeed.
|
2015-12-07 12:12:19 +00:00
|
|
|
CHECK_EQ(static_cast<int64_t>(*i), m.Call(*i));
|
|
|
|
CHECK_NE(0, success);
|
|
|
|
} else {
|
|
|
|
m.Call(*i);
|
|
|
|
CHECK_EQ(0, success);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-17 10:24:36 +00:00
|
|
|
TEST(RunTryTruncateFloat32ToUint64WithoutCheck) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<uint64_t> m(MachineType::Float32());
|
2015-12-11 14:06:59 +00:00
|
|
|
m.Return(m.TryTruncateFloat32ToUint64(m.Parameter(0)));
|
2015-11-27 15:01:34 +00:00
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(i) {
|
|
|
|
float input = static_cast<float>(*i);
|
2015-12-17 10:24:36 +00:00
|
|
|
// This condition on 'input' is required because
|
|
|
|
// static_cast<float>(UINT64_MAX) results in a value outside uint64 range.
|
|
|
|
if (input < static_cast<float>(UINT64_MAX)) {
|
2015-11-27 15:01:34 +00:00
|
|
|
CHECK_EQ(static_cast<uint64_t>(input), m.Call(input));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-11 14:06:59 +00:00
|
|
|
TEST(RunTryTruncateFloat32ToUint64WithCheck) {
|
|
|
|
int64_t success = 0;
|
|
|
|
BufferedRawMachineAssemblerTester<uint64_t> m(MachineType::Float32());
|
|
|
|
Node* trunc = m.TryTruncateFloat32ToUint64(m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, trunc);
|
|
|
|
Node* check = m.Projection(1, trunc);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&success, MachineRepresentation::kWord64, check);
|
2015-12-11 14:06:59 +00:00
|
|
|
m.Return(val);
|
|
|
|
|
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
2015-12-17 10:24:36 +00:00
|
|
|
if (*i < static_cast<float>(UINT64_MAX) && *i > -1.0) {
|
2015-12-11 14:06:59 +00:00
|
|
|
// Conversions within this range should succeed.
|
|
|
|
CHECK_EQ(static_cast<uint64_t>(*i), m.Call(*i));
|
|
|
|
CHECK_NE(0, success);
|
|
|
|
} else {
|
|
|
|
m.Call(*i);
|
|
|
|
CHECK_EQ(0, success);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-09 11:15:18 +00:00
|
|
|
TEST(RunTryTruncateFloat64ToUint64WithoutCheck) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<uint64_t> m(MachineType::Float64());
|
2016-03-02 17:59:31 +00:00
|
|
|
m.Return(m.TryTruncateFloat64ToUint64(m.Parameter(0)));
|
2015-11-19 20:42:03 +00:00
|
|
|
|
|
|
|
FOR_UINT64_INPUTS(j) {
|
|
|
|
double input = static_cast<double>(*j);
|
|
|
|
|
2015-12-17 10:24:36 +00:00
|
|
|
if (input < static_cast<float>(UINT64_MAX)) {
|
2015-11-19 20:42:03 +00:00
|
|
|
CHECK_EQ(static_cast<uint64_t>(input), m.Call(input));
|
|
|
|
}
|
|
|
|
}
|
2015-12-09 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST(RunTryTruncateFloat64ToUint64WithCheck) {
|
|
|
|
int64_t success = 0;
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
|
2015-12-09 11:15:18 +00:00
|
|
|
Node* trunc = m.TryTruncateFloat64ToUint64(m.Parameter(0));
|
|
|
|
Node* val = m.Projection(0, trunc);
|
|
|
|
Node* check = m.Projection(1, trunc);
|
2015-12-11 15:34:00 +00:00
|
|
|
m.StoreToPointer(&success, MachineRepresentation::kWord64, check);
|
2015-12-09 11:15:18 +00:00
|
|
|
m.Return(val);
|
2015-11-19 20:42:03 +00:00
|
|
|
|
|
|
|
FOR_FLOAT64_INPUTS(i) {
|
2015-12-17 10:24:36 +00:00
|
|
|
if (*i < 18446744073709551616.0 && *i > -1) {
|
2015-12-09 11:15:18 +00:00
|
|
|
// Conversions within this range should succeed.
|
2016-11-11 12:00:34 +00:00
|
|
|
CHECK_EQ(static_cast<uint64_t>(*i), static_cast<uint64_t>(m.Call(*i)));
|
2015-12-09 11:15:18 +00:00
|
|
|
CHECK_NE(0, success);
|
|
|
|
} else {
|
|
|
|
m.Call(*i);
|
|
|
|
CHECK_EQ(0, success);
|
2015-11-19 20:42:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-10 20:39:18 +00:00
|
|
|
TEST(RunRoundInt64ToFloat32) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Int64());
|
2015-11-10 20:39:18 +00:00
|
|
|
m.Return(m.RoundInt64ToFloat32(m.Parameter(0)));
|
|
|
|
FOR_INT64_INPUTS(i) { CHECK_EQ(static_cast<float>(*i), m.Call(*i)); }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-03 15:46:00 +00:00
|
|
|
TEST(RunRoundInt64ToFloat64) {
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Int64());
|
2015-11-03 15:46:00 +00:00
|
|
|
m.Return(m.RoundInt64ToFloat64(m.Parameter(0)));
|
|
|
|
FOR_INT64_INPUTS(i) { CHECK_EQ(static_cast<double>(*i), m.Call(*i)); }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-11 19:12:25 +00:00
|
|
|
TEST(RunRoundUint64ToFloat64) {
|
2015-11-17 13:07:14 +00:00
|
|
|
struct {
|
|
|
|
uint64_t input;
|
|
|
|
uint64_t expected;
|
|
|
|
} values[] = {{0x0, 0x0},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0x1, 0x3FF0000000000000},
|
|
|
|
{0xFFFFFFFF, 0x41EFFFFFFFE00000},
|
|
|
|
{0x1B09788B, 0x41BB09788B000000},
|
|
|
|
{0x4C5FCE8, 0x419317F3A0000000},
|
|
|
|
{0xCC0DE5BF, 0x41E981BCB7E00000},
|
2015-11-17 13:07:14 +00:00
|
|
|
{0x2, 0x4000000000000000},
|
|
|
|
{0x3, 0x4008000000000000},
|
|
|
|
{0x4, 0x4010000000000000},
|
|
|
|
{0x5, 0x4014000000000000},
|
|
|
|
{0x8, 0x4020000000000000},
|
|
|
|
{0x9, 0x4022000000000000},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0xFFFFFFFFFFFFFFFF, 0x43F0000000000000},
|
|
|
|
{0xFFFFFFFFFFFFFFFE, 0x43F0000000000000},
|
|
|
|
{0xFFFFFFFFFFFFFFFD, 0x43F0000000000000},
|
|
|
|
{0x100000000, 0x41F0000000000000},
|
|
|
|
{0xFFFFFFFF00000000, 0x43EFFFFFFFE00000},
|
|
|
|
{0x1B09788B00000000, 0x43BB09788B000000},
|
|
|
|
{0x4C5FCE800000000, 0x439317F3A0000000},
|
|
|
|
{0xCC0DE5BF00000000, 0x43E981BCB7E00000},
|
2015-11-17 13:07:14 +00:00
|
|
|
{0x200000000, 0x4200000000000000},
|
|
|
|
{0x300000000, 0x4208000000000000},
|
|
|
|
{0x400000000, 0x4210000000000000},
|
|
|
|
{0x500000000, 0x4214000000000000},
|
|
|
|
{0x800000000, 0x4220000000000000},
|
|
|
|
{0x900000000, 0x4222000000000000},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0x273A798E187937A3, 0x43C39D3CC70C3C9C},
|
|
|
|
{0xECE3AF835495A16B, 0x43ED9C75F06A92B4},
|
|
|
|
{0xB668ECC11223344, 0x43A6CD1D98224467},
|
|
|
|
{0x9E, 0x4063C00000000000},
|
|
|
|
{0x43, 0x4050C00000000000},
|
|
|
|
{0xAF73, 0x40E5EE6000000000},
|
|
|
|
{0x116B, 0x40B16B0000000000},
|
|
|
|
{0x658ECC, 0x415963B300000000},
|
|
|
|
{0x2B3B4C, 0x41459DA600000000},
|
|
|
|
{0x88776655, 0x41E10EECCAA00000},
|
|
|
|
{0x70000000, 0x41DC000000000000},
|
|
|
|
{0x7200000, 0x419C800000000000},
|
|
|
|
{0x7FFFFFFF, 0x41DFFFFFFFC00000},
|
|
|
|
{0x56123761, 0x41D5848DD8400000},
|
|
|
|
{0x7FFFFF00, 0x41DFFFFFC0000000},
|
|
|
|
{0x761C4761EEEEEEEE, 0x43DD8711D87BBBBC},
|
|
|
|
{0x80000000EEEEEEEE, 0x43E00000001DDDDE},
|
|
|
|
{0x88888888DDDDDDDD, 0x43E11111111BBBBC},
|
|
|
|
{0xA0000000DDDDDDDD, 0x43E40000001BBBBC},
|
|
|
|
{0xDDDDDDDDAAAAAAAA, 0x43EBBBBBBBB55555},
|
|
|
|
{0xE0000000AAAAAAAA, 0x43EC000000155555},
|
|
|
|
{0xEEEEEEEEEEEEEEEE, 0x43EDDDDDDDDDDDDE},
|
|
|
|
{0xFFFFFFFDEEEEEEEE, 0x43EFFFFFFFBDDDDE},
|
|
|
|
{0xF0000000DDDDDDDD, 0x43EE0000001BBBBC},
|
|
|
|
{0x7FFFFFDDDDDDDD, 0x435FFFFFF7777777},
|
|
|
|
{0x3FFFFFAAAAAAAA, 0x434FFFFFD5555555},
|
|
|
|
{0x1FFFFFAAAAAAAA, 0x433FFFFFAAAAAAAA},
|
|
|
|
{0xFFFFF, 0x412FFFFE00000000},
|
|
|
|
{0x7FFFF, 0x411FFFFC00000000},
|
|
|
|
{0x3FFFF, 0x410FFFF800000000},
|
|
|
|
{0x1FFFF, 0x40FFFFF000000000},
|
|
|
|
{0xFFFF, 0x40EFFFE000000000},
|
|
|
|
{0x7FFF, 0x40DFFFC000000000},
|
|
|
|
{0x3FFF, 0x40CFFF8000000000},
|
|
|
|
{0x1FFF, 0x40BFFF0000000000},
|
|
|
|
{0xFFF, 0x40AFFE0000000000},
|
|
|
|
{0x7FF, 0x409FFC0000000000},
|
|
|
|
{0x3FF, 0x408FF80000000000},
|
|
|
|
{0x1FF, 0x407FF00000000000},
|
|
|
|
{0x3FFFFFFFFFFF, 0x42CFFFFFFFFFFF80},
|
|
|
|
{0x1FFFFFFFFFFF, 0x42BFFFFFFFFFFF00},
|
|
|
|
{0xFFFFFFFFFFF, 0x42AFFFFFFFFFFE00},
|
|
|
|
{0x7FFFFFFFFFF, 0x429FFFFFFFFFFC00},
|
|
|
|
{0x3FFFFFFFFFF, 0x428FFFFFFFFFF800},
|
|
|
|
{0x1FFFFFFFFFF, 0x427FFFFFFFFFF000},
|
|
|
|
{0x8000008000000000, 0x43E0000010000000},
|
|
|
|
{0x8000008000000001, 0x43E0000010000000},
|
|
|
|
{0x8000000000000400, 0x43E0000000000000},
|
|
|
|
{0x8000000000000401, 0x43E0000000000001}};
|
2015-11-17 13:07:14 +00:00
|
|
|
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<double> m(MachineType::Uint64());
|
2015-11-11 19:12:25 +00:00
|
|
|
m.Return(m.RoundUint64ToFloat64(m.Parameter(0)));
|
2015-11-12 19:35:47 +00:00
|
|
|
|
2015-11-17 16:07:00 +00:00
|
|
|
for (size_t i = 0; i < arraysize(values); i++) {
|
2015-11-17 13:07:14 +00:00
|
|
|
CHECK_EQ(bit_cast<double>(values[i].expected), m.Call(values[i].input));
|
|
|
|
}
|
2015-11-11 19:12:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-17 11:51:27 +00:00
|
|
|
TEST(RunRoundUint64ToFloat32) {
|
|
|
|
struct {
|
|
|
|
uint64_t input;
|
|
|
|
uint32_t expected;
|
|
|
|
} values[] = {{0x0, 0x0},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0x1, 0x3F800000},
|
|
|
|
{0xFFFFFFFF, 0x4F800000},
|
|
|
|
{0x1B09788B, 0x4DD84BC4},
|
|
|
|
{0x4C5FCE8, 0x4C98BF9D},
|
|
|
|
{0xCC0DE5BF, 0x4F4C0DE6},
|
2015-11-17 11:51:27 +00:00
|
|
|
{0x2, 0x40000000},
|
|
|
|
{0x3, 0x40400000},
|
|
|
|
{0x4, 0x40800000},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0x5, 0x40A00000},
|
2015-11-17 11:51:27 +00:00
|
|
|
{0x8, 0x41000000},
|
|
|
|
{0x9, 0x41100000},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0xFFFFFFFFFFFFFFFF, 0x5F800000},
|
|
|
|
{0xFFFFFFFFFFFFFFFE, 0x5F800000},
|
|
|
|
{0xFFFFFFFFFFFFFFFD, 0x5F800000},
|
2015-11-17 11:51:27 +00:00
|
|
|
{0x0, 0x0},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0x100000000, 0x4F800000},
|
|
|
|
{0xFFFFFFFF00000000, 0x5F800000},
|
|
|
|
{0x1B09788B00000000, 0x5DD84BC4},
|
|
|
|
{0x4C5FCE800000000, 0x5C98BF9D},
|
|
|
|
{0xCC0DE5BF00000000, 0x5F4C0DE6},
|
2015-11-17 11:51:27 +00:00
|
|
|
{0x200000000, 0x50000000},
|
|
|
|
{0x300000000, 0x50400000},
|
|
|
|
{0x400000000, 0x50800000},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0x500000000, 0x50A00000},
|
2015-11-17 11:51:27 +00:00
|
|
|
{0x800000000, 0x51000000},
|
|
|
|
{0x900000000, 0x51100000},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0x273A798E187937A3, 0x5E1CE9E6},
|
|
|
|
{0xECE3AF835495A16B, 0x5F6CE3B0},
|
|
|
|
{0xB668ECC11223344, 0x5D3668ED},
|
|
|
|
{0x9E, 0x431E0000},
|
2015-11-17 11:51:27 +00:00
|
|
|
{0x43, 0x42860000},
|
2017-12-02 00:30:37 +00:00
|
|
|
{0xAF73, 0x472F7300},
|
|
|
|
{0x116B, 0x458B5800},
|
|
|
|
{0x658ECC, 0x4ACB1D98},
|
|
|
|
{0x2B3B4C, 0x4A2CED30},
|
|
|
|
{0x88776655, 0x4F087766},
|
|
|
|
{0x70000000, 0x4EE00000},
|
|
|
|
{0x7200000, 0x4CE40000},
|
|
|
|
{0x7FFFFFFF, 0x4F000000},
|
|
|
|
{0x56123761, 0x4EAC246F},
|
|
|
|
{0x7FFFFF00, 0x4EFFFFFE},
|
|
|
|
{0x761C4761EEEEEEEE, 0x5EEC388F},
|
|
|
|
{0x80000000EEEEEEEE, 0x5F000000},
|
|
|
|
{0x88888888DDDDDDDD, 0x5F088889},
|
|
|
|
{0xA0000000DDDDDDDD, 0x5F200000},
|
|
|
|
{0xDDDDDDDDAAAAAAAA, 0x5F5DDDDE},
|
|
|
|
{0xE0000000AAAAAAAA, 0x5F600000},
|
|
|
|
{0xEEEEEEEEEEEEEEEE, 0x5F6EEEEF},
|
|
|
|
{0xFFFFFFFDEEEEEEEE, 0x5F800000},
|
|
|
|
{0xF0000000DDDDDDDD, 0x5F700000},
|
|
|
|
{0x7FFFFFDDDDDDDD, 0x5B000000},
|
|
|
|
{0x3FFFFFAAAAAAAA, 0x5A7FFFFF},
|
|
|
|
{0x1FFFFFAAAAAAAA, 0x59FFFFFD},
|
|
|
|
{0xFFFFF, 0x497FFFF0},
|
|
|
|
{0x7FFFF, 0x48FFFFE0},
|
|
|
|
{0x3FFFF, 0x487FFFC0},
|
|
|
|
{0x1FFFF, 0x47FFFF80},
|
|
|
|
{0xFFFF, 0x477FFF00},
|
|
|
|
{0x7FFF, 0x46FFFE00},
|
|
|
|
{0x3FFF, 0x467FFC00},
|
|
|
|
{0x1FFF, 0x45FFF800},
|
|
|
|
{0xFFF, 0x457FF000},
|
|
|
|
{0x7FF, 0x44FFE000},
|
|
|
|
{0x3FF, 0x447FC000},
|
|
|
|
{0x1FF, 0x43FF8000},
|
|
|
|
{0x3FFFFFFFFFFF, 0x56800000},
|
|
|
|
{0x1FFFFFFFFFFF, 0x56000000},
|
|
|
|
{0xFFFFFFFFFFF, 0x55800000},
|
|
|
|
{0x7FFFFFFFFFF, 0x55000000},
|
|
|
|
{0x3FFFFFFFFFF, 0x54800000},
|
|
|
|
{0x1FFFFFFFFFF, 0x54000000},
|
|
|
|
{0x8000008000000000, 0x5F000000},
|
|
|
|
{0x8000008000000001, 0x5F000001},
|
|
|
|
{0x8000000000000400, 0x5F000000},
|
|
|
|
{0x8000000000000401, 0x5F000000}};
|
2015-11-17 11:51:27 +00:00
|
|
|
|
2015-12-10 09:03:30 +00:00
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Uint64());
|
2015-11-17 11:51:27 +00:00
|
|
|
m.Return(m.RoundUint64ToFloat32(m.Parameter(0)));
|
|
|
|
|
2015-11-17 16:07:00 +00:00
|
|
|
for (size_t i = 0; i < arraysize(values); i++) {
|
2015-11-17 11:51:27 +00:00
|
|
|
CHECK_EQ(bit_cast<float>(values[i].expected), m.Call(values[i].input));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-03 10:45:35 +00:00
|
|
|
#endif
|
2015-09-21 14:00:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
TEST(RunBitcastFloat32ToInt32) {
|
|
|
|
float input = 32.25;
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
2015-12-10 09:03:30 +00:00
|
|
|
m.Return(m.BitcastFloat32ToInt32(
|
|
|
|
m.LoadFromPointer(&input, MachineType::Float32())));
|
2015-09-21 14:00:51 +00:00
|
|
|
FOR_FLOAT32_INPUTS(i) {
|
|
|
|
input = *i;
|
|
|
|
int32_t expected = bit_cast<int32_t>(input);
|
|
|
|
CHECK_EQ(expected, m.Call());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
[turbofan] Add the RoundInt32ToFloat32 operator to turbofan.
The new operator converts an int32 input to float32. If the input cannot
be represented exactly in float32, the value is rounded using the
round-ties-even rounding mode (the default rounding mode).
I provide implementations of the new operator for x64, ia32, arm, arm64,
mips, mips64, ppc, and ppc64.
R=titzer@chromium.org, v8-arm-ports@googlegroups.com, v8-mips-ports@googlegroups.com, v8-ppc-ports@googlegroups.com
Review URL: https://codereview.chromium.org/1589363002
Cr-Commit-Position: refs/heads/master@{#33347}
2016-01-16 13:11:40 +00:00
|
|
|
TEST(RunRoundInt32ToFloat32) {
|
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Int32());
|
|
|
|
m.Return(m.RoundInt32ToFloat32(m.Parameter(0)));
|
2016-02-01 08:27:43 +00:00
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
volatile float expected = static_cast<float>(*i);
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
[turbofan] Add the RoundInt32ToFloat32 operator to turbofan.
The new operator converts an int32 input to float32. If the input cannot
be represented exactly in float32, the value is rounded using the
round-ties-even rounding mode (the default rounding mode).
I provide implementations of the new operator for x64, ia32, arm, arm64,
mips, mips64, ppc, and ppc64.
R=titzer@chromium.org, v8-arm-ports@googlegroups.com, v8-mips-ports@googlegroups.com, v8-ppc-ports@googlegroups.com
Review URL: https://codereview.chromium.org/1589363002
Cr-Commit-Position: refs/heads/master@{#33347}
2016-01-16 13:11:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-06 18:07:39 +00:00
|
|
|
TEST(RunRoundUint32ToFloat32) {
|
|
|
|
BufferedRawMachineAssemblerTester<float> m(MachineType::Uint32());
|
|
|
|
m.Return(m.RoundUint32ToFloat32(m.Parameter(0)));
|
2016-02-23 01:49:46 +00:00
|
|
|
FOR_UINT32_INPUTS(i) {
|
|
|
|
volatile float expected = static_cast<float>(*i);
|
|
|
|
CHECK_EQ(expected, m.Call(*i));
|
|
|
|
}
|
2016-02-06 18:07:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-21 14:00:51 +00:00
|
|
|
TEST(RunBitcastInt32ToFloat32) {
|
|
|
|
int32_t input = 1;
|
2017-10-20 09:12:46 +00:00
|
|
|
Float32 output;
|
2015-09-21 14:00:51 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
m.StoreToPointer(
|
2017-10-20 09:12:46 +00:00
|
|
|
output.get_bits_address(), MachineRepresentation::kFloat32,
|
2015-12-10 09:03:30 +00:00
|
|
|
m.BitcastInt32ToFloat32(m.LoadFromPointer(&input, MachineType::Int32())));
|
2015-09-21 14:00:51 +00:00
|
|
|
m.Return(m.Int32Constant(11));
|
|
|
|
FOR_INT32_INPUTS(i) {
|
|
|
|
input = *i;
|
|
|
|
CHECK_EQ(11, m.Call());
|
2017-10-20 09:12:46 +00:00
|
|
|
Float32 expected = Float32::FromBits(input);
|
|
|
|
CHECK_EQ(expected.get_bits(), output.get_bits());
|
2015-09-21 14:00:51 +00:00
|
|
|
}
|
|
|
|
}
|
2015-10-01 17:11:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
TEST(RunComputedCodeObject) {
|
2015-10-27 00:37:27 +00:00
|
|
|
GraphBuilderTester<int32_t> a;
|
2015-10-01 17:11:34 +00:00
|
|
|
a.Return(a.Int32Constant(33));
|
2015-10-27 00:37:27 +00:00
|
|
|
a.End();
|
|
|
|
Handle<Code> code_a = a.GetCode();
|
2015-10-01 17:11:34 +00:00
|
|
|
|
2015-10-27 00:37:27 +00:00
|
|
|
GraphBuilderTester<int32_t> b;
|
2015-10-01 17:11:34 +00:00
|
|
|
b.Return(b.Int32Constant(44));
|
2015-10-27 00:37:27 +00:00
|
|
|
b.End();
|
|
|
|
Handle<Code> code_b = b.GetCode();
|
2015-10-01 17:11:34 +00:00
|
|
|
|
2015-12-10 09:03:30 +00:00
|
|
|
RawMachineAssemblerTester<int32_t> r(MachineType::Int32());
|
2015-11-30 11:28:50 +00:00
|
|
|
RawMachineLabel tlabel;
|
|
|
|
RawMachineLabel flabel;
|
|
|
|
RawMachineLabel merge;
|
2015-10-01 17:11:34 +00:00
|
|
|
r.Branch(r.Parameter(0), &tlabel, &flabel);
|
|
|
|
r.Bind(&tlabel);
|
2015-10-27 00:37:27 +00:00
|
|
|
Node* fa = r.HeapConstant(code_a);
|
2015-10-01 17:11:34 +00:00
|
|
|
r.Goto(&merge);
|
|
|
|
r.Bind(&flabel);
|
2015-10-27 00:37:27 +00:00
|
|
|
Node* fb = r.HeapConstant(code_b);
|
2015-10-01 17:11:34 +00:00
|
|
|
r.Goto(&merge);
|
|
|
|
r.Bind(&merge);
|
2015-12-10 09:03:30 +00:00
|
|
|
Node* phi = r.Phi(MachineRepresentation::kWord32, fa, fb);
|
2015-10-01 17:11:34 +00:00
|
|
|
|
|
|
|
// TODO(titzer): all this descriptor hackery is just to call the above
|
|
|
|
// functions as code objects instead of direct addresses.
|
2018-01-16 09:26:02 +00:00
|
|
|
CSignatureOf<int32_t> sig;
|
2015-10-01 17:11:34 +00:00
|
|
|
CallDescriptor* c = Linkage::GetSimplifiedCDescriptor(r.zone(), &sig);
|
|
|
|
LinkageLocation ret[] = {c->GetReturnLocation(0)};
|
|
|
|
Signature<LinkageLocation> loc(1, 0, ret);
|
2018-02-09 19:19:25 +00:00
|
|
|
auto call_descriptor = new (r.zone()) CallDescriptor( // --
|
2015-10-01 17:11:34 +00:00
|
|
|
CallDescriptor::kCallCodeObject, // kind
|
2015-12-10 09:03:30 +00:00
|
|
|
MachineType::AnyTagged(), // target_type
|
2015-10-01 17:11:34 +00:00
|
|
|
c->GetInputLocation(0), // target_loc
|
|
|
|
&loc, // location_sig
|
|
|
|
0, // stack count
|
|
|
|
Operator::kNoProperties, // properties
|
|
|
|
c->CalleeSavedRegisters(), // callee saved
|
|
|
|
c->CalleeSavedFPRegisters(), // callee saved FP
|
|
|
|
CallDescriptor::kNoFlags, // flags
|
|
|
|
"c-call-as-code");
|
2018-02-09 19:19:25 +00:00
|
|
|
Node* call = r.AddNode(r.common()->Call(call_descriptor), phi);
|
2015-10-01 17:11:34 +00:00
|
|
|
r.Return(call);
|
|
|
|
|
|
|
|
CHECK_EQ(33, r.Call(1));
|
|
|
|
CHECK_EQ(44, r.Call(0));
|
|
|
|
}
|
2015-10-30 09:16:26 +00:00
|
|
|
|
2016-02-16 07:28:57 +00:00
|
|
|
TEST(ParentFramePointer) {
|
|
|
|
RawMachineAssemblerTester<int32_t> r(MachineType::Int32());
|
|
|
|
RawMachineLabel tlabel;
|
|
|
|
RawMachineLabel flabel;
|
|
|
|
RawMachineLabel merge;
|
|
|
|
Node* frame = r.LoadFramePointer();
|
|
|
|
Node* parent_frame = r.LoadParentFramePointer();
|
|
|
|
frame = r.Load(MachineType::IntPtr(), frame);
|
|
|
|
r.Branch(r.WordEqual(frame, parent_frame), &tlabel, &flabel);
|
|
|
|
r.Bind(&tlabel);
|
|
|
|
Node* fa = r.Int32Constant(1);
|
|
|
|
r.Goto(&merge);
|
|
|
|
r.Bind(&flabel);
|
|
|
|
Node* fb = r.Int32Constant(0);
|
|
|
|
r.Goto(&merge);
|
|
|
|
r.Bind(&merge);
|
|
|
|
Node* phi = r.Phi(MachineRepresentation::kWord32, fa, fb);
|
|
|
|
r.Return(phi);
|
|
|
|
CHECK_EQ(1, r.Call(1));
|
|
|
|
}
|
|
|
|
|
2017-05-16 12:27:56 +00:00
|
|
|
#if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64
|
|
|
|
|
|
|
|
TEST(StackSlotAlignment) {
|
|
|
|
RawMachineAssemblerTester<int32_t> r;
|
|
|
|
RawMachineLabel tlabel;
|
|
|
|
RawMachineLabel flabel;
|
|
|
|
RawMachineLabel merge;
|
|
|
|
|
|
|
|
int alignments[] = {4, 8, 16};
|
|
|
|
int alignment_count = arraysize(alignments);
|
|
|
|
|
|
|
|
Node* alignment_counter = r.Int32Constant(0);
|
|
|
|
for (int i = 0; i < alignment_count; i++) {
|
|
|
|
for (int j = 0; j < 5; j++) {
|
|
|
|
Node* stack_slot =
|
|
|
|
r.StackSlot(MachineRepresentation::kWord32, alignments[i]);
|
|
|
|
alignment_counter = r.Int32Add(
|
|
|
|
alignment_counter,
|
|
|
|
r.Word32And(stack_slot, r.Int32Constant(alignments[i] - 1)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r.Return(alignment_counter);
|
2017-05-18 09:42:44 +00:00
|
|
|
CHECK_EQ(0, r.Call());
|
2017-05-16 12:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64
|
|
|
|
|
2017-02-08 11:52:16 +00:00
|
|
|
#if V8_TARGET_ARCH_64_BIT
|
|
|
|
|
|
|
|
TEST(Regression5923) {
|
|
|
|
{
|
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Int64());
|
|
|
|
m.Return(m.Int64Add(
|
|
|
|
m.Word64Shr(m.Parameter(0), m.Int64Constant(4611686018427387888)),
|
|
|
|
m.Parameter(0)));
|
|
|
|
int64_t input = 16;
|
|
|
|
m.Call(input);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Int64());
|
|
|
|
m.Return(m.Int64Add(
|
|
|
|
m.Parameter(0),
|
|
|
|
m.Word64Shr(m.Parameter(0), m.Int64Constant(4611686018427387888))));
|
|
|
|
int64_t input = 16;
|
|
|
|
m.Call(input);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-14 17:40:51 +00:00
|
|
|
TEST(Regression5951) {
|
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Int64());
|
|
|
|
m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(0)),
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Int64Constant(0xFFFFFFFFFFFFFFFFl)));
|
2017-02-14 17:40:51 +00:00
|
|
|
int64_t input = 1234;
|
|
|
|
CHECK_EQ(input, m.Call(input));
|
|
|
|
}
|
|
|
|
|
2017-03-07 14:54:05 +00:00
|
|
|
TEST(Regression6046a) {
|
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m;
|
|
|
|
m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(0), m.Int64Constant(0)),
|
|
|
|
m.Int64Constant(64)));
|
|
|
|
CHECK_EQ(0, m.Call());
|
|
|
|
}
|
|
|
|
|
2017-03-20 09:42:37 +00:00
|
|
|
TEST(Regression6122) {
|
|
|
|
BufferedRawMachineAssemblerTester<int64_t> m;
|
|
|
|
m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(59), m.Int64Constant(-1)),
|
|
|
|
m.Int64Constant(0)));
|
|
|
|
CHECK_EQ(59, m.Call());
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // V8_TARGET_ARCH_64_BIT
|
|
|
|
|
2017-03-07 14:54:05 +00:00
|
|
|
TEST(Regression6046b) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m;
|
|
|
|
m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(0), m.Int32Constant(0)),
|
|
|
|
m.Int32Constant(32)));
|
|
|
|
CHECK_EQ(0, m.Call());
|
|
|
|
}
|
|
|
|
|
2017-03-20 09:42:37 +00:00
|
|
|
TEST(Regression6122b) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m;
|
|
|
|
m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(59), m.Int32Constant(-1)),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
CHECK_EQ(59, m.Call());
|
|
|
|
}
|
2017-02-08 11:52:16 +00:00
|
|
|
|
2017-03-02 19:46:09 +00:00
|
|
|
TEST(Regression6028) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m;
|
|
|
|
m.Return(m.Word32Equal(
|
|
|
|
m.Word32And(m.Int32Constant(0x23),
|
|
|
|
m.Word32Sar(m.Int32Constant(1), m.Int32Constant(18))),
|
|
|
|
m.Int32Constant(0)));
|
|
|
|
CHECK_EQ(1, m.Call());
|
|
|
|
}
|
|
|
|
|
2017-04-13 09:51:20 +00:00
|
|
|
TEST(Regression5951_32bit) {
|
|
|
|
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Int32());
|
|
|
|
m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(0)),
|
2017-12-02 00:30:37 +00:00
|
|
|
m.Int32Constant(0xFFFFFFFF)));
|
2017-04-13 09:51:20 +00:00
|
|
|
int32_t input = 1234;
|
|
|
|
CHECK_EQ(input, m.Call(input));
|
|
|
|
}
|
|
|
|
|
2017-07-06 05:58:37 +00:00
|
|
|
TEST(Regression738952) {
|
|
|
|
RawMachineAssemblerTester<int32_t> m;
|
|
|
|
|
|
|
|
int32_t sentinel = 1234;
|
|
|
|
// The index can be any value where the lower bits are 0 and the upper bits
|
|
|
|
// are not 0;
|
|
|
|
int64_t index = 3224;
|
|
|
|
index <<= 32;
|
|
|
|
double d = static_cast<double>(index);
|
|
|
|
m.Return(m.Load(MachineType::Int32(), m.PointerConstant(&sentinel),
|
|
|
|
m.TruncateFloat64ToWord32(m.Float64Constant(d))));
|
|
|
|
CHECK_EQ(sentinel, m.Call());
|
|
|
|
}
|
2017-07-26 14:10:52 +00:00
|
|
|
|
2015-10-30 09:16:26 +00:00
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|