HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Nougat 7.1
|
7.1.1_r28
下载
查看原文件
收藏
根目录
external
v8
test
cctest
compiler
test-run-machops.cc
// 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. #include
#include
#include
#include "src/base/bits.h" #include "src/base/ieee754.h" #include "src/base/utils/random-number-generator.h" #include "src/codegen.h" #include "test/cctest/cctest.h" #include "test/cctest/compiler/codegen-tester.h" #include "test/cctest/compiler/graph-builder-tester.h" #include "test/cctest/compiler/value-helper.h" using namespace v8::base; namespace v8 { namespace internal { namespace compiler { TEST(RunInt32Add) { RawMachineAssemblerTester
m; Node* add = m.Int32Add(m.Int32Constant(0), m.Int32Constant(1)); m.Return(add); CHECK_EQ(1, m.Call()); } static int RunInt32AddShift(bool is_left, int32_t add_left, int32_t add_right, int32_t shift_left, int32_t shit_right) { RawMachineAssemblerTester
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)); } } TEST(RunWord32ReverseBits) { BufferedRawMachineAssemblerTester
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))); CHECK_EQ(uint32_t(0x12345678), m.Call(uint32_t(0x1e6a2c48))); CHECK_EQ(uint32_t(0xfedcba09), m.Call(uint32_t(0x905d3b7f))); CHECK_EQ(uint32_t(0x01010101), m.Call(uint32_t(0x80808080))); CHECK_EQ(uint32_t(0x01020408), m.Call(uint32_t(0x10204080))); 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))); } TEST(RunWord32Ctz) { BufferedRawMachineAssemblerTester
m(MachineType::Uint32()); 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))); CHECK_EQ(27, m.Call(uint32_t(0xa8000000))); CHECK_EQ(26, m.Call(uint32_t(0xf4000000))); CHECK_EQ(25, m.Call(uint32_t(0x62000000))); CHECK_EQ(24, m.Call(uint32_t(0x91000000))); CHECK_EQ(23, m.Call(uint32_t(0xcd800000))); CHECK_EQ(22, m.Call(uint32_t(0x09400000))); 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))); } TEST(RunWord32Clz) { BufferedRawMachineAssemblerTester
m(MachineType::Uint32()); 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))); CHECK_EQ(7, m.Call(uint32_t(0x010000a0))); CHECK_EQ(8, m.Call(uint32_t(0x00800c00))); CHECK_EQ(9, m.Call(uint32_t(0x00400000))); CHECK_EQ(10, m.Call(uint32_t(0x0020000d))); CHECK_EQ(11, m.Call(uint32_t(0x00100f00))); 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) { BufferedRawMachineAssemblerTester
m(MachineType::Uint32()); 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))); 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))); } #if V8_TARGET_ARCH_64_BIT TEST(RunWord64ReverseBits) { RawMachineAssemblerTester
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))); CHECK_EQ(uint64_t(0x1234567890abcdef), m.Call(uint64_t(0xf7b3d5091e6a2c48))); CHECK_EQ(uint64_t(0xfedcba0987654321), m.Call(uint64_t(0x84c2a6e1905d3b7f))); CHECK_EQ(uint64_t(0x0101010101010101), m.Call(uint64_t(0x8080808080808080))); 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))); } TEST(RunWord64Clz) { BufferedRawMachineAssemblerTester
m(MachineType::Uint64()); 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))); CHECK_EQ(7, m.Call(uint64_t(0x010000a000000000))); CHECK_EQ(8, m.Call(uint64_t(0x00800c0000000000))); CHECK_EQ(9, m.Call(uint64_t(0x0040000000000000))); CHECK_EQ(10, m.Call(uint64_t(0x0020000d00000000))); CHECK_EQ(11, m.Call(uint64_t(0x00100f0000000000))); 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))); CHECK_EQ(39, m.Call(uint64_t(0x00000000010000a0))); CHECK_EQ(40, m.Call(uint64_t(0x0000000000800c00))); CHECK_EQ(41, m.Call(uint64_t(0x0000000000400000))); CHECK_EQ(42, m.Call(uint64_t(0x000000000020000d))); CHECK_EQ(43, m.Call(uint64_t(0x0000000000100f00))); 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))); } TEST(RunWord64Ctz) { RawMachineAssemblerTester
m(MachineType::Uint64()); 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))); CHECK_EQ(59, m.Call(uint64_t(0xa800000000000000))); CHECK_EQ(58, m.Call(uint64_t(0xf400000000000000))); CHECK_EQ(57, m.Call(uint64_t(0x6200000000000000))); CHECK_EQ(56, m.Call(uint64_t(0x9100000000000000))); CHECK_EQ(55, m.Call(uint64_t(0xcd80000000000000))); CHECK_EQ(54, m.Call(uint64_t(0x0940000000000000))); 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))); 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))); CHECK_EQ(27, m.Call(uint64_t(0x00000000a8000000))); CHECK_EQ(26, m.Call(uint64_t(0x00000000f4000000))); CHECK_EQ(25, m.Call(uint64_t(0x0000000062000000))); CHECK_EQ(24, m.Call(uint64_t(0x0000000091000000))); CHECK_EQ(23, m.Call(uint64_t(0x00000000cd800000))); CHECK_EQ(22, m.Call(uint64_t(0x0000000009400000))); 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))); } TEST(RunWord64Popcnt) { BufferedRawMachineAssemblerTester
m(MachineType::Uint64()); 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))); 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))); } #endif // V8_TARGET_ARCH_64_BIT static Node* Int32Input(RawMachineAssemblerTester
* 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: return m->Int32Constant(0xff); case 6: return m->Int32Constant(0x01234567); case 7: return m->Load(MachineType::Int32(), m->PointerConstant(NULL)); default: return NULL; } } TEST(CodeGenInt32Binop) { RawMachineAssemblerTester
m; const Operator* kOps[] = { 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()}; for (size_t i = 0; i < arraysize(kOps); ++i) { for (int j = 0; j < 8; j++) { for (int k = 0; k < 8; k++) { RawMachineAssemblerTester
m(MachineType::Int32(), MachineType::Int32()); Node* a = Int32Input(&m, j); Node* b = Int32Input(&m, k); m.Return(m.AddNode(kOps[i], a, b)); m.GenerateCode(); } } } } TEST(CodeGenNop) { RawMachineAssemblerTester
m; m.Return(m.Int32Constant(0)); m.GenerateCode(); } #if V8_TARGET_ARCH_64_BIT static Node* Int64Input(RawMachineAssemblerTester
* 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: return m->Int64Constant(0xff); case 6: return m->Int64Constant(0x0123456789abcdefLL); case 7: return m->Load(MachineType::Int64(), m->PointerConstant(NULL)); default: return NULL; } } TEST(CodeGenInt64Binop) { RawMachineAssemblerTester
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++) { RawMachineAssemblerTester
m(MachineType::Int64(), MachineType::Int64()); Node* a = Int64Input(&m, j); Node* b = Int64Input(&m, k); m.Return(m.AddNode(kOps[i], a, b)); m.GenerateCode(); } } } } TEST(RunInt64AddWithOverflowP) { int64_t actual_val = -1; RawMachineAssemblerTester
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; int expected_ovf = bits::SignedAddOverflow64(*i, *j, &expected_val); 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
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) { int expected_ovf = bits::SignedAddOverflow64(*i, *j, &expected_val); CHECK_EQ(expected_ovf, m.Call(*j)); CHECK_EQ(expected_val, actual_val); } } { RawMachineAssemblerTester
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) { int expected_ovf = bits::SignedAddOverflow64(*i, *j, &expected_val); CHECK_EQ(expected_ovf, m.Call(*j)); CHECK_EQ(expected_val, actual_val); } } FOR_INT64_INPUTS(j) { RawMachineAssemblerTester
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); int expected_ovf = bits::SignedAddOverflow64(*i, *j, &expected_val); CHECK_EQ(expected_ovf, m.Call()); CHECK_EQ(expected_val, actual_val); } } } TEST(RunInt64AddWithOverflowInBranchP) { int constant = 911777; RawMachineLabel blocka, blockb; RawMachineAssemblerTester
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; if (!bits::SignedAddOverflow64(*i, *j, &result)) { expected = static_cast
(result); } CHECK_EQ(expected, bt.call(*i, *j)); } } } TEST(RunInt64SubWithOverflowP) { int64_t actual_val = -1; RawMachineAssemblerTester
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; int expected_ovf = bits::SignedSubOverflow64(*i, *j, &expected_val); 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
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) { int expected_ovf = bits::SignedSubOverflow64(*i, *j, &expected_val); CHECK_EQ(expected_ovf, m.Call(*j)); CHECK_EQ(expected_val, actual_val); } } { RawMachineAssemblerTester
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) { int expected_ovf = bits::SignedSubOverflow64(*j, *i, &expected_val); CHECK_EQ(expected_ovf, m.Call(*j)); CHECK_EQ(expected_val, actual_val); } } FOR_INT64_INPUTS(j) { RawMachineAssemblerTester
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); int expected_ovf = bits::SignedSubOverflow64(*i, *j, &expected_val); CHECK_EQ(expected_ovf, m.Call()); CHECK_EQ(expected_val, actual_val); } } } TEST(RunInt64SubWithOverflowInBranchP) { int constant = 911999; RawMachineLabel blocka, blockb; RawMachineAssemblerTester
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; if (!bits::SignedSubOverflow64(*i, *j, &result)) { expected = static_cast
(result); } CHECK_EQ(expected, static_cast
(bt.call(*i, *j))); } } } static int64_t RunInt64AddShift(bool is_left, int64_t add_left, int64_t add_right, int64_t shift_left, int64_t shit_right) { RawMachineAssemblerTester
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)); } } // TODO(titzer): add tests that run 64-bit integer operations. #endif // V8_TARGET_ARCH_64_BIT TEST(RunGoto) { RawMachineAssemblerTester
m; int constant = 99999; RawMachineLabel next; m.Goto(&next); m.Bind(&next); m.Return(m.Int32Constant(constant)); CHECK_EQ(constant, m.Call()); } TEST(RunGotoMultiple) { RawMachineAssemblerTester
m; int constant = 9999977; RawMachineLabel labels[10]; for (size_t i = 0; i < arraysize(labels); i++) { m.Goto(&labels[i]); m.Bind(&labels[i]); } m.Return(m.Int32Constant(constant)); CHECK_EQ(constant, m.Call()); } TEST(RunBranch) { RawMachineAssemblerTester
m; int constant = 999777; RawMachineLabel blocka, blockb; 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
m; int constant = 995666; RawMachineLabel blocka, blockb, end; 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
m; int constant = 999555; RawMachineLabel header, body, exit; 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
static void BuildDiamondPhi(RawMachineAssemblerTester
* m, Node* cond_node, MachineRepresentation rep, Node* true_node, Node* false_node) { RawMachineLabel blocka, blockb, end; m->Branch(cond_node, &blocka, &blockb); m->Bind(&blocka); m->Goto(&end); m->Bind(&blockb); m->Goto(&end); m->Bind(&end); Node* phi = m->Phi(rep, true_node, false_node); m->Return(phi); } TEST(RunDiamondPhiConst) { RawMachineAssemblerTester
m(MachineType::Int32()); int false_val = 0xFF666; int true_val = 0x00DDD; Node* true_node = m.Int32Constant(true_val); Node* false_node = m.Int32Constant(false_val); BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kWord32, true_node, false_node); CHECK_EQ(false_val, m.Call(0)); CHECK_EQ(true_val, m.Call(1)); } TEST(RunDiamondPhiNumber) { RawMachineAssemblerTester
m(MachineType::Int32()); double false_val = -11.1; double true_val = 200.1; Node* true_node = m.NumberConstant(true_val); Node* false_node = m.NumberConstant(false_val); BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kTagged, true_node, false_node); m.CheckNumber(false_val, m.Call(0)); m.CheckNumber(true_val, m.Call(1)); } TEST(RunDiamondPhiString) { RawMachineAssemblerTester
m(MachineType::Int32()); const char* false_val = "false"; const char* true_val = "true"; Node* true_node = m.StringConstant(true_val); Node* false_node = m.StringConstant(false_val); BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kTagged, true_node, false_node); m.CheckString(false_val, m.Call(0)); m.CheckString(true_val, m.Call(1)); } TEST(RunDiamondPhiParam) { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Int32(), MachineType::Int32()); BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kWord32, m.Parameter(1), m.Parameter(2)); int32_t c1 = 0x260cb75a; int32_t c2 = 0xcd3e9c8b; int result = m.Call(0, c1, c2); CHECK_EQ(c2, result); result = m.Call(1, c1, c2); CHECK_EQ(c1, result); } TEST(RunLoopPhiConst) { RawMachineAssemblerTester
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; RawMachineLabel body, header, end; m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(MachineRepresentation::kWord32, false_node, true_node); m.Branch(cond_node, &body, &end); m.Bind(&body); m.Goto(&header); m.Bind(&end); m.Return(phi); CHECK_EQ(false_val, m.Call()); } TEST(RunLoopPhiParam) { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Int32(), MachineType::Int32()); RawMachineLabel blocka, blockb, end; m.Goto(&blocka); m.Bind(&blocka); Node* phi = m.Phi(MachineRepresentation::kWord32, m.Parameter(1), m.Parameter(2)); Node* cond = m.Phi(MachineRepresentation::kWord32, m.Parameter(0), m.Int32Constant(0)); m.Branch(cond, &blockb, &end); m.Bind(&blockb); m.Goto(&blocka); m.Bind(&end); m.Return(phi); int32_t c1 = 0xa81903b4; int32_t c2 = 0x5a1207da; int result = m.Call(0, c1, c2); CHECK_EQ(c1, result); result = m.Call(1, c1, c2); CHECK_EQ(c2, result); } TEST(RunLoopPhiInduction) { RawMachineAssemblerTester
m; int false_val = 0x10777; // x = false_val; while(false) { x++; } return x; RawMachineLabel header, body, end; Node* false_node = m.Int32Constant(false_val); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(MachineRepresentation::kWord32, false_node, false_node); 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()); } TEST(RunLoopIncrement) { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); // x = 0; while(x ^ param) { x++; } return x; RawMachineLabel header, body, end; Node* zero = m.Int32Constant(0); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero); m.Branch(m.WordXor(phi, bt.param0), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1))); m.Goto(&header); m.Bind(&end); 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
m; Int32BinopTester bt(&m); // x = 0; while(x < param) { x++; } return x; RawMachineLabel header, body, end; Node* zero = m.Int32Constant(0); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero); m.Branch(m.Int32LessThan(phi, bt.param0), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1))); m.Goto(&header); m.Bind(&end); 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
m; Int32BinopTester bt(&m); // x = 0; while(x < param) { x++; } return x; RawMachineLabel header, body, end; Node* zero = m.Int32Constant(0); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero); m.Branch(m.Uint32LessThan(phi, bt.param0), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1))); m.Goto(&header); m.Bind(&end); 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
m; Int32BinopTester bt(&m); // x = param; while(x) { x--; } return x; RawMachineLabel header, body, end; m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(MachineRepresentation::kWord32, bt.param0, m.Int32Constant(0)); m.Branch(phi, &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Int32Sub(phi, m.Int32Constant(1))); m.Goto(&header); m.Bind(&end); bt.AddReturn(phi); CHECK_EQ(0, bt.call(11, 0)); CHECK_EQ(0, bt.call(110, 0)); CHECK_EQ(0, bt.call(197, 0)); } TEST(RunLoopIncrementFloat32) { RawMachineAssemblerTester
m; // x = -3.0f; while(x < 10f) { x = x + 0.5f; } return (int) (double) x; RawMachineLabel header, body, end; Node* minus_3 = m.Float32Constant(-3.0f); Node* ten = m.Float32Constant(10.0f); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(MachineRepresentation::kFloat32, minus_3, ten); m.Branch(m.Float32LessThan(phi, ten), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Float32Add(phi, m.Float32Constant(0.5f))); m.Goto(&header); m.Bind(&end); m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(phi))); CHECK_EQ(10, m.Call()); } TEST(RunLoopIncrementFloat64) { RawMachineAssemblerTester
m; // x = -3.0; while(x < 10) { x = x + 0.5; } return (int) x; RawMachineLabel header, body, end; Node* minus_3 = m.Float64Constant(-3.0); Node* ten = m.Float64Constant(10.0); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(MachineRepresentation::kFloat64, minus_3, ten); m.Branch(m.Float64LessThan(phi, ten), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Float64Add(phi, m.Float64Constant(0.5))); m.Goto(&header); m.Bind(&end); m.Return(m.ChangeFloat64ToInt32(phi)); CHECK_EQ(10, m.Call()); } TEST(RunSwitch1) { RawMachineAssemblerTester
m; int constant = 11223344; RawMachineLabel block0, block1, def, end; RawMachineLabel* case_labels[] = {&block0, &block1}; int32_t case_values[] = {0, 1}; m.Switch(m.Int32Constant(0), &def, case_values, case_labels, arraysize(case_labels)); m.Bind(&block0); m.Goto(&end); m.Bind(&block1); m.Goto(&end); m.Bind(&def); m.Goto(&end); m.Bind(&end); m.Return(m.Int32Constant(constant)); CHECK_EQ(constant, m.Call()); } TEST(RunSwitch2) { RawMachineAssemblerTester
m(MachineType::Int32()); RawMachineLabel blocka, blockb, blockc; RawMachineLabel* case_labels[] = {&blocka, &blockb}; int32_t case_values[] = {std::numeric_limits
::min(), std::numeric_limits
::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
::max())); CHECK_EQ(-1, m.Call(std::numeric_limits
::min())); for (int i = -100; i < 100; i += 25) { CHECK_EQ(0, m.Call(i)); } } TEST(RunSwitch3) { RawMachineAssemblerTester
m(MachineType::Int32()); RawMachineLabel blocka, blockb, blockc; RawMachineLabel* case_labels[] = {&blocka, &blockb}; int32_t case_values[] = {std::numeric_limits
::min() + 0, std::numeric_limits
::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
::min() + 0)); CHECK_EQ(1, m.Call(std::numeric_limits
::min() + 1)); for (int i = -100; i < 100; i += 25) { CHECK_EQ(2, m.Call(i)); } } TEST(RunSwitch4) { RawMachineAssemblerTester
m(MachineType::Int32()); const size_t kNumCases = 512; const size_t kNumValues = kNumCases + 1; int32_t values[kNumValues]; m.main_isolate()->random_number_generator()->NextBytes(values, sizeof(values)); RawMachineLabel end, def; int32_t case_values[kNumCases]; RawMachineLabel* case_labels[kNumCases]; Node* results[kNumValues]; for (size_t i = 0; i < kNumCases; ++i) { case_values[i] = static_cast
(i); case_labels[i] = new (m.main_zone()->New(sizeof(RawMachineLabel))) RawMachineLabel; } m.Switch(m.Parameter(0), &def, case_values, case_labels, arraysize(case_labels)); for (size_t i = 0; i < kNumCases; ++i) { m.Bind(case_labels[i]); results[i] = m.Int32Constant(values[i]); m.Goto(&end); } m.Bind(&def); results[kNumCases] = m.Int32Constant(values[kNumCases]); m.Goto(&end); m.Bind(&end); const int num_results = static_cast
(arraysize(results)); Node* phi = m.AddNode(m.common()->Phi(MachineRepresentation::kWord32, num_results), num_results, results); m.Return(phi); for (size_t i = 0; i < kNumValues; ++i) { CHECK_EQ(values[i], m.Call(static_cast
(i))); } } TEST(RunInt32AddP) { RawMachineAssemblerTester
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. int expected = static_cast
(*i + *j); CHECK_EQ(expected, bt.call(*i, *j)); } } } TEST(RunInt32AddAndWord32EqualP) { { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Int32(), MachineType::Int32()); 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
(bit_cast
(*i) + (*j == *k)); CHECK_EQ(expected, m.Call(*i, *j, *k)); } } } } { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Int32(), MachineType::Int32()); 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
((*i == *j) + bit_cast
(*k)); CHECK_EQ(expected, m.Call(*i, *j, *k)); } } } } } TEST(RunInt32AddAndWord32EqualImm) { { FOR_INT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Int32(), MachineType::Int32()); 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
(bit_cast
(*i) + (*j == *k)); CHECK_EQ(expected, m.Call(*j, *k)); } } } } { FOR_INT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Int32(), MachineType::Int32()); 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
((*i == *j) + bit_cast
(*k)); CHECK_EQ(expected, m.Call(*j, *k)); } } } } } TEST(RunInt32AddAndWord32NotEqualP) { { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Int32(), MachineType::Int32()); 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
(bit_cast
(*i) + (*j != *k)); CHECK_EQ(expected, m.Call(*i, *j, *k)); } } } } { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Int32(), MachineType::Int32()); 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
((*i != *j) + bit_cast
(*k)); CHECK_EQ(expected, m.Call(*i, *j, *k)); } } } } } TEST(RunInt32AddAndWord32NotEqualImm) { { FOR_INT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Int32(), MachineType::Int32()); 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
(bit_cast
(*i) + (*j != *k)); CHECK_EQ(expected, m.Call(*j, *k)); } } } } { FOR_INT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Int32(), MachineType::Int32()); 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
((*i != *j) + bit_cast
(*k)); CHECK_EQ(expected, m.Call(*j, *k)); } } } } } TEST(RunInt32AddAndWord32SarP) { { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); m.Return(m.Int32Add(m.Parameter(0), m.Word32Sar(m.Parameter(1), m.Parameter(2)))); FOR_UINT32_INPUTS(i) { FOR_INT32_INPUTS(j) { FOR_UINT32_SHIFTS(shift) { // Use uint32_t because signed overflow is UB in C. int32_t expected = *i + (*j >> shift); CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32()); m.Return(m.Int32Add(m.Word32Sar(m.Parameter(0), m.Parameter(1)), m.Parameter(2))); FOR_INT32_INPUTS(i) { FOR_UINT32_SHIFTS(shift) { 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) { { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); m.Return(m.Int32Add(m.Parameter(0), m.Word32Shl(m.Parameter(1), m.Parameter(2)))); FOR_UINT32_INPUTS(i) { FOR_INT32_INPUTS(j) { FOR_UINT32_SHIFTS(shift) { // Use uint32_t because signed overflow is UB in C. int32_t expected = *i + (*j << shift); CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32()); m.Return(m.Int32Add(m.Word32Shl(m.Parameter(0), m.Parameter(1)), m.Parameter(2))); FOR_INT32_INPUTS(i) { FOR_UINT32_SHIFTS(shift) { 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) { { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32()); m.Return(m.Int32Add(m.Parameter(0), m.Word32Shr(m.Parameter(1), m.Parameter(2)))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { FOR_UINT32_SHIFTS(shift) { // Use uint32_t because signed overflow is UB in C. int32_t expected = *i + (*j >> shift); CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32()); m.Return(m.Int32Add(m.Word32Shr(m.Parameter(0), m.Parameter(1)), m.Parameter(2))); FOR_UINT32_INPUTS(i) { FOR_UINT32_SHIFTS(shift) { 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
m; Int32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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
m; Int32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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) { RawMachineAssemblerTester
m(MachineType::Uint32()); RawMachineLabel blocka, blockb; 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) { uint32_t expected = (*i + *j) == 0 ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); RawMachineLabel blocka, blockb; 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) { uint32_t expected = (*i + *j) != 0 ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*j)); } } } { RawMachineAssemblerTester
m; const Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(), m.machine()->Word32Shr()}; for (size_t n = 0; n < arraysize(shops); n++) { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); RawMachineLabel blocka, blockb; m.Branch(m.Word32Equal(m.Int32Add(m.Parameter(0), m.AddNode(shops[n], m.Parameter(1), 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) { FOR_UINT32_SHIFTS(shift) { 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
(*j) >> shift; break; } int32_t expected = ((*i + right) == 0) ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } } } TEST(RunInt32AddInComparison) { { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Equal(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = (*i + *j) == 0; CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Equal(m.Int32Constant(0), m.Int32Add(bt.param0, bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = (*i + *j) == 0; CHECK_EQ(expected, bt.call(*i, *j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Equal(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)), m.Int32Constant(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = (*i + *j) == 0; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Equal(m.Int32Add(m.Parameter(0), m.Int32Constant(*i)), m.Int32Constant(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = (*j + *i) == 0; CHECK_EQ(expected, m.Call(*j)); } } } { RawMachineAssemblerTester
m; const Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(), m.machine()->Word32Shr()}; for (size_t n = 0; n < arraysize(shops); n++) { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); m.Return(m.Word32Equal( m.Int32Add(m.Parameter(0), m.AddNode(shops[n], m.Parameter(1), m.Parameter(2))), m.Int32Constant(0))); FOR_UINT32_INPUTS(i) { FOR_INT32_INPUTS(j) { FOR_UINT32_SHIFTS(shift) { 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
(*j) >> shift; break; } int32_t expected = (*i + right) == 0; CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } } } TEST(RunInt32SubP) { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); m.Return(m.Int32Sub(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = static_cast
(*i - *j); CHECK_EQ(expected, bt.call(*i, *j)); } } } TEST(RunInt32SubImm) { { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = *i - *j; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i))); FOR_UINT32_INPUTS(j) { uint32_t expected = *j - *i; CHECK_EQ(expected, m.Call(*j)); } } } } TEST(RunInt32SubImm2) { BufferedRawMachineAssemblerTester
r; r.Return(r.Int32Sub(r.Int32Constant(-1), r.Int32Constant(0))); CHECK_EQ(-1, r.Call()); } TEST(RunInt32SubAndWord32SarP) { { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); m.Return(m.Int32Sub(m.Parameter(0), m.Word32Sar(m.Parameter(1), m.Parameter(2)))); FOR_UINT32_INPUTS(i) { FOR_INT32_INPUTS(j) { FOR_UINT32_SHIFTS(shift) { int32_t expected = *i - (*j >> shift); CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32()); m.Return(m.Int32Sub(m.Word32Sar(m.Parameter(0), m.Parameter(1)), m.Parameter(2))); FOR_INT32_INPUTS(i) { FOR_UINT32_SHIFTS(shift) { FOR_UINT32_INPUTS(k) { int32_t expected = (*i >> shift) - *k; CHECK_EQ(expected, m.Call(*i, shift, *k)); } } } } } TEST(RunInt32SubAndWord32ShlP) { { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); m.Return(m.Int32Sub(m.Parameter(0), m.Word32Shl(m.Parameter(1), m.Parameter(2)))); FOR_UINT32_INPUTS(i) { FOR_INT32_INPUTS(j) { FOR_UINT32_SHIFTS(shift) { int32_t expected = *i - (*j << shift); CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32()); m.Return(m.Int32Sub(m.Word32Shl(m.Parameter(0), m.Parameter(1)), m.Parameter(2))); FOR_INT32_INPUTS(i) { FOR_UINT32_SHIFTS(shift) { 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) { { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32()); m.Return(m.Int32Sub(m.Parameter(0), m.Word32Shr(m.Parameter(1), m.Parameter(2)))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { FOR_UINT32_SHIFTS(shift) { // Use uint32_t because signed overflow is UB in C. uint32_t expected = *i - (*j >> shift); CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32()); m.Return(m.Int32Sub(m.Word32Shr(m.Parameter(0), m.Parameter(1)), m.Parameter(2))); FOR_UINT32_INPUTS(i) { FOR_UINT32_SHIFTS(shift) { FOR_UINT32_INPUTS(k) { // Use uint32_t because signed overflow is UB in C. uint32_t expected = (*i >> shift) - *k; CHECK_EQ(expected, m.Call(*i, shift, *k)); } } } } } TEST(RunInt32SubInBranch) { static const int constant = 987654321; { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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
m; Int32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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) { RawMachineAssemblerTester
m(MachineType::Uint32()); RawMachineLabel blocka, blockb; 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) { uint32_t expected = (*i - *j) == 0 ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); RawMachineLabel blocka, blockb; 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
m; const Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(), m.machine()->Word32Shr()}; for (size_t n = 0; n < arraysize(shops); n++) { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); RawMachineLabel blocka, blockb; m.Branch(m.Word32Equal(m.Int32Sub(m.Parameter(0), m.AddNode(shops[n], m.Parameter(1), 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) { FOR_UINT32_SHIFTS(shift) { 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
(*j) >> shift; break; } int32_t expected = ((*i - right) == 0) ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } } } TEST(RunInt32SubInComparison) { { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Equal(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = (*i - *j) == 0; CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Equal(m.Int32Constant(0), m.Int32Sub(bt.param0, bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = (*i - *j) == 0; CHECK_EQ(expected, bt.call(*i, *j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Equal(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)), m.Int32Constant(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = (*i - *j) == 0; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Equal(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)), m.Int32Constant(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = (*j - *i) == 0; CHECK_EQ(expected, m.Call(*j)); } } } { RawMachineAssemblerTester
m; const Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(), m.machine()->Word32Shr()}; for (size_t n = 0; n < arraysize(shops); n++) { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); m.Return(m.Word32Equal( m.Int32Sub(m.Parameter(0), m.AddNode(shops[n], m.Parameter(1), m.Parameter(2))), m.Int32Constant(0))); FOR_UINT32_INPUTS(i) { FOR_INT32_INPUTS(j) { FOR_UINT32_SHIFTS(shift) { 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
(*j) >> shift; break; } int32_t expected = (*i - right) == 0; CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } } } TEST(RunInt32MulP) { { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn(m.Int32Mul(bt.param0, bt.param1)); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { int expected = static_cast
(*i * *j); CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Int32Mul(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = *i * *j; CHECK_EQ(expected, bt.call(*i, *j)); } } } } TEST(RunInt32MulHighP) { RawMachineAssemblerTester
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
( (static_cast
(*i) * static_cast
(*j)) >> 32); CHECK_EQ(expected, bt.call(*i, *j)); } } } TEST(RunInt32MulImm) { { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Int32Mul(m.Int32Constant(*i), m.Parameter(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = *i * *j; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant(*i))); FOR_UINT32_INPUTS(j) { uint32_t expected = *j * *i; CHECK_EQ(expected, m.Call(*j)); } } } } TEST(RunInt32MulAndInt32AddP) { { FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { RawMachineAssemblerTester
m(MachineType::Int32()); 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
(p1 * p2); CHECK_EQ(expected, m.Call(p2)); } } } } { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Int32(), MachineType::Int32()); 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
(p1 * p2); CHECK_EQ(expected, m.Call(p0, p1, p2)); } } } } { RawMachineAssemblerTester
m( MachineType::Int32(), MachineType::Int32(), MachineType::Int32()); 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
(p0 * p1) + p2; CHECK_EQ(expected, m.Call(p0, p1, p2)); } } } } { FOR_INT32_INPUTS(i) { RawMachineAssemblerTester
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
(p0 * p1); CHECK_EQ(expected, bt.call(p0, p1)); } } } } } TEST(RunInt32MulAndInt32SubP) { { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Int32()); 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
(p1 * p2); CHECK_EQ(expected, m.Call(p0, p1, p2)); } } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
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
(p0 * p1); CHECK_EQ(expected, bt.call(p0, p1)); } } } } } TEST(RunUint32MulHighP) { RawMachineAssemblerTester
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
(static_cast
( (static_cast
(*i) * static_cast
(*j)) >> 32)); CHECK_EQ(expected, bt.call(bit_cast
(*i), bit_cast
(*j))); } } } TEST(RunInt32DivP) { { RawMachineAssemblerTester
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
(p0) != 0x80000000 || p1 != -1)) { int expected = static_cast
(p0 / p1); CHECK_EQ(expected, bt.call(p0, p1)); } } } } { RawMachineAssemblerTester
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
(p0) != 0x80000000 || p1 != -1)) { int expected = static_cast
(p0 + (p0 / p1)); CHECK_EQ(expected, bt.call(p0, p1)); } } } } } TEST(RunUint32DivP) { { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn(m.Uint32Div(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t p0 = *i; uint32_t p1 = *j; if (p1 != 0) { int32_t expected = bit_cast
(p0 / p1); CHECK_EQ(expected, bt.call(p0, p1)); } } } } { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn(m.Int32Add(bt.param0, m.Uint32Div(bt.param0, bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t p0 = *i; uint32_t p1 = *j; if (p1 != 0) { int32_t expected = bit_cast
(p0 + (p0 / p1)); CHECK_EQ(expected, bt.call(p0, p1)); } } } } } TEST(RunInt32ModP) { { RawMachineAssemblerTester
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
(p0) != 0x80000000 || p1 != -1)) { int expected = static_cast
(p0 % p1); CHECK_EQ(expected, bt.call(p0, p1)); } } } } { RawMachineAssemblerTester
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
(p0) != 0x80000000 || p1 != -1)) { int expected = static_cast
(p0 + (p0 % p1)); CHECK_EQ(expected, bt.call(p0, p1)); } } } } } TEST(RunUint32ModP) { { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Uint32Mod(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t p0 = *i; uint32_t p1 = *j; if (p1 != 0) { uint32_t expected = static_cast
(p0 % p1); CHECK_EQ(expected, bt.call(p0, p1)); } } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Int32Add(bt.param0, m.Uint32Mod(bt.param0, bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t p0 = *i; uint32_t p1 = *j; if (p1 != 0) { uint32_t expected = static_cast
(p0 + (p0 % p1)); CHECK_EQ(expected, bt.call(p0, p1)); } } } } } TEST(RunWord32AndP) { { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn(m.Word32And(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { int32_t expected = *i & *j; CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn(m.Word32And(bt.param0, m.Word32Not(bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { int32_t expected = *i & ~(*j); CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn(m.Word32And(m.Word32Not(bt.param0), bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { int32_t expected = ~(*i) & *j; CHECK_EQ(expected, bt.call(*i, *j)); } } } } TEST(RunWord32AndAndWord32ShlP) { { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Shl(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1f)))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = *i << (*j & 0x1f); CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Shl(bt.param0, m.Word32And(m.Int32Constant(0x1f), bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = *i << (0x1f & *j); CHECK_EQ(expected, bt.call(*i, *j)); } } } } TEST(RunWord32AndAndWord32ShrP) { { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Shr(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1f)))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = *i >> (*j & 0x1f); CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Shr(bt.param0, m.Word32And(m.Int32Constant(0x1f), bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = *i >> (0x1f & *j); CHECK_EQ(expected, bt.call(*i, *j)); } } } } TEST(RunWord32AndAndWord32SarP) { { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn( m.Word32Sar(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1f)))); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { int32_t expected = *i >> (*j & 0x1f); CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn( m.Word32Sar(bt.param0, m.Word32And(m.Int32Constant(0x1f), bt.param1))); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { int32_t expected = *i >> (0x1f & *j); CHECK_EQ(expected, bt.call(*i, *j)); } } } } TEST(RunWord32AndImm) { { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32And(m.Int32Constant(*i), m.Parameter(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = *i & *j; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32And(m.Int32Constant(*i), m.Word32Not(m.Parameter(0)))); FOR_UINT32_INPUTS(j) { uint32_t expected = *i & ~(*j); CHECK_EQ(expected, m.Call(*j)); } } } } TEST(RunWord32AndInBranch) { static const int constant = 987654321; { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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
m; Int32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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) { RawMachineAssemblerTester
m(MachineType::Uint32()); RawMachineLabel blocka, blockb; 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) { RawMachineAssemblerTester
m(MachineType::Uint32()); RawMachineLabel blocka, blockb; 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
m; const Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(), m.machine()->Word32Shr()}; for (size_t n = 0; n < arraysize(shops); n++) { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); RawMachineLabel blocka, blockb; m.Branch(m.Word32Equal(m.Word32And(m.Parameter(0), m.AddNode(shops[n], m.Parameter(1), 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) { FOR_UINT32_SHIFTS(shift) { 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
(*j) >> shift; break; } int32_t expected = ((*i & right) == 0) ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } } } TEST(RunWord32AndInComparison) { { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Equal(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = (*i & *j) == 0; CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn( m.Word32Equal(m.Int32Constant(0), m.Word32And(bt.param0, bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = (*i & *j) == 0; CHECK_EQ(expected, bt.call(*i, *j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Equal(m.Word32And(m.Int32Constant(*i), m.Parameter(0)), m.Int32Constant(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = (*i & *j) == 0; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Equal(m.Word32And(m.Parameter(0), m.Int32Constant(*i)), m.Int32Constant(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = (*j & *i) == 0; CHECK_EQ(expected, m.Call(*j)); } } } } TEST(RunWord32OrP) { { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Word32Or(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = *i | *j; CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Word32Or(bt.param0, m.Word32Not(bt.param1))); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = *i | ~(*j); CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Word32Or(m.Word32Not(bt.param0), bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = ~(*i) | *j; CHECK_EQ(expected, bt.call(*i, *j)); } } } } TEST(RunWord32OrImm) { { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Or(m.Int32Constant(*i), m.Parameter(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = *i | *j; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Or(m.Int32Constant(*i), m.Word32Not(m.Parameter(0)))); FOR_UINT32_INPUTS(j) { uint32_t expected = *i | ~(*j); CHECK_EQ(expected, m.Call(*j)); } } } } TEST(RunWord32OrInBranch) { static const int constant = 987654321; { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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)); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { int32_t expected = (*i | *j) == 0 ? constant : 0 - constant; CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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)); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { int32_t expected = (*i | *j) != 0 ? constant : 0 - constant; CHECK_EQ(expected, bt.call(*i, *j)); } } } { FOR_INT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Int32()); RawMachineLabel blocka, blockb; 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)); FOR_INT32_INPUTS(j) { int32_t expected = (*i | *j) == 0 ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_INT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Int32()); RawMachineLabel blocka, blockb; 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)); FOR_INT32_INPUTS(j) { int32_t expected = (*i | *j) != 0 ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*j)); } } } { RawMachineAssemblerTester
m; const Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(), m.machine()->Word32Shr()}; for (size_t n = 0; n < arraysize(shops); n++) { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); RawMachineLabel blocka, blockb; m.Branch(m.Word32Equal(m.Word32Or(m.Parameter(0), m.AddNode(shops[n], m.Parameter(1), 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) { FOR_UINT32_SHIFTS(shift) { 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
(*j) >> shift; break; } int32_t expected = ((*i | right) == 0) ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } } } TEST(RunWord32OrInComparison) { { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); 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
m; Int32BinopTester bt(&m); 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) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Equal(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)), m.Int32Constant(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = (*i | *j) == 0; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Equal(m.Word32Or(m.Parameter(0), m.Int32Constant(*i)), m.Int32Constant(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = (*j | *i) == 0; CHECK_EQ(expected, m.Call(*j)); } } } } TEST(RunWord32XorP) { { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0))); FOR_UINT32_INPUTS(j) { uint32_t expected = *i ^ *j; CHECK_EQ(expected, m.Call(*j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Word32Xor(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_INPUTS(j) { uint32_t expected = *i ^ *j; CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn(m.Word32Xor(bt.param0, m.Word32Not(bt.param1))); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { int32_t expected = *i ^ ~(*j); CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Int32BinopTester bt(&m); bt.AddReturn(m.Word32Xor(m.Word32Not(bt.param0), bt.param1)); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { int32_t expected = ~(*i) ^ *j; CHECK_EQ(expected, bt.call(*i, *j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Xor(m.Int32Constant(*i), m.Word32Not(m.Parameter(0)))); FOR_UINT32_INPUTS(j) { uint32_t expected = *i ^ ~(*j); CHECK_EQ(expected, m.Call(*j)); } } } } TEST(RunWord32XorInBranch) { static const uint32_t constant = 987654321; { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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) { uint32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant; CHECK_EQ(expected, bt.call(*i, *j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); RawMachineLabel blocka, blockb; 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) { uint32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant; CHECK_EQ(expected, bt.call(*i, *j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); RawMachineLabel blocka, blockb; 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) { uint32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*j)); } } } { FOR_UINT32_INPUTS(i) { RawMachineAssemblerTester
m(MachineType::Uint32()); RawMachineLabel blocka, blockb; 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) { uint32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*j)); } } } { RawMachineAssemblerTester
m; const Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(), m.machine()->Word32Shr()}; for (size_t n = 0; n < arraysize(shops); n++) { RawMachineAssemblerTester
m( MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32()); RawMachineLabel blocka, blockb; m.Branch(m.Word32Equal(m.Word32Xor(m.Parameter(0), m.AddNode(shops[n], m.Parameter(1), 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) { FOR_UINT32_SHIFTS(shift) { 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
(*j) >> shift; break; } int32_t expected = ((*i ^ right) == 0) ? constant : 0 - constant; CHECK_EQ(expected, m.Call(*i, *j, shift)); } } } } } } TEST(RunWord32ShlP) { { FOR_UINT32_SHIFTS(shift) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Shl(m.Parameter(0), m.Int32Constant(shift))); FOR_UINT32_INPUTS(j) { uint32_t expected = *j << shift; CHECK_EQ(expected, m.Call(*j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Word32Shl(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_SHIFTS(shift) { uint32_t expected = *i << shift; CHECK_EQ(expected, bt.call(*i, shift)); } } } } TEST(RunWord32ShlInComparison) { { RawMachineAssemblerTester
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); CHECK_EQ(expected, bt.call(*i, shift)); } } } { RawMachineAssemblerTester
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); CHECK_EQ(expected, bt.call(*i, shift)); } } } { FOR_UINT32_SHIFTS(shift) { RawMachineAssemblerTester
m(MachineType::Uint32()); 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); CHECK_EQ(expected, m.Call(*i)); } } } { FOR_UINT32_SHIFTS(shift) { RawMachineAssemblerTester
m(MachineType::Uint32()); 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); CHECK_EQ(expected, m.Call(*i)); } } } } TEST(RunWord32ShrP) { { FOR_UINT32_SHIFTS(shift) { RawMachineAssemblerTester
m(MachineType::Uint32()); m.Return(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))); FOR_UINT32_INPUTS(j) { uint32_t expected = *j >> shift; CHECK_EQ(expected, m.Call(*j)); } } } { RawMachineAssemblerTester
m; Uint32BinopTester bt(&m); bt.AddReturn(m.Word32Shr(bt.param0, bt.param1)); FOR_UINT32_INPUTS(i) { FOR_UINT32_SHIFTS(shift) { uint32_t expected = *i >> shift; CHECK_EQ(expected, bt.call(*i, shift)); } } CHECK_EQ(0x00010000u, bt.call(0x80000000, 15)); } } TEST(RunWord32ShrInComparison) { { RawMachineAssemblerTester
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); CHECK_EQ(expected, bt.call(*i, shift)); } } } { RawMachineAssemblerTester
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); CHECK_EQ(expected, bt.call(*i, shift)); } } } { FOR_UINT32_SHIFTS(shift) { RawMachineAssemblerTester
m(MachineType::Uint32()); 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); CHECK_EQ(expected, m.Call(*i)); } } } { FOR_UINT32_SHIFTS(shift) { RawMachineAssemblerTester
m(MachineType::Uint32()); 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); CHECK_EQ(expected, m.Call(*i)); } } } } TEST(RunWord32SarP) { { FOR_INT32_SHIFTS(shift) { RawMachineAssemblerTester
m(MachineType::Int32()); 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
m; Int32BinopTester bt(&m); bt.AddReturn(m.Word32Sar(bt.param0, bt.param1)); FOR_INT32_INPUTS(i) { FOR_INT32_SHIFTS(shift) { int32_t expected = *i >> shift; CHECK_EQ(expected, bt.call(*i, shift)); } } CHECK_EQ(bit_cast
(0xFFFF0000), bt.call(0x80000000, 15)); } } TEST(RunWord32SarInComparison) { { RawMachineAssemblerTester