| Index: test/cctest/compiler/test-run-machops.cc
|
| diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1f71c4ad2965b2906aa4bc3dd17abcfbbc8f9a5e
|
| --- /dev/null
|
| +++ b/test/cctest/compiler/test-run-machops.cc
|
| @@ -0,0 +1,3798 @@
|
| +// 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 <limits>
|
| +#include "src/v8.h"
|
| +
|
| +#include "test/cctest/cctest.h"
|
| +#include "test/cctest/compiler/codegen-tester.h"
|
| +#include "test/cctest/compiler/value-helper.h"
|
| +
|
| +#if V8_TURBOFAN_TARGET
|
| +
|
| +using namespace v8::internal;
|
| +using namespace v8::internal::compiler;
|
| +
|
| +typedef RawMachineAssembler::Label MLabel;
|
| +
|
| +TEST(RunInt32Add) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* add = m.Int32Add(m.Int32Constant(0), m.Int32Constant(1));
|
| + m.Return(add);
|
| + CHECK_EQ(1, m.Call());
|
| +}
|
| +
|
| +
|
| +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:
|
| + return m->Int32Constant(0xff);
|
| + case 6:
|
| + return m->Int32Constant(0x01234567);
|
| + case 7:
|
| + return m->Load(kMachineWord32, m->PointerConstant(NULL));
|
| + default:
|
| + return NULL;
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(CodeGenInt32Binop) {
|
| + RawMachineAssemblerTester<void> m;
|
| +
|
| + Operator* ops[] = {
|
| + 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()->Int32Div(), m.machine()->Int32UDiv(),
|
| + m.machine()->Int32Mod(), m.machine()->Int32UMod(),
|
| + m.machine()->Int32LessThan(), m.machine()->Int32LessThanOrEqual(),
|
| + m.machine()->Uint32LessThan(), m.machine()->Uint32LessThanOrEqual(),
|
| + NULL};
|
| +
|
| + for (int i = 0; ops[i] != NULL; i++) {
|
| + for (int j = 0; j < 8; j++) {
|
| + for (int k = 0; k < 8; k++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
|
| + Node* a = Int32Input(&m, j);
|
| + Node* b = Int32Input(&m, k);
|
| + m.Return(m.NewNode(ops[i], a, b));
|
| + m.GenerateCode();
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunGoto) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int constant = 99999;
|
| +
|
| + MLabel next;
|
| + 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;
|
| +
|
| + MLabel labels[10];
|
| + for (size_t i = 0; i < ARRAY_SIZE(labels); i++) {
|
| + 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;
|
| +
|
| + MLabel 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(RunRedundantBranch1) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int constant = 944777;
|
| +
|
| + MLabel blocka;
|
| + m.Branch(m.Int32Constant(0), &blocka, &blocka);
|
| + m.Bind(&blocka);
|
| + m.Return(m.Int32Constant(constant));
|
| +
|
| + CHECK_EQ(constant, m.Call());
|
| +}
|
| +
|
| +
|
| +TEST(RunRedundantBranch2) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int constant = 955777;
|
| +
|
| + MLabel blocka, blockb;
|
| + m.Branch(m.Int32Constant(0), &blocka, &blocka);
|
| + m.Bind(&blockb);
|
| + m.Goto(&blocka);
|
| + m.Bind(&blocka);
|
| + m.Return(m.Int32Constant(constant));
|
| +
|
| + CHECK_EQ(constant, m.Call());
|
| +}
|
| +
|
| +
|
| +TEST(RunRedundantBranch3) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int constant = 966777;
|
| +
|
| + MLabel blocka, blockb, blockc;
|
| + m.Branch(m.Int32Constant(0), &blocka, &blockc);
|
| + m.Bind(&blocka);
|
| + m.Branch(m.Int32Constant(0), &blockb, &blockb);
|
| + m.Bind(&blockc);
|
| + m.Goto(&blockb);
|
| + m.Bind(&blockb);
|
| + m.Return(m.Int32Constant(constant));
|
| +
|
| + CHECK_EQ(constant, m.Call());
|
| +}
|
| +
|
| +
|
| +TEST(RunDiamond2) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| +
|
| + int constant = 995666;
|
| +
|
| + MLabel 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<int32_t> m;
|
| + int constant = 999555;
|
| +
|
| + MLabel 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 <typename R>
|
| +static void BuildDiamondPhi(RawMachineAssemblerTester<R>* m, Node* cond_node,
|
| + Node* true_node, Node* false_node) {
|
| + MLabel blocka, blockb;
|
| + MLabel* end = m->Exit();
|
| + 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(true_node, false_node);
|
| + m->Return(phi);
|
| +}
|
| +
|
| +
|
| +TEST(RunDiamondPhiConst) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + 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), true_node, false_node);
|
| + CHECK_EQ(false_val, m.Call(0));
|
| + CHECK_EQ(true_val, m.Call(1));
|
| +}
|
| +
|
| +
|
| +TEST(RunDiamondPhiNumber) {
|
| + RawMachineAssemblerTester<Object*> m(kMachineWord32);
|
| + 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), true_node, false_node);
|
| + m.CheckNumber(false_val, m.Call(0));
|
| + m.CheckNumber(true_val, m.Call(1));
|
| +}
|
| +
|
| +
|
| +TEST(RunDiamondPhiString) {
|
| + RawMachineAssemblerTester<Object*> m(kMachineWord32);
|
| + 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), true_node, false_node);
|
| + m.CheckString(false_val, m.Call(0));
|
| + m.CheckString(true_val, m.Call(1));
|
| +}
|
| +
|
| +
|
| +TEST(RunDiamondPhiParam) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + BuildDiamondPhi(&m, m.Parameter(0), 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<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;
|
| + MLabel body, header;
|
| + MLabel* end = m.Exit();
|
| +
|
| + m.Goto(&header);
|
| + m.Bind(&header);
|
| + Node* phi = m.Phi(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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| +
|
| + MLabel blocka, blockb;
|
| + MLabel* end = m.Exit();
|
| +
|
| + m.Goto(&blocka);
|
| +
|
| + m.Bind(&blocka);
|
| + Node* phi = m.Phi(m.Parameter(1), m.Parameter(2));
|
| + Node* cond = m.Phi(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<int32_t> m;
|
| +
|
| + int false_val = 0x10777;
|
| +
|
| + // x = false_val; while(false) { x++; } return x;
|
| + MLabel header, body;
|
| + MLabel* end = m.Exit();
|
| + Node* false_node = m.Int32Constant(false_val);
|
| +
|
| + m.Goto(&header);
|
| +
|
| + m.Bind(&header);
|
| + Node* phi = m.Phi(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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| +
|
| + // x = 0; while(x ^ param) { x++; } return x;
|
| + MLabel header, body;
|
| + MLabel* end = m.Exit();
|
| + Node* zero = m.Int32Constant(0);
|
| +
|
| + m.Goto(&header);
|
| +
|
| + m.Bind(&header);
|
| + Node* phi = m.Phi(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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| +
|
| + // x = 0; while(x < param) { x++; } return x;
|
| + MLabel header, body;
|
| + MLabel* end = m.Exit();
|
| + Node* zero = m.Int32Constant(0);
|
| +
|
| + m.Goto(&header);
|
| +
|
| + m.Bind(&header);
|
| + Node* phi = m.Phi(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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| +
|
| + // x = 0; while(x < param) { x++; } return x;
|
| + MLabel header, body;
|
| + MLabel* end = m.Exit();
|
| + Node* zero = m.Int32Constant(0);
|
| +
|
| + m.Goto(&header);
|
| +
|
| + m.Bind(&header);
|
| + Node* phi = m.Phi(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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| +
|
| + // x = param; while(x) { x--; } return x;
|
| + MLabel header, body;
|
| + MLabel* end = m.Exit();
|
| +
|
| + m.Goto(&header);
|
| +
|
| + m.Bind(&header);
|
| + Node* phi = m.Phi(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(RunLoopIncrementFloat64) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| +
|
| + // x = -3.0; while(x < 10) { x = x + 0.5; } return (int) x;
|
| + MLabel header, body;
|
| + MLabel* end = m.Exit();
|
| + Node* minus_3 = m.Float64Constant(-3.0);
|
| + Node* ten = m.Float64Constant(10.0);
|
| +
|
| + m.Goto(&header);
|
| +
|
| + m.Bind(&header);
|
| + Node* phi = m.Phi(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.ConvertFloat64ToInt32(phi));
|
| +
|
| + CHECK_EQ(10, m.Call());
|
| +}
|
| +
|
| +
|
| +TEST(RunLoadInt32) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| +
|
| + int32_t p1 = 0; // loads directly from this location.
|
| + m.Return(m.LoadFromPointer(&p1, kMachineWord32));
|
| +
|
| + FOR_INT32_INPUTS(i) {
|
| + p1 = *i;
|
| + CHECK_EQ(p1, m.Call());
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunLoadInt32Offset) {
|
| + int32_t p1 = 0; // loads directly from this location.
|
| +
|
| + int32_t offsets[] = {-2000000, -100, -101, 1, 3,
|
| + 7, 120, 2000, 2000000000, 0xff};
|
| +
|
| + for (size_t i = 0; i < ARRAY_SIZE(offsets); i++) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int32_t offset = offsets[i];
|
| + byte* pointer = reinterpret_cast<byte*>(&p1) - offset;
|
| + // generate load [#base + #index]
|
| + m.Return(m.LoadFromPointer(pointer, kMachineWord32, offset));
|
| +
|
| + FOR_INT32_INPUTS(j) {
|
| + p1 = *j;
|
| + CHECK_EQ(p1, m.Call());
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunLoadStoreFloat64Offset) {
|
| + double p1 = 0; // loads directly from this location.
|
| + double p2 = 0; // and stores directly into this location.
|
| +
|
| + FOR_INT32_INPUTS(i) {
|
| + int32_t magic = 0x2342aabb + *i * 3;
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int32_t offset = *i;
|
| + byte* from = reinterpret_cast<byte*>(&p1) - offset;
|
| + byte* to = reinterpret_cast<byte*>(&p2) - offset;
|
| + // generate load [#base + #index]
|
| + Node* load = m.Load(kMachineFloat64, m.PointerConstant(from),
|
| + m.Int32Constant(offset));
|
| + m.Store(kMachineFloat64, m.PointerConstant(to), m.Int32Constant(offset),
|
| + load);
|
| + m.Return(m.Int32Constant(magic));
|
| +
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + p1 = *j;
|
| + p2 = *j - 5;
|
| + CHECK_EQ(magic, m.Call());
|
| + CHECK_EQ(p1, p2);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +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.
|
| + int expected = static_cast<int32_t>(*i + *j);
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunInt32AddAndWord32SarP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Int32Add(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Int32Add(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Int32Add(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + // 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;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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<int32_t> m(kMachineWord32);
|
| + MLabel 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) {
|
| + int32_t expected = (*i + *j) == 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + MLabel 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) {
|
| + int32_t expected = (*i + *j) != 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<void> m;
|
| + Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
|
| + m.machine()->Word32Shr()};
|
| + for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + MLabel blocka, blockb;
|
| + m.Branch(m.Word32Equal(m.Int32Add(m.Parameter(0),
|
| + m.NewNode(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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + 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;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(
|
| + m.Word32Equal(m.Int32Add(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;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(
|
| + m.Word32Equal(m.Int32Constant(0), m.Int32Add(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<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = (*i + *j) == 0;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Int32Add(m.Parameter(0), m.Int32Constant(*i)),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = (*j + *i) == 0;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<void> m;
|
| + Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
|
| + m.machine()->Word32Shr()};
|
| + for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Word32Equal(
|
| + m.Int32Add(m.Parameter(0),
|
| + m.NewNode(shops[n], m.Parameter(1), m.Parameter(2))),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_INT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + 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;
|
| + Int32BinopTester bt(&m);
|
| +
|
| + m.Return(m.Int32Sub(bt.param0, bt.param1));
|
| +
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + // Use uint32_t because signed overflow is UB in C.
|
| + int expected = static_cast<int32_t>(*i - *j);
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunInt32SubImm) {
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + // Use uint32_t because signed overflow is UB in C.
|
| + int32_t expected = static_cast<int32_t>(*i - *j);
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + // Use uint32_t because signed overflow is UB in C.
|
| + int32_t expected = static_cast<int32_t>(*j - *i);
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunInt32SubAndWord32SarP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Int32Sub(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + // 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(RunInt32SubAndWord32ShlP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Int32Sub(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + // 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<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Int32Sub(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + // 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(RunInt32SubInBranch) {
|
| + static const int constant = 987654321;
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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<int32_t> m(kMachineWord32);
|
| + MLabel 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) {
|
| + int32_t expected = (*i - *j) == 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + MLabel 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<void> m;
|
| + Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
|
| + m.machine()->Word32Shr()};
|
| + for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + MLabel blocka, blockb;
|
| + m.Branch(m.Word32Equal(m.Int32Sub(m.Parameter(0),
|
| + m.NewNode(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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + 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;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(
|
| + m.Word32Equal(m.Int32Sub(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;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(
|
| + m.Word32Equal(m.Int32Constant(0), m.Int32Sub(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<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = (*i - *j) == 0;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = (*j - *i) == 0;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<void> m;
|
| + Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
|
| + m.machine()->Word32Shr()};
|
| + for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Word32Equal(
|
| + m.Int32Sub(m.Parameter(0),
|
| + m.NewNode(shops[n], m.Parameter(1), m.Parameter(2))),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_INT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + 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;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Int32Mul(bt.param0, bt.param1));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + int expected = static_cast<int32_t>(*i * *j);
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunInt32MulImm) {
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Int32Mul(m.Int32Constant(*i), m.Parameter(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = static_cast<int32_t>(*i * *j);
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant(*i)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = static_cast<int32_t>(*j * *i);
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunInt32MulAndInt32AddP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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));
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + 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));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +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));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunInt32UDivP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Int32UDiv(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<uint32_t>(p0 / p1);
|
| + CHECK_EQ(expected, bt.call(p0, p1));
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Int32Add(bt.param0, m.Int32UDiv(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<uint32_t>(p0 + (p0 / p1));
|
| + 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));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunInt32UModP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Int32UMod(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<uint32_t>(p0 % p1);
|
| + CHECK_EQ(expected, bt.call(p0, p1));
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Int32Add(bt.param0, m.Int32UMod(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<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) {
|
| + uint32_t expected = *i & *j;
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Word32And(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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Word32And(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(RunWord32AndAndWord32ShlP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester 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<int32_t> m;
|
| + Int32BinopTester 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<int32_t> m;
|
| + Int32BinopTester 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<int32_t> m;
|
| + Int32BinopTester 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(
|
| + m.Word32Sar(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1f))));
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + uint32_t expected = *i >> (*j & 0x1f);
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(
|
| + m.Word32Sar(bt.param0, m.Word32And(m.Int32Constant(0x1f), bt.param1)));
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + uint32_t expected = *i >> (0x1f & *j);
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32AndImm) {
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + 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<int32_t> m(kMachineWord32);
|
| + 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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<int32_t> m(kMachineWord32);
|
| + MLabel 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<int32_t> m(kMachineWord32);
|
| + MLabel 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<void> m;
|
| + Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
|
| + m.machine()->Word32Shr()};
|
| + for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + MLabel blocka, blockb;
|
| + m.Branch(m.Word32Equal(m.Word32And(m.Parameter(0),
|
| + m.NewNode(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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + 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;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(
|
| + m.Word32Equal(m.Word32And(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;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(
|
| + m.Word32Equal(m.Int32Constant(0), m.Word32And(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<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = (*i & *j) == 0;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Word32And(m.Parameter(0), m.Int32Constant(*i)),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = (*j & *i) == 0;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32OrP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester 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<int32_t> m;
|
| + Int32BinopTester 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<int32_t> m;
|
| + Int32BinopTester 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<int32_t> m(kMachineWord32);
|
| + 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<int32_t> m(kMachineWord32);
|
| + 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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_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;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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_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<int32_t> m(kMachineWord32);
|
| + MLabel 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_UINT32_INPUTS(j) {
|
| + int32_t expected = (*i | *j) == 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + MLabel 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_UINT32_INPUTS(j) {
|
| + int32_t expected = (*i | *j) != 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<void> m;
|
| + Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
|
| + m.machine()->Word32Shr()};
|
| + for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + MLabel blocka, blockb;
|
| + m.Branch(m.Word32Equal(m.Word32Or(m.Parameter(0),
|
| + m.NewNode(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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + 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;
|
| + 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<int32_t> 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<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = (*i | *j) == 0;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Word32Or(m.Parameter(0), m.Int32Constant(*i)),
|
| + m.Int32Constant(0)));
|
| + FOR_UINT32_INPUTS(j) {
|
| + int32_t expected = (*j | *i) == 0;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32XorP) {
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + 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<int32_t> m;
|
| + Int32BinopTester 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Word32Xor(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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Word32Xor(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));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + 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 int constant = 987654321;
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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) {
|
| + int32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + MLabel 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) {
|
| + int32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + MLabel 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) {
|
| + int32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + MLabel 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) {
|
| + int32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant;
|
| + CHECK_EQ(expected, m.Call(*j));
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<void> m;
|
| + Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
|
| + m.machine()->Word32Shr()};
|
| + for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + MLabel blocka, blockb;
|
| + m.Branch(m.Word32Equal(m.Word32Xor(m.Parameter(0),
|
| + m.NewNode(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_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + 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) {
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + uint32_t shift = *i & 0x1F;
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Word32Shl(bt.param0, bt.param1));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + uint32_t shift = *j & 0x1F;
|
| + uint32_t expected = *i << shift;
|
| + CHECK_EQ(expected, bt.call(*i, shift));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32ShrP) {
|
| + {
|
| + FOR_UINT32_INPUTS(i) {
|
| + uint32_t shift = *i & 0x1F;
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + 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<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + bt.AddReturn(m.Word32Shr(bt.param0, bt.param1));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + uint32_t shift = *j & 0x1F;
|
| + uint32_t expected = *i >> shift;
|
| + CHECK_EQ(expected, bt.call(*i, shift));
|
| + }
|
| + }
|
| + CHECK_EQ(0x00010000, bt.call(0x80000000, 15));
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32SarP) {
|
| + {
|
| + FOR_INT32_INPUTS(i) {
|
| + int32_t shift = *i & 0x1F;
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + 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) {
|
| + FOR_INT32_INPUTS(j) {
|
| + int32_t shift = *j & 0x1F;
|
| + int32_t expected = *i >> shift;
|
| + CHECK_EQ(expected, bt.call(*i, shift));
|
| + }
|
| + }
|
| + CHECK_EQ(0xFFFF0000, bt.call(0x80000000, 15));
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32NotP) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Word32Not(m.Parameter(0)));
|
| + FOR_UINT32_INPUTS(i) {
|
| + int expected = ~(*i);
|
| + CHECK_EQ(expected, m.Call(*i));
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunInt32NegP) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + m.Return(m.Int32Neg(m.Parameter(0)));
|
| + FOR_INT32_INPUTS(i) {
|
| + int expected = -*i;
|
| + CHECK_EQ(expected, m.Call(*i));
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32EqualAndWord32SarP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Parameter(0),
|
| + m.Word32Sar(m.Parameter(1), m.Parameter(2))));
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_INT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + int32_t expected = (*i == (*j >> shift));
|
| + CHECK_EQ(expected, m.Call(*i, *j, shift));
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_INT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + int32_t expected = ((*i >> shift) == *k);
|
| + CHECK_EQ(expected, m.Call(*i, shift, *k));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32EqualAndWord32ShlP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Parameter(0),
|
| + m.Word32Shl(m.Parameter(1), m.Parameter(2))));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + int32_t expected = (*i == (*j << shift));
|
| + CHECK_EQ(expected, m.Call(*i, *j, shift));
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + int32_t expected = ((*i << shift) == *k);
|
| + CHECK_EQ(expected, m.Call(*i, shift, *k));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunWord32EqualAndWord32ShrP) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Parameter(0),
|
| + m.Word32Shr(m.Parameter(1), m.Parameter(2))));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *k & 0x1F;
|
| + int32_t expected = (*i == (*j >> shift));
|
| + CHECK_EQ(expected, m.Call(*i, *j, shift));
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
|
| + kMachineWord32);
|
| + m.Return(m.Word32Equal(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
|
| + m.Parameter(2)));
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + FOR_UINT32_INPUTS(k) {
|
| + uint32_t shift = *j & 0x1F;
|
| + int32_t expected = ((*i >> shift) == *k);
|
| + CHECK_EQ(expected, m.Call(*i, shift, *k));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunDeadNodes) {
|
| + for (int i = 0; true; i++) {
|
| + RawMachineAssemblerTester<int32_t> m(i == 5 ? kMachineWord32
|
| + : kMachineLast);
|
| + 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:
|
| + m.LoadFromPointer(&constant, kMachineWord32);
|
| + 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;
|
| +
|
| + Operator* ops[] = {
|
| + 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()->Int32Div(), m.machine()->Int32UDiv(),
|
| + m.machine()->Int32Mod(), m.machine()->Int32UMod(),
|
| + m.machine()->Int32LessThan(), m.machine()->Int32LessThanOrEqual(),
|
| + m.machine()->Uint32LessThan(), m.machine()->Uint32LessThanOrEqual(),
|
| + NULL};
|
| +
|
| + for (int i = 0; ops[i] != NULL; i++) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
|
| + int constant = 0x55555 + i;
|
| + m.NewNode(ops[i], m.Parameter(0), m.Parameter(1));
|
| + m.Return(m.Int32Constant(constant));
|
| +
|
| + CHECK_EQ(constant, m.Call(1, 1));
|
| + }
|
| +}
|
| +
|
| +
|
| +template <typename CType>
|
| +static void RunLoadImmIndex(MachineRepresentation rep) {
|
| + const int kNumElems = 3;
|
| + CType buffer[kNumElems];
|
| +
|
| + // initialize the buffer with raw data.
|
| + byte* raw = reinterpret_cast<byte*>(buffer);
|
| + for (size_t i = 0; i < sizeof(buffer); i++) {
|
| + raw[i] = (i + sizeof(buffer)) ^ 0xAA;
|
| + }
|
| +
|
| + // Test with various large and small offsets.
|
| + for (int offset = -1; offset <= 200000; offset *= -5) {
|
| + for (int i = 0; i < kNumElems; i++) {
|
| + RawMachineAssemblerTester<CType> m;
|
| + Node* base = m.PointerConstant(buffer - offset);
|
| + Node* index = m.Int32Constant((offset + i) * sizeof(buffer[0]));
|
| + m.Return(m.Load(rep, base, index));
|
| +
|
| + CHECK_EQ(buffer[i], m.Call());
|
| + printf("XXX\n");
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunLoadImmIndex) {
|
| + RunLoadImmIndex<int8_t>(kMachineWord8);
|
| + RunLoadImmIndex<int16_t>(kMachineWord16);
|
| + RunLoadImmIndex<int32_t>(kMachineWord32);
|
| + RunLoadImmIndex<int32_t*>(kMachineTagged);
|
| +
|
| + // TODO(titzer): test kMachineFloat64 loads
|
| + // TODO(titzer): test various indexing modes.
|
| +}
|
| +
|
| +
|
| +template <typename CType>
|
| +static void RunLoadStore(MachineRepresentation rep) {
|
| + const int kNumElems = 4;
|
| + CType buffer[kNumElems];
|
| +
|
| + for (int32_t x = 0; x < kNumElems; x++) {
|
| + int32_t y = kNumElems - x - 1;
|
| + // initialize the buffer with raw data.
|
| + byte* raw = reinterpret_cast<byte*>(buffer);
|
| + for (size_t i = 0; i < sizeof(buffer); i++) {
|
| + raw[i] = (i + sizeof(buffer)) ^ 0xAA;
|
| + }
|
| +
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int32_t OK = 0x29000 + x;
|
| + Node* base = m.PointerConstant(buffer);
|
| + Node* index0 = m.Int32Constant(x * sizeof(buffer[0]));
|
| + Node* load = m.Load(rep, base, index0);
|
| + Node* index1 = m.Int32Constant(y * sizeof(buffer[0]));
|
| + m.Store(rep, base, index1, load);
|
| + m.Return(m.Int32Constant(OK));
|
| +
|
| + CHECK_NE(buffer[x], buffer[y]);
|
| + CHECK_EQ(OK, m.Call());
|
| + CHECK_EQ(buffer[x], buffer[y]);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunLoadStore) {
|
| + RunLoadStore<int8_t>(kMachineWord8);
|
| + RunLoadStore<int16_t>(kMachineWord16);
|
| + RunLoadStore<int32_t>(kMachineWord32);
|
| + RunLoadStore<void*>(kMachineTagged);
|
| + RunLoadStore<double>(kMachineFloat64);
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64Binop) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + double result;
|
| +
|
| + Operator* ops[] = {m.machine()->Float64Add(), m.machine()->Float64Sub(),
|
| + m.machine()->Float64Mul(), m.machine()->Float64Div(),
|
| + m.machine()->Float64Mod(), NULL};
|
| +
|
| + double inf = V8_INFINITY;
|
| + Operator* inputs[] = {
|
| + m.common()->Float64Constant(0), m.common()->Float64Constant(1),
|
| + m.common()->Float64Constant(1), m.common()->Float64Constant(0),
|
| + m.common()->Float64Constant(0), m.common()->Float64Constant(-1),
|
| + m.common()->Float64Constant(-1), m.common()->Float64Constant(0),
|
| + m.common()->Float64Constant(0.22), m.common()->Float64Constant(-1.22),
|
| + m.common()->Float64Constant(-1.22), m.common()->Float64Constant(0.22),
|
| + m.common()->Float64Constant(inf), m.common()->Float64Constant(0.22),
|
| + m.common()->Float64Constant(inf), m.common()->Float64Constant(-inf),
|
| + NULL};
|
| +
|
| + for (int i = 0; ops[i] != NULL; i++) {
|
| + for (int j = 0; inputs[j] != NULL; j += 2) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* a = m.NewNode(inputs[j]);
|
| + Node* b = m.NewNode(inputs[j + 1]);
|
| + Node* binop = m.NewNode(ops[i], a, b);
|
| + Node* base = m.PointerConstant(&result);
|
| + Node* zero = m.Int32Constant(0);
|
| + m.Store(kMachineFloat64, base, zero, binop);
|
| + m.Return(m.Int32Constant(i + j));
|
| + CHECK_EQ(i + j, m.Call());
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunDeadFloat64Binops) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| +
|
| + Operator* ops[] = {m.machine()->Float64Add(), m.machine()->Float64Sub(),
|
| + m.machine()->Float64Mul(), m.machine()->Float64Div(),
|
| + m.machine()->Float64Mod(), NULL};
|
| +
|
| + for (int i = 0; ops[i] != NULL; i++) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int constant = 0x53355 + i;
|
| + m.NewNode(ops[i], m.Float64Constant(0.1), m.Float64Constant(1.11));
|
| + m.Return(m.Int32Constant(constant));
|
| + CHECK_EQ(constant, m.Call());
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64AddP) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Float64BinopTester bt(&m);
|
| +
|
| + bt.AddReturn(m.Float64Add(bt.param0, bt.param1));
|
| +
|
| + FOR_FLOAT64_INPUTS(pl) {
|
| + FOR_FLOAT64_INPUTS(pr) {
|
| + double expected = *pl + *pr;
|
| + CHECK_EQ(expected, bt.call(*pl, *pr));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64SubP) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Float64BinopTester bt(&m);
|
| +
|
| + bt.AddReturn(m.Float64Sub(bt.param0, bt.param1));
|
| +
|
| + FOR_FLOAT64_INPUTS(pl) {
|
| + FOR_FLOAT64_INPUTS(pr) {
|
| + double expected = *pl - *pr;
|
| + CHECK_EQ(expected, bt.call(*pl, *pr));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64SubImm1) {
|
| + double input = 0.0;
|
| + double output = 0.0;
|
| +
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* t0 = m.LoadFromPointer(&input, kMachineFloat64);
|
| + Node* t1 = m.Float64Sub(m.Float64Constant(*i), t0);
|
| + m.StoreToPointer(&output, kMachineFloat64, t1);
|
| + m.Return(m.Int32Constant(0));
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + input = *j;
|
| + double expected = *i - input;
|
| + CHECK_EQ(0, m.Call());
|
| + CHECK_EQ(expected, output);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64SubImm2) {
|
| + double input = 0.0;
|
| + double output = 0.0;
|
| +
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* t0 = m.LoadFromPointer(&input, kMachineFloat64);
|
| + Node* t1 = m.Float64Sub(t0, m.Float64Constant(*i));
|
| + m.StoreToPointer(&output, kMachineFloat64, t1);
|
| + m.Return(m.Int32Constant(0));
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + input = *j;
|
| + double expected = input - *i;
|
| + CHECK_EQ(0, m.Call());
|
| + CHECK_EQ(expected, output);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +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;
|
| + CHECK_EQ(expected, bt.call(*pl, *pr));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64MulAndFloat64AddP) {
|
| + double input_a = 0.0;
|
| + double input_b = 0.0;
|
| + double input_c = 0.0;
|
| + double output = 0.0;
|
| +
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
|
| + Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
|
| + Node* c = m.LoadFromPointer(&input_c, kMachineFloat64);
|
| + m.StoreToPointer(&output, kMachineFloat64,
|
| + m.Float64Add(m.Float64Mul(a, b), c));
|
| + m.Return(m.Int32Constant(0));
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + FOR_FLOAT64_INPUTS(k) {
|
| + input_a = *i;
|
| + input_b = *j;
|
| + input_c = *k;
|
| + volatile double temp = input_a * input_b;
|
| + volatile double expected = temp + input_c;
|
| + CHECK_EQ(0, m.Call());
|
| + CHECK_EQ(expected, output);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
|
| + Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
|
| + Node* c = m.LoadFromPointer(&input_c, kMachineFloat64);
|
| + m.StoreToPointer(&output, kMachineFloat64,
|
| + m.Float64Add(a, m.Float64Mul(b, c)));
|
| + m.Return(m.Int32Constant(0));
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + FOR_FLOAT64_INPUTS(k) {
|
| + input_a = *i;
|
| + input_b = *j;
|
| + input_c = *k;
|
| + volatile double temp = input_b * input_c;
|
| + volatile double expected = input_a + temp;
|
| + CHECK_EQ(0, m.Call());
|
| + CHECK_EQ(expected, output);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64MulAndFloat64SubP) {
|
| + double input_a = 0.0;
|
| + double input_b = 0.0;
|
| + double input_c = 0.0;
|
| + double output = 0.0;
|
| +
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
|
| + Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
|
| + Node* c = m.LoadFromPointer(&input_c, kMachineFloat64);
|
| + m.StoreToPointer(&output, kMachineFloat64,
|
| + m.Float64Sub(a, m.Float64Mul(b, c)));
|
| + m.Return(m.Int32Constant(0));
|
| +
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + FOR_FLOAT64_INPUTS(k) {
|
| + input_a = *i;
|
| + input_b = *j;
|
| + input_c = *k;
|
| + volatile double temp = input_b * input_c;
|
| + volatile double expected = input_a - temp;
|
| + CHECK_EQ(0, m.Call());
|
| + CHECK_EQ(expected, output);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64MulImm) {
|
| + double input = 0.0;
|
| + double output = 0.0;
|
| +
|
| + {
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* t0 = m.LoadFromPointer(&input, kMachineFloat64);
|
| + Node* t1 = m.Float64Mul(m.Float64Constant(*i), t0);
|
| + m.StoreToPointer(&output, kMachineFloat64, t1);
|
| + m.Return(m.Int32Constant(0));
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + input = *j;
|
| + double expected = *i * input;
|
| + CHECK_EQ(0, m.Call());
|
| + CHECK_EQ(expected, output);
|
| + }
|
| + }
|
| + }
|
| + {
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* t0 = m.LoadFromPointer(&input, kMachineFloat64);
|
| + Node* t1 = m.Float64Mul(t0, m.Float64Constant(*i));
|
| + m.StoreToPointer(&output, kMachineFloat64, t1);
|
| + m.Return(m.Int32Constant(0));
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + input = *j;
|
| + double expected = input * *i;
|
| + CHECK_EQ(0, m.Call());
|
| + CHECK_EQ(expected, output);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64DivP) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Float64BinopTester bt(&m);
|
| +
|
| + bt.AddReturn(m.Float64Div(bt.param0, bt.param1));
|
| +
|
| + FOR_FLOAT64_INPUTS(pl) {
|
| + FOR_FLOAT64_INPUTS(pr) {
|
| + double expected = *pl / *pr;
|
| + CHECK_EQ(expected, bt.call(*pl, *pr));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64ModP) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Float64BinopTester bt(&m);
|
| +
|
| + bt.AddReturn(m.Float64Mod(bt.param0, bt.param1));
|
| +
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + FOR_FLOAT64_INPUTS(j) {
|
| + double expected = modulo(*i, *j);
|
| + double found = bt.call(*i, *j);
|
| + CHECK_EQ(expected, found);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunConvertInt32ToFloat64_A) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int32_t magic = 0x986234;
|
| + double result = 0;
|
| +
|
| + Node* convert = m.ConvertInt32ToFloat64(m.Int32Constant(magic));
|
| + m.Store(kMachineFloat64, m.PointerConstant(&result), m.Int32Constant(0),
|
| + convert);
|
| + m.Return(m.Int32Constant(magic));
|
| +
|
| + CHECK_EQ(magic, m.Call());
|
| + CHECK_EQ(static_cast<double>(magic), result);
|
| +}
|
| +
|
| +
|
| +TEST(RunConvertInt32ToFloat64_B) {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + double output = 0;
|
| +
|
| + Node* convert = m.ConvertInt32ToFloat64(m.Parameter(0));
|
| + m.Store(kMachineFloat64, m.PointerConstant(&output), m.Int32Constant(0),
|
| + convert);
|
| + m.Return(m.Parameter(0));
|
| +
|
| + FOR_INT32_INPUTS(i) {
|
| + int32_t expect = *i;
|
| + CHECK_EQ(expect, m.Call(expect));
|
| + CHECK_EQ(static_cast<double>(expect), output);
|
| + }
|
| +}
|
| +
|
| +
|
| +// TODO(titzer): Test ConvertUint32ToFloat64
|
| +
|
| +
|
| +TEST(RunConvertFloat64ToInt32_A) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int32_t magic = 0x786234;
|
| + double input = 11.1;
|
| + int32_t result = 0;
|
| +
|
| + m.Store(kMachineWord32, m.PointerConstant(&result), m.Int32Constant(0),
|
| + m.ConvertFloat64ToInt32(m.Float64Constant(input)));
|
| + m.Return(m.Int32Constant(magic));
|
| +
|
| + CHECK_EQ(magic, m.Call());
|
| + CHECK_EQ(static_cast<int32_t>(input), result);
|
| +}
|
| +
|
| +
|
| +TEST(RunConvertFloat64ToInt32_B) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + double input = 0;
|
| + int32_t output = 0;
|
| +
|
| + Node* load =
|
| + m.Load(kMachineFloat64, m.PointerConstant(&input), m.Int32Constant(0));
|
| + Node* convert = m.ConvertFloat64ToInt32(load);
|
| + m.Store(kMachineWord32, m.PointerConstant(&output), m.Int32Constant(0),
|
| + convert);
|
| + m.Return(convert);
|
| +
|
| + {
|
| + FOR_INT32_INPUTS(i) {
|
| + input = *i;
|
| + int expect = *i;
|
| + CHECK_EQ(expect, m.Call());
|
| + CHECK_EQ(expect, output);
|
| + }
|
| + }
|
| +
|
| + {
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + input = *i;
|
| + // TODO(titzer): float64 -> int32 outside of the int32 range; the machine
|
| + // backends are all wrong in different ways, and they certainly don't
|
| + // implement the JavaScript conversions correctly.
|
| + if (std::isnan(input) || input > INT_MAX || input < INT_MIN) {
|
| + continue;
|
| + }
|
| + int32_t expect = static_cast<int32_t>(input);
|
| + CHECK_EQ(expect, m.Call());
|
| + CHECK_EQ(expect, output);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +// TODO(titzer): test ConvertFloat64ToUint32
|
| +
|
| +
|
| +TEST(RunConvertFloat64ToInt32_truncation) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + int32_t magic = 0x786234;
|
| + double input = 3.9;
|
| + int32_t result = 0;
|
| +
|
| + Node* input_node =
|
| + m.Load(kMachineFloat64, m.PointerConstant(&input), m.Int32Constant(0));
|
| + m.Store(kMachineWord32, m.PointerConstant(&result), m.Int32Constant(0),
|
| + m.ConvertFloat64ToInt32(input_node));
|
| + m.Return(m.Int32Constant(magic));
|
| +
|
| + for (int i = -200; i < 200; i++) {
|
| + input = i + (i < 0 ? -0.9 : 0.9);
|
| + CHECK_EQ(magic, m.Call());
|
| + CHECK_EQ(i, result);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunConvertFloat64ToInt32_spilled) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + const int kNumInputs = 32;
|
| + int32_t magic = 0x786234;
|
| + double input[kNumInputs];
|
| + int32_t result[kNumInputs];
|
| + Node* input_node[kNumInputs];
|
| +
|
| + for (int i = 0; i < kNumInputs; i++) {
|
| + input_node[i] = m.Load(kMachineFloat64, m.PointerConstant(&input),
|
| + m.Int32Constant(i * 8));
|
| + }
|
| +
|
| + for (int i = 0; i < kNumInputs; i++) {
|
| + m.Store(kMachineWord32, m.PointerConstant(&result), m.Int32Constant(i * 4),
|
| + m.ConvertFloat64ToInt32(input_node[i]));
|
| + }
|
| +
|
| + m.Return(m.Int32Constant(magic));
|
| +
|
| + for (int i = 0; i < kNumInputs; i++) {
|
| + input[i] = 100.9 + i;
|
| + }
|
| +
|
| + CHECK_EQ(magic, m.Call());
|
| +
|
| + for (int i = 0; i < kNumInputs; i++) {
|
| + CHECK_EQ(result[i], 100 + i);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunDeadConvertFloat64ToInt32) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + const int magic = 0x88abcda4;
|
| + m.ConvertFloat64ToInt32(m.Float64Constant(999.78));
|
| + m.Return(m.Int32Constant(magic));
|
| + CHECK_EQ(magic, m.Call());
|
| +}
|
| +
|
| +
|
| +TEST(RunDeadConvertInt32ToFloat64) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + const int magic = 0x8834abcd;
|
| + m.ConvertInt32ToFloat64(m.Int32Constant(magic - 6888));
|
| + 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;
|
| + MLabel header, body, end;
|
| + Node* false_node = m.Int32Constant(false_val);
|
| + m.Goto(&header);
|
| + m.Bind(&header);
|
| + Node* phi = m.Phi(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(RunDoubleDiamond) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| +
|
| + const int magic = 99645;
|
| + double buffer = 0.1;
|
| + double constant = 99.99;
|
| +
|
| + MLabel blocka, blockb, end;
|
| + 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);
|
| + Node* phi = m.Phi(k2, k1);
|
| + m.Store(kMachineFloat64, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
|
| + 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;
|
| +
|
| + MLabel blocka, blockb, end;
|
| + 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);
|
| + Node* phi = m.Phi(k2, k1);
|
| + m.Store(kMachineTagged, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
|
| + 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;
|
| +
|
| + MLabel blocka, blockb, end;
|
| + 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);
|
| + Node* dphi = m.Phi(d2, d1);
|
| + Node* rphi = m.Phi(r2, r1);
|
| + m.Store(kMachineFloat64, m.PointerConstant(&dbuffer), m.Int32Constant(0),
|
| + dphi);
|
| + m.Store(kMachineTagged, m.PointerConstant(&rbuffer), m.Int32Constant(0),
|
| + rphi);
|
| + 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;
|
| +
|
| + MLabel blocka, blockb, mid, blockd, blocke, end;
|
| + 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);
|
| + Node* dphi1 = m.Phi(d2, d1);
|
| + Node* rphi1 = m.Phi(r2, r1);
|
| + m.Branch(m.Int32Constant(0), &blockd, &blocke);
|
| +
|
| + m.Bind(&blockd);
|
| + m.Goto(&end);
|
| + m.Bind(&blocke);
|
| + m.Goto(&end);
|
| + m.Bind(&end);
|
| + Node* dphi2 = m.Phi(d1, dphi1);
|
| + Node* rphi2 = m.Phi(r1, rphi1);
|
| +
|
| + m.Store(kMachineFloat64, m.PointerConstant(&dbuffer), m.Int32Constant(0),
|
| + dphi2);
|
| + m.Store(kMachineTagged, m.PointerConstant(&rbuffer), m.Int32Constant(0),
|
| + rphi2);
|
| + m.Return(m.Int32Constant(magic));
|
| +
|
| + CHECK_EQ(magic, m.Call());
|
| + CHECK_EQ(dconstant, dbuffer);
|
| + CHECK(rexpected->SameValue(rbuffer));
|
| +}
|
| +
|
| +
|
| +TEST(RunDoubleLoopPhi) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + MLabel header, body, end;
|
| +
|
| + 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);
|
| + Node* phi = m.Phi(dk, dk);
|
| + phi->ReplaceInput(1, phi);
|
| + m.Branch(zero, &body, &end);
|
| + m.Bind(&body);
|
| + m.Goto(&header);
|
| + m.Bind(&end);
|
| + m.Store(kMachineFloat64, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
|
| + 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);
|
| +
|
| + MLabel header, body, body_cont, end;
|
| +
|
| + m.Goto(&header);
|
| +
|
| + m.Bind(&header);
|
| + Node* i = m.Phi(zero, zero);
|
| + Node* j = m.Phi(zero, zero);
|
| + 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);
|
| +
|
| + MLabel header, body, body_cont, end;
|
| +
|
| + m.Goto(&header);
|
| +
|
| + m.Bind(&header);
|
| + Node* i = m.Phi(zero, zero);
|
| + Node* j = m.Phi(zero, zero);
|
| + Node* k = m.Phi(zero, zero);
|
| + 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);
|
| + Node* n0 = m.Load(kMachineWord32, base, m.Int32Constant(0 * sizeof(int32_t)));
|
| + Node* n1 = m.Load(kMachineWord32, base, m.Int32Constant(1 * sizeof(int32_t)));
|
| + Node* n2 = m.Load(kMachineWord32, base, m.Int32Constant(2 * sizeof(int32_t)));
|
| + Node* n3 = m.Load(kMachineWord32, base, m.Int32Constant(3 * sizeof(int32_t)));
|
| + Node* n4 = m.Load(kMachineWord32, base, m.Int32Constant(4 * sizeof(int32_t)));
|
| + Node* n5 = m.Load(kMachineWord32, base, m.Int32Constant(5 * sizeof(int32_t)));
|
| + Node* n6 = m.Load(kMachineWord32, base, m.Int32Constant(6 * sizeof(int32_t)));
|
| + Node* n7 = m.Load(kMachineWord32, base, m.Int32Constant(7 * sizeof(int32_t)));
|
| +
|
| + 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());
|
| +}
|
| +
|
| +
|
| +#if MACHINE_ASSEMBLER_SUPPORTS_CALL_C
|
| +
|
| +static int Seven() { return 7; }
|
| +static int UnaryMinus(int a) { return -a; }
|
| +static int APlusTwoB(int a, int b) { return a + 2 * b; }
|
| +
|
| +
|
| +TEST(RunCallSeven) {
|
| + for (int i = 0; i < 2; i++) {
|
| + bool call_direct = i == 0;
|
| + void* function_address =
|
| + reinterpret_cast<void*>(reinterpret_cast<intptr_t>(&Seven));
|
| +
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node** args = NULL;
|
| + MachineRepresentation* arg_types = NULL;
|
| + Node* function =
|
| + call_direct ? m.PointerConstant(function_address)
|
| + : m.LoadFromPointer(&function_address,
|
| + MachineOperatorBuilder::pointer_rep());
|
| + m.Return(m.CallC(function, kMachineWord32, arg_types, args, 0));
|
| +
|
| + CHECK_EQ(7, m.Call());
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunCallUnaryMinus) {
|
| + for (int i = 0; i < 2; i++) {
|
| + bool call_direct = i == 0;
|
| + void* function_address =
|
| + reinterpret_cast<void*>(reinterpret_cast<intptr_t>(&UnaryMinus));
|
| +
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + Node* args[] = {m.Parameter(0)};
|
| + MachineRepresentation arg_types[] = {kMachineWord32};
|
| + Node* function =
|
| + call_direct ? m.PointerConstant(function_address)
|
| + : m.LoadFromPointer(&function_address,
|
| + MachineOperatorBuilder::pointer_rep());
|
| + m.Return(m.CallC(function, kMachineWord32, arg_types, args, 1));
|
| +
|
| + FOR_INT32_INPUTS(i) {
|
| + int a = *i;
|
| + CHECK_EQ(-a, m.Call(a));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunCallAPlusTwoB) {
|
| + for (int i = 0; i < 2; i++) {
|
| + bool call_direct = i == 0;
|
| + void* function_address =
|
| + reinterpret_cast<void*>(reinterpret_cast<intptr_t>(&APlusTwoB));
|
| +
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
|
| + Node* args[] = {m.Parameter(0), m.Parameter(1)};
|
| + MachineRepresentation arg_types[] = {kMachineWord32, kMachineWord32};
|
| + Node* function =
|
| + call_direct ? m.PointerConstant(function_address)
|
| + : m.LoadFromPointer(&function_address,
|
| + MachineOperatorBuilder::pointer_rep());
|
| + m.Return(m.CallC(function, kMachineWord32, arg_types, args, 2));
|
| +
|
| + FOR_INT32_INPUTS(i) {
|
| + FOR_INT32_INPUTS(j) {
|
| + int a = *i;
|
| + int b = *j;
|
| + int result = m.Call(a, b);
|
| + CHECK_EQ(a + 2 * b, result);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +#endif // MACHINE_ASSEMBLER_SUPPORTS_CALL_C
|
| +
|
| +
|
| +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;
|
| + Node* a = load_a ? m->Load(kMachineFloat64, m->PointerConstant(&buffer[0]))
|
| + : m->Float64Constant(x);
|
| + Node* b = load_b ? m->Load(kMachineFloat64, m->PointerConstant(&buffer[1]))
|
| + : m->Float64Constant(y);
|
| + Node* cmp = NULL;
|
| + 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) {
|
| + double inf = V8_INFINITY;
|
| + // 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++) {
|
| + for (size_t input = 0; input < ARRAY_SIZE(inputs); input += 2) {
|
| + 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;
|
| +
|
| + Operator* operators[] = {m.machine()->Float64Equal(),
|
| + m.machine()->Float64LessThan(),
|
| + m.machine()->Float64LessThanOrEqual()};
|
| +
|
| + double nan = v8::base::OS::nan_value();
|
| +
|
| + FOR_FLOAT64_INPUTS(i) {
|
| + for (size_t o = 0; o < ARRAY_SIZE(operators); ++o) {
|
| + 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);
|
| + m.Return(m.NewNode(operators[o], a, b));
|
| + CHECK_EQ(0, m.Call());
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunFloat64Equal) {
|
| + double input_a = 0.0;
|
| + double input_b = 0.0;
|
| +
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
|
| + Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
|
| + 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;
|
| + Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
|
| + Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
|
| + 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());
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +template <typename IntType, MachineRepresentation kRepresentation>
|
| +static void LoadStoreTruncation() {
|
| + IntType input;
|
| +
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* a = m.LoadFromPointer(&input, kRepresentation);
|
| + Node* ap1 = m.Int32Add(a, m.Int32Constant(1));
|
| + m.StoreToPointer(&input, kRepresentation, ap1);
|
| + m.Return(ap1);
|
| +
|
| + const IntType max = std::numeric_limits<IntType>::max();
|
| + const IntType min = std::numeric_limits<IntType>::min();
|
| +
|
| + // Test upper bound.
|
| + input = max;
|
| + CHECK_EQ(max + 1, m.Call());
|
| + CHECK_EQ(min, input);
|
| +
|
| + // Test lower bound.
|
| + input = min;
|
| + CHECK_EQ(max + 2, m.Call());
|
| + CHECK_EQ(min + 1, input);
|
| +
|
| + // Test all one byte values that are not one byte bounds.
|
| + for (int i = -127; i < 127; i++) {
|
| + input = i;
|
| + int expected = i >= 0 ? i + 1 : max + (i - min) + 2;
|
| + CHECK_EQ(expected, m.Call());
|
| + CHECK_EQ(i + 1, input);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunLoadStoreTruncation) {
|
| + LoadStoreTruncation<int8_t, kMachineWord8>();
|
| + LoadStoreTruncation<int16_t, kMachineWord16>();
|
| +}
|
| +
|
| +
|
| +static void IntPtrCompare(intptr_t left, intptr_t right) {
|
| + for (int test = 0; test < 7; test++) {
|
| + RawMachineAssemblerTester<bool> m(MachineOperatorBuilder::pointer_rep(),
|
| + MachineOperatorBuilder::pointer_rep());
|
| + Node* p0 = m.Parameter(0);
|
| + Node* p1 = m.Parameter(1);
|
| + Node* res = NULL;
|
| + 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};
|
| + for (size_t i = 0; i < ARRAY_SIZE(inputs) - 1; i++) {
|
| + 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]);
|
| + Node* elem_size = m.ConvertInt32ToIntPtr(m.Int32Constant(sizeof(inputs[0])));
|
| + for (int i = 0; i < kInputSize; i++) {
|
| + m.Store(kMachineWord32, output, m.Load(kMachineWord32, input));
|
| + 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]);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunSpillLotsOfThings) {
|
| + static const int kInputSize = 1000;
|
| + RawMachineAssemblerTester<void> m;
|
| + 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++) {
|
| + m.StoreToPointer(&outputs[i], kMachineWord32, accs[i]);
|
| + }
|
| + m.Return(one);
|
| + m.Call();
|
| + for (int i = 0; i < kInputSize; i++) {
|
| + CHECK_EQ(outputs[i], i + 2);
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunSpillConstantsAndParameters) {
|
| + static const size_t kInputSize = 1000;
|
| + static const int32_t kBase = 987;
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
|
| + int32_t outputs[kInputSize];
|
| + Node* csts[kInputSize];
|
| + Node* accs[kInputSize];
|
| + Node* acc = m.Int32Constant(0);
|
| + for (size_t i = 0; i < kInputSize; i++) {
|
| + csts[i] = m.Int32Constant(static_cast<int32_t>(kBase + i));
|
| + }
|
| + for (size_t i = 0; i < kInputSize; i++) {
|
| + acc = m.Int32Add(acc, csts[i]);
|
| + accs[i] = acc;
|
| + }
|
| + for (size_t i = 0; i < kInputSize; i++) {
|
| + m.StoreToPointer(&outputs[i], kMachineWord32, accs[i]);
|
| + }
|
| + 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;
|
| + for (size_t k = 0; k < kInputSize; k++) {
|
| + expected += kBase + k;
|
| + }
|
| + CHECK_EQ(expected, m.Call(*i, *j));
|
| + expected = 0;
|
| + for (size_t k = 0; k < kInputSize; k++) {
|
| + expected += kBase + k;
|
| + CHECK_EQ(expected, outputs[k]);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunNewSpaceConstantsInPhi) {
|
| + RawMachineAssemblerTester<Object*> m(kMachineWord32);
|
| +
|
| + 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);
|
| +
|
| + MLabel blocka, blockb, end;
|
| + m.Branch(m.Parameter(0), &blocka, &blockb);
|
| + m.Bind(&blocka);
|
| + m.Goto(&end);
|
| + m.Bind(&blockb);
|
| + m.Goto(&end);
|
| +
|
| + m.Bind(&end);
|
| + Node* phi = m.Phi(true_node, false_node);
|
| + m.Return(phi);
|
| +
|
| + CHECK_EQ(*false_val, m.Call(0));
|
| + CHECK_EQ(*true_val, m.Call(1));
|
| +}
|
| +
|
| +
|
| +#if MACHINE_ASSEMBLER_SUPPORTS_CALL_C
|
| +
|
| +TEST(RunSpillLotsOfThingsWithCall) {
|
| + static const int kInputSize = 1000;
|
| + RawMachineAssemblerTester<void> m;
|
| + 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;
|
| + }
|
| + // If the spill slot computation is wrong, it might load from the c frame
|
| + {
|
| + void* func = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(&Seven));
|
| + Node** args = NULL;
|
| + MachineRepresentation* arg_types = NULL;
|
| + m.CallC(m.PointerConstant(func), kMachineWord32, arg_types, args, 0);
|
| + }
|
| + for (int i = 0; i < kInputSize; i++) {
|
| + m.StoreToPointer(&outputs[i], kMachineWord32, accs[i]);
|
| + }
|
| + m.Return(one);
|
| + m.Call();
|
| + for (int i = 0; i < kInputSize; i++) {
|
| + CHECK_EQ(outputs[i], i + 2);
|
| + }
|
| +}
|
| +
|
| +#endif // MACHINE_ASSEMBLER_SUPPORTS_CALL_C
|
| +
|
| +#endif
|
|
|