Commit f2503fee authored by Nico Hartmann's avatar Nico Hartmann Committed by Commit Bot

Removes premature constant folding in CodeAssembler

Many binary operations defiend in CodeAssembler check for constants
in the inputs and apply simplification if applicable. This is now
performed by the MachineOperatorReducer in a uniform way. To avoid
code duplication, the premature optimizations in CodeAssembler have
been removed in this CL.

Bug: v8:10021
Change-Id: I9b99f05e4f9ab31ff933f22d62674ee80efee8ac
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1995277Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65707}
parent 2806dd78
This diff is collapsed.
......@@ -249,6 +249,10 @@ class CodeAssemblerParameterizedLabel;
V(Float64Min, Float64T, Float64T, Float64T) \
V(Float64InsertLowWord32, Float64T, Float64T, Word32T) \
V(Float64InsertHighWord32, Float64T, Float64T, Word32T) \
V(IntPtrAdd, WordT, WordT, WordT) \
V(IntPtrSub, WordT, WordT, WordT) \
V(IntPtrMul, WordT, WordT, WordT) \
V(IntPtrDiv, IntPtrT, IntPtrT, IntPtrT) \
V(IntPtrAddWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
V(IntPtrSubWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
V(Int32Add, Word32T, Word32T, Word32T) \
......@@ -259,9 +263,27 @@ class CodeAssemblerParameterizedLabel;
V(Int32MulWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T) \
V(Int32Div, Int32T, Int32T, Int32T) \
V(Int32Mod, Int32T, Int32T, Int32T) \
V(WordOr, WordT, WordT, WordT) \
V(WordAnd, WordT, WordT, WordT) \
V(WordXor, WordT, WordT, WordT) \
V(WordRor, WordT, WordT, IntegralT) \
V(WordShl, WordT, WordT, IntegralT) \
V(WordShr, WordT, WordT, IntegralT) \
V(WordSar, WordT, WordT, IntegralT) \
V(Word32Or, Word32T, Word32T, Word32T) \
V(Word32And, Word32T, Word32T, Word32T) \
V(Word32Xor, Word32T, Word32T, Word32T) \
V(Word32Ror, Word32T, Word32T, Word32T) \
V(Word64Ror, Word64T, Word64T, Word64T)
V(Word32Shl, Word32T, Word32T, Word32T) \
V(Word32Shr, Word32T, Word32T, Word32T) \
V(Word32Sar, Word32T, Word32T, Word32T) \
V(Word64And, Word64T, Word64T, Word64T) \
V(Word64Or, Word64T, Word64T, Word64T) \
V(Word64Xor, Word64T, Word64T, Word64T) \
V(Word64Ror, Word64T, Word64T, Word64T) \
V(Word64Shl, Word64T, Word64T, Word64T) \
V(Word64Shr, Word64T, Word64T, Word64T) \
V(Word64Sar, Word64T, Word64T, Word64T)
TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
......@@ -825,10 +847,6 @@ class V8_EXPORT_PRIVATE CodeAssembler {
Int32Mul(static_cast<Node*>(left), static_cast<Node*>(right)));
}
TNode<WordT> IntPtrAdd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<IntPtrT> IntPtrDiv(TNode<IntPtrT> left, TNode<IntPtrT> right);
TNode<WordT> IntPtrSub(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<WordT> IntPtrMul(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<IntPtrT> IntPtrAdd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
return Signed(
IntPtrAdd(static_cast<Node*>(left), static_cast<Node*>(right)));
......@@ -872,37 +890,6 @@ class V8_EXPORT_PRIVATE CodeAssembler {
TNode<Word32T> Word32Shr(SloppyTNode<Word32T> value, int shift);
TNode<Word32T> Word32Sar(SloppyTNode<Word32T> value, int shift);
TNode<WordT> WordOr(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<WordT> WordAnd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<WordT> WordXor(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
TNode<WordT> WordShl(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
TNode<WordT> WordShr(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
TNode<WordT> WordSar(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
TNode<Word32T> Word32Or(SloppyTNode<Word32T> left,
SloppyTNode<Word32T> right);
TNode<Word32T> Word32And(SloppyTNode<Word32T> left,
SloppyTNode<Word32T> right);
TNode<Word32T> Word32Xor(SloppyTNode<Word32T> left,
SloppyTNode<Word32T> right);
TNode<Word32T> Word32Shl(SloppyTNode<Word32T> left,
SloppyTNode<Word32T> right);
TNode<Word32T> Word32Shr(SloppyTNode<Word32T> left,
SloppyTNode<Word32T> right);
TNode<Word32T> Word32Sar(SloppyTNode<Word32T> left,
SloppyTNode<Word32T> right);
TNode<Word64T> Word64Or(SloppyTNode<Word64T> left,
SloppyTNode<Word64T> right);
TNode<Word64T> Word64And(SloppyTNode<Word64T> left,
SloppyTNode<Word64T> right);
TNode<Word64T> Word64Xor(SloppyTNode<Word64T> left,
SloppyTNode<Word64T> right);
TNode<Word64T> Word64Shl(SloppyTNode<Word64T> left,
SloppyTNode<Word64T> right);
TNode<Word64T> Word64Shr(SloppyTNode<Word64T> left,
SloppyTNode<Word64T> right);
TNode<Word64T> Word64Sar(SloppyTNode<Word64T> left,
SloppyTNode<Word64T> right);
// Unary
#define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
TNode<ResType> name(SloppyTNode<ArgType> a);
......
......@@ -108,8 +108,6 @@ v8_source_set("unittests_sources") {
"compiler/branch-elimination-unittest.cc",
"compiler/bytecode-analysis-unittest.cc",
"compiler/checkpoint-elimination-unittest.cc",
"compiler/code-assembler-unittest.cc",
"compiler/code-assembler-unittest.h",
"compiler/common-operator-reducer-unittest.cc",
"compiler/common-operator-unittest.cc",
"compiler/compiler-test-utils.h",
......
// Copyright 2017 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 "test/unittests/compiler/code-assembler-unittest.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/interface-descriptors.h"
#include "src/compiler/node.h"
#include "src/execution/isolate.h"
#include "src/objects/objects-inl.h"
#include "test/unittests/compiler/compiler-test-utils.h"
#include "test/unittests/compiler/node-test-utils.h"
using ::testing::_;
using ::testing::Eq;
namespace v8 {
namespace internal {
namespace compiler {
CodeAssemblerTestState::CodeAssemblerTestState(CodeAssemblerTest* test)
: CodeAssemblerState(test->isolate(), test->zone(), VoidDescriptor{},
Code::STUB, "test",
PoisoningMitigationLevel::kPoisonCriticalOnly) {}
TARGET_TEST_F(CodeAssemblerTest, IntPtrAdd) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(1);
TNode<WordT> add = m.IntPtrAdd(a, b);
EXPECT_THAT(add, IsIntPtrAdd(Eq(a), Eq(b)));
}
// x + 0 => x
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(0);
TNode<WordT> add = m.IntPtrAdd(a, b);
EXPECT_THAT(add, a);
}
// 0 + x => x
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(0);
TNode<WordT> add = m.IntPtrAdd(b, a);
EXPECT_THAT(add, a);
}
// CONST_a + CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(22);
TNode<IntPtrT> b = m.IntPtrConstant(33);
TNode<IntPtrT> c = m.IntPtrAdd(a, b);
EXPECT_THAT(c, IsIntPtrConstant(55));
}
}
TARGET_TEST_F(CodeAssemblerTest, IntPtrSub) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(1);
TNode<WordT> sub = m.IntPtrSub(a, b);
EXPECT_THAT(sub, IsIntPtrSub(Eq(a), Eq(b)));
}
// x - 0 => x
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(0);
TNode<WordT> c = m.IntPtrSub(a, b);
EXPECT_THAT(c, a);
}
// CONST_a - CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(100);
TNode<IntPtrT> b = m.IntPtrConstant(1);
TNode<IntPtrT> c = m.IntPtrSub(a, b);
EXPECT_THAT(c, IsIntPtrConstant(99));
}
}
TARGET_TEST_F(CodeAssemblerTest, IntPtrMul) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(100);
TNode<WordT> mul = m.IntPtrMul(a, b);
EXPECT_THAT(mul, IsIntPtrMul(Eq(a), Eq(b)));
}
// x * 1 => x
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(1);
TNode<WordT> mul = m.IntPtrMul(a, b);
EXPECT_THAT(mul, a);
}
// 1 * x => x
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(1);
TNode<WordT> mul = m.IntPtrMul(b, a);
EXPECT_THAT(mul, a);
}
// CONST_a * CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(100);
TNode<IntPtrT> b = m.IntPtrConstant(5);
TNode<IntPtrT> c = m.IntPtrMul(a, b);
EXPECT_THAT(c, IsIntPtrConstant(500));
}
// x * 2^CONST => x << CONST
{
Node* a = m.Parameter(0);
TNode<IntPtrT> b = m.IntPtrConstant(1 << 3);
TNode<WordT> c = m.IntPtrMul(a, b);
EXPECT_THAT(c, IsWordShl(a, IsIntPtrConstant(3)));
}
// 2^CONST * x => x << CONST
{
TNode<IntPtrT> a = m.IntPtrConstant(1 << 3);
Node* b = m.Parameter(0);
TNode<WordT> c = m.IntPtrMul(a, b);
EXPECT_THAT(c, IsWordShl(b, IsIntPtrConstant(3)));
}
}
TARGET_TEST_F(CodeAssemblerTest, IntPtrDiv) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
TNode<IntPtrT> b = m.IntPtrConstant(100);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, IsIntPtrDiv(Matcher<Node*>(a), Matcher<Node*>(b)));
}
// x / 1 => x
{
TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
TNode<IntPtrT> b = m.IntPtrConstant(1);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, a);
}
// CONST_a / CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(100);
TNode<IntPtrT> b = m.IntPtrConstant(5);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, IsIntPtrConstant(20));
}
{
TNode<IntPtrT> a = m.IntPtrConstant(100);
TNode<IntPtrT> b = m.IntPtrConstant(5);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, IsIntPtrConstant(20));
}
// x / 2^CONST => x >> CONST
{
TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
TNode<IntPtrT> b = m.IntPtrConstant(1 << 3);
TNode<IntPtrT> div = m.IntPtrDiv(a, b);
EXPECT_THAT(div, IsWordSar(Matcher<Node*>(a), IsIntPtrConstant(3)));
}
}
TARGET_TEST_F(CodeAssemblerTest, WordShl) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<WordT> add = m.WordShl(a, 10);
EXPECT_THAT(add, IsWordShl(a, IsIntPtrConstant(10)));
}
// x << 0 => x
{
Node* a = m.Parameter(0);
TNode<WordT> add = m.WordShl(a, 0);
EXPECT_THAT(add, a);
}
// CONST_a << CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(1024);
TNode<WordT> shl = m.WordShl(a, 2);
EXPECT_THAT(shl, IsIntPtrConstant(4096));
}
}
TARGET_TEST_F(CodeAssemblerTest, WordShr) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<WordT> shr = m.WordShr(a, 10);
EXPECT_THAT(shr, IsWordShr(a, IsIntPtrConstant(10)));
}
// x >> 0 => x
{
Node* a = m.Parameter(0);
TNode<WordT> shr = m.WordShr(a, 0);
EXPECT_THAT(shr, a);
}
// +CONST_a >> CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(4096);
TNode<IntPtrT> shr = m.WordShr(a, 2);
EXPECT_THAT(shr, IsIntPtrConstant(1024));
}
// -CONST_a >> CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(-1234);
TNode<IntPtrT> shr = m.WordShr(a, 2);
EXPECT_THAT(shr, IsIntPtrConstant(static_cast<uintptr_t>(-1234) >> 2));
}
}
TARGET_TEST_F(CodeAssemblerTest, WordSar) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<WordT> sar = m.WordSar(a, m.IntPtrConstant(10));
EXPECT_THAT(sar, IsWordSar(a, IsIntPtrConstant(10)));
}
// x >>> 0 => x
{
Node* a = m.Parameter(0);
TNode<WordT> sar = m.WordSar(a, m.IntPtrConstant(0));
EXPECT_THAT(sar, a);
}
// +CONST_a >>> CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(4096);
TNode<IntPtrT> sar = m.WordSar(a, m.IntPtrConstant(2));
EXPECT_THAT(sar, IsIntPtrConstant(1024));
}
// -CONST_a >>> CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(-1234);
TNode<IntPtrT> sar = m.WordSar(a, m.IntPtrConstant(2));
EXPECT_THAT(sar, IsIntPtrConstant(static_cast<intptr_t>(-1234) >> 2));
}
}
TARGET_TEST_F(CodeAssemblerTest, WordOr) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<WordT> z = m.WordOr(a, m.IntPtrConstant(8));
EXPECT_THAT(z, IsWordOr(a, IsIntPtrConstant(8)));
}
// x | 0 => x
{
Node* a = m.Parameter(0);
TNode<WordT> z = m.WordOr(a, m.IntPtrConstant(0));
EXPECT_THAT(z, a);
}
// 0 | x => x
{
Node* a = m.Parameter(0);
TNode<WordT> z = m.WordOr(m.IntPtrConstant(0), a);
EXPECT_THAT(z, a);
}
// CONST_a | CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(3);
TNode<WordT> b = m.WordOr(a, m.IntPtrConstant(7));
EXPECT_THAT(b, IsIntPtrConstant(7));
}
}
TARGET_TEST_F(CodeAssemblerTest, WordAnd) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<WordT> z = m.WordAnd(a, m.IntPtrConstant(8));
EXPECT_THAT(z, IsWordAnd(a, IsIntPtrConstant(8)));
}
// CONST_a & CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(3);
TNode<IntPtrT> b = m.WordAnd(a, m.IntPtrConstant(7));
EXPECT_THAT(b, IsIntPtrConstant(3));
}
}
TARGET_TEST_F(CodeAssemblerTest, WordXor) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
{
Node* a = m.Parameter(0);
TNode<WordT> z = m.WordXor(a, m.IntPtrConstant(8));
EXPECT_THAT(z, IsWordXor(a, IsIntPtrConstant(8)));
}
// CONST_a ^ CONST_b => CONST_c
{
TNode<IntPtrT> a = m.IntPtrConstant(3);
TNode<WordT> b = m.WordXor(a, m.IntPtrConstant(7));
EXPECT_THAT(b, IsIntPtrConstant(4));
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
// Copyright 2017 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.
#ifndef V8_UNITTESTS_COMPILER_CODE_ASSEMBLER_UNITTEST_H_
#define V8_UNITTESTS_COMPILER_CODE_ASSEMBLER_UNITTEST_H_
#include "src/compiler/code-assembler.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock-support.h"
namespace v8 {
namespace internal {
namespace compiler {
class CodeAssemblerTest : public TestWithIsolateAndZone {
public:
CodeAssemblerTest() = default;
~CodeAssemblerTest() override = default;
};
class CodeAssemblerTestState : public CodeAssemblerState {
public:
explicit CodeAssemblerTestState(CodeAssemblerTest* test);
};
class CodeAssemblerForTest : public CodeAssembler {
public:
explicit CodeAssemblerForTest(CodeAssemblerTestState* state)
: CodeAssembler(state) {}
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_UNITTESTS_COMPILER_CODE_ASSEMBLER_UNITTEST_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment