Re: Change in dart/sdk[master]: [vm/compiler] Refactoring binary operation and unary operation evalua...

6 views
Skip to first unread message

Vyacheslav Egorov

unread,
Oct 25, 2019, 1:49:46 PM10/25/19
to commit-bot@chromium.org (Gerrit), Aart Bik, Ben Konyi, Fizaa Luthra, Keerti Parthasarathy, Martin Kustermann, dart-vm-compil...@google.com, rev...@dartlang.org, vm-...@dartlang.org
Thank you for doing this refactoring! 

On Fri, 25 Oct 2019 at 00.31, commi...@chromium.org (Gerrit) <noreply-gerritcoderevie...@google.com> wrote:

commi...@chromium.org submitted this change.

View Change

Approvals: Aart Bik: Looks good to me, approved Fizaa Luthra: Commit
[vm/compiler] Refactoring binary operation and unary operation evaluation logic

Rationale:
1) Centralize constant expression evaluation logic.
2) Avoid code duplication with constant folding in unoptimized code.

Bug:
https://github.com/dart-lang/sdk/issues/36409


Change-Id: I0ee4916e9e731df3dd8eb30dd5f182bc40e1dfa3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122172
Reviewed-by: Aart Bik <ajc...@google.com>
Commit-Queue: Fizaa Luthra <fizaa...@google.com>

---
M runtime/vm/compiler/backend/constant_propagator.cc
A runtime/vm/compiler/backend/evaluator.cc
A runtime/vm/compiler/backend/evaluator.h
M runtime/vm/compiler/backend/il.cc
M runtime/vm/compiler/backend/il.h
M runtime/vm/compiler/compiler_sources.gni
6 files changed, 325 insertions(+), 251 deletions(-)

diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 7447b7e..258c917 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -7,6 +7,7 @@
#include "vm/compiler/backend/constant_propagator.h"

#include "vm/bit_vector.h"
+#include "vm/compiler/backend/evaluator.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/backend/il.h"
#include "vm/compiler/backend/il_printer.h"
@@ -1007,18 +1008,15 @@
const Object& left = binary_op->left()->definition()->constant_value();
const Object& right = binary_op->right()->definition()->constant_value();
if (IsConstant(left) && IsConstant(right)) {
- if (left.IsInteger() && right.IsInteger()) {
- const Integer& left_int = Integer::Cast(left);
- const Integer& right_int = Integer::Cast(right);
- const Integer& result =
- Integer::Handle(Z, binary_op->Evaluate(left_int, right_int));
- if (!result.IsNull()) {
- SetValue(binary_op, Integer::ZoneHandle(Z, result.raw()));
- return;
- }
+ const Integer& result = Integer::Handle(
+ Z, Evaluator::BinaryIntegerEvaluate(left, right, binary_op->op_kind(),
+ binary_op->is_truncating(),
+ binary_op->representation(), T));
+ if (!result.IsNull()) {
+ SetValue(binary_op, Integer::ZoneHandle(Z, result.raw()));
+ return;
}
}
-
SetValue(binary_op, non_constant_);
}

@@ -1077,9 +1075,10 @@

void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) {
const Object& value = unary_op->value()->definition()->constant_value();
- if (IsConstant(value) && value.IsInteger()) {
- const Integer& value_int = Integer::Cast(value);
- const Integer& result = Integer::Handle(Z, unary_op->Evaluate(value_int));
+ if (IsConstant(value)) {
+ const Integer& result = Integer::Handle(
+ Z, Evaluator::UnaryIntegerEvaluate(value, unary_op->op_kind(),
+ unary_op->representation(), T));
if (!result.IsNull()) {
SetValue(unary_op, Integer::ZoneHandle(Z, result.raw()));
return;
@@ -1210,36 +1209,19 @@
void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) {
const Object& left = instr->left()->definition()->constant_value();
const Object& right = instr->right()->definition()->constant_value();
- if (IsNonConstant(left) || IsNonConstant(right)) {
- SetValue(instr, non_constant_);
- } else if (left.IsInteger() && right.IsInteger()) {
- SetValue(instr, non_constant_);
- } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) {
- const double left_val = ToDouble(left);
- const double right_val = ToDouble(right);
- double result_val = 0.0;
- switch (instr->op_kind()) {
- case Token::kADD:
- result_val = left_val + right_val;
- break;
- case Token::kSUB:
- result_val = left_val - right_val;
- break;
- case Token::kMUL:
- result_val = left_val * right_val;
- break;
- case Token::kDIV:
- result_val = left_val / right_val;
- break;
- default:
- UNREACHABLE();
+ if (IsConstant(left) && IsConstant(right)) {
+ const bool both_are_integers = left.IsInteger() && right.IsInteger();
+ if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right) &&
+ !both_are_integers) {
+ const double result_val = Evaluator::EvaluateDoubleOp(
+ ToDouble(left), ToDouble(right), instr->op_kind());
+ const Double& result =
+ Double::ZoneHandle(Double::NewCanonical(result_val));
+ SetValue(instr, result);
+ return;
}
- const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val));
- SetValue(instr, result);
- } else if (IsConstant(left) && IsConstant(right)) {
- // Both values known, but no rule to evaluate this further.
- SetValue(instr, non_constant_);
}
+ SetValue(instr, non_constant_);
}

void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) {
diff --git a/runtime/vm/compiler/backend/evaluator.cc b/runtime/vm/compiler/backend/evaluator.cc
new file mode 100644
index 0000000..f6adab3
--- /dev/null
+++ b/runtime/vm/compiler/backend/evaluator.cc
@@ -0,0 +1,241 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/compiler/backend/evaluator.h"
+
+namespace dart {
+
+static bool IsRepresentable(const Integer& value, Representation rep) {
+ switch (rep) {
+ case kTagged: // Smi case.
+ return value.IsSmi();
+
+ case kUnboxedInt32:
+ if (value.IsSmi() || value.IsMint()) {
+ return Utils::IsInt(32, value.AsInt64Value());
+ }
+ return false;
+
+ case kUnboxedInt64:
+ return value.IsSmi() || value.IsMint();
+
+ case kUnboxedUint32:
+ if (value.IsSmi() || value.IsMint()) {
+ return Utils::IsUint(32, value.AsInt64Value());
+ }
+ return false;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+static RawInteger* BinaryIntegerEvaluateRaw(const Integer& left,

+ const Integer& right,
+ Token::Kind token_kind) {
+ switch (token_kind) {
+ case Token::kTRUNCDIV:
+ FALL_THROUGH;
+ case Token::kMOD:
+ // Check right value for zero.
+ if (right.AsInt64Value() == 0) {
+ break; // Will throw.
+ }
+ FALL_THROUGH;
+ case Token::kADD:
+ FALL_THROUGH;
+ case Token::kSUB:
+ FALL_THROUGH;
+ case Token::kMUL:
+ return left.ArithmeticOp(token_kind, right, Heap::kOld);
+ case Token::kSHL:
+ FALL_THROUGH;
+ case Token::kSHR:
+ if (right.AsInt64Value() >= 0) {
+ return left.ShiftOp(token_kind, right, Heap::kOld);
+ }
+ break;
+ case Token::kBIT_AND:
+ FALL_THROUGH;
+ case Token::kBIT_OR:
+ FALL_THROUGH;
+ case Token::kBIT_XOR:
+ return left.BitOp(token_kind, right, Heap::kOld);
+ case Token::kDIV:
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return Integer::null();
+}
+
+static RawInteger* UnaryIntegerEvaluateRaw(const Integer& value,
+ Token::Kind token_kind,
+ Zone* zone) {
+ switch (token_kind) {
+ case Token::kNEGATE:
+ return value.ArithmeticOp(Token::kMUL, Smi::Handle(zone, Smi::New(-1)),
+ Heap::kOld);
+ case Token::kBIT_NOT:
+ if (value.IsSmi()) {
+ return Integer::New(~Smi::Cast(value).Value(), Heap::kOld);
+ } else if (value.IsMint()) {
+ return Integer::New(~Mint::Cast(value).value(), Heap::kOld);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return Integer::null();
+}
+
+int64_t Evaluator::TruncateTo(int64_t v, Representation r) {
+ switch (r) {
+ case kTagged: {
+ // Smi occupies word minus kSmiTagShift bits.
+ const intptr_t kTruncateBits =
+ (kBitsPerInt64 - kBitsPerWord) + kSmiTagShift;
+ return Utils::ShiftLeftWithTruncation(v, kTruncateBits) >> kTruncateBits;
+ }
+ case kUnboxedInt32:
+ return Utils::ShiftLeftWithTruncation(v, kBitsPerInt32) >> kBitsPerInt32;
+ case kUnboxedUint32:
+ return v & kMaxUint32;
+ case kUnboxedInt64:
+ return v;
+ default:
+ UNREACHABLE();
+ }
+}
+
+RawInteger* Evaluator::BinaryIntegerEvaluate(const Object& left,
+ const Object& right,
+ Token::Kind token_kind,
+ bool is_truncating,
+ Representation representation,
+ Thread* thread) {
+ if (!left.IsInteger() || !right.IsInteger()) {
+ return Integer::null();
+ }
+ Zone* zone = thread->zone();
+ const Integer& left_int = Integer::Cast(left);
+ const Integer& right_int = Integer::Cast(right);
+ Integer& result = Integer::Handle(
+ zone, BinaryIntegerEvaluateRaw(left_int, right_int, token_kind));
+
+ if (!result.IsNull()) {
+ if (is_truncating) {
+ const int64_t truncated =
+ TruncateTo(result.AsTruncatedInt64Value(), representation);
+ result = Integer::New(truncated, Heap::kOld);
+ ASSERT(IsRepresentable(result, representation));
+ } else if (!IsRepresentable(result, representation)) {
+ // If this operation is not truncating it would deoptimize on overflow.
+ // Check that we match this behavior and don't produce a value that is
+ // larger than something this operation can produce. We could have
+ // specialized instructions that use this value under this assumption.
+ return Integer::null();
+ }
+ const char* error_str = NULL;
+ result ^= result.CheckAndCanonicalize(thread, &error_str);
+ if (error_str != NULL) {
+ FATAL1("Failed to canonicalize: %s", error_str);
+ }
+ }
+
+ return result.raw();
+}
+
+RawInteger* Evaluator::UnaryIntegerEvaluate(const Object& value,
+ Token::Kind token_kind,
+ Representation representation,
+ Thread* thread) {
+ if (!value.IsInteger()) {
+ return Integer::null();
+ }
+ Zone* zone = thread->zone();
+ const Integer& value_int = Integer::Cast(value);
+ Integer& result = Integer::Handle(
+ zone, UnaryIntegerEvaluateRaw(value_int, token_kind, zone));
+
+ if (!result.IsNull()) {
+ if (!IsRepresentable(result, representation)) {
+ // If this operation is not truncating it would deoptimize on overflow.
+ // Check that we match this behavior and don't produce a value that is
+ // larger than something this operation can produce. We could have
+ // specialized instructions that use this value under this assumption.
+ return Integer::null();
+ }
+
+ const char* error_str = NULL;
+ result ^= result.CheckAndCanonicalize(thread, &error_str);
+ if (error_str != NULL) {
+ FATAL1("Failed to canonicalize: %s", error_str);
+ }
+ }
+
+ return result.raw();
+}
+
+double Evaluator::EvaluateDoubleOp(const double left,
+ const double right,
+ Token::Kind token_kind) {
+ switch (token_kind) {
+ case Token::kADD:
+ return left + right;
+ case Token::kSUB:
+ return left - right;
+ case Token::kMUL:
+ return left * right;
+ case Token::kDIV:
+ return left / right;
+ default:
+ UNREACHABLE();
+ }
+}
+
+bool Evaluator::ToIntegerConstant(Value* value, int64_t* result) {
+ if (!value->BindsToConstant()) {
+ UnboxInstr* unbox = value->definition()->AsUnbox();
+ if (unbox != nullptr) {
+ switch (unbox->representation()) {
+ case kUnboxedDouble:
+ case kUnboxedInt64:
+ return ToIntegerConstant(unbox->value(), result);
+ case kUnboxedUint32:
+ if (ToIntegerConstant(unbox->value(), result)) {
+ *result = Evaluator::TruncateTo(*result, kUnboxedUint32);
+ return true;
+ }
+ break;
+ // No need to handle Unbox<Int32>(Constant(C)) because it gets
+ // canonicalized to UnboxedConstant<Int32>(C).
+ case kUnboxedInt32:
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+ const Object& constant = value->BoundConstant();
+ if (constant.IsDouble()) {
+ const Double& double_constant = Double::Cast(constant);
+ *result = Utils::SafeDoubleToInt<int64_t>(double_constant.value());
+ return (static_cast<double>(*result) == double_constant.value());
+ } else if (constant.IsSmi()) {
+ *result = Smi::Cast(constant).Value();
+ return true;
+ } else if (constant.IsMint()) {
+ *result = Mint::Cast(constant).value();
+ return true;
+ }
+ return false;
+}
+
+} // namespace dart
+
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/backend/evaluator.h b/runtime/vm/compiler/backend/evaluator.h
new file mode 100644
index 0000000..8c8e814
--- /dev/null
+++ b/runtime/vm/compiler/backend/evaluator.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_COMPILER_BACKEND_EVALUATOR_H_
+#define RUNTIME_VM_COMPILER_BACKEND_EVALUATOR_H_
+
+#include "vm/allocation.h"
+#include "vm/compiler/backend/flow_graph.h"
+#include "vm/compiler/backend/il.h"
+#include "vm/compiler/backend/locations.h"
+
+namespace dart {
+
+// Namespace for static helper methods that evaluate constant expressions.
+class Evaluator : public AllStatic {
+ public:
+ // Truncates the given int64 value based on the representation.
+ static int64_t TruncateTo(int64_t v, Representation r);
+
+ // Evaluates a binary integer operation and returns a pointer to a
+ // canonicalized RawInteger.
+ static RawInteger* BinaryIntegerEvaluate(const Object& left,
+ const Object& right,
+ Token::Kind token_kind,
+ bool is_truncating,
+ Representation representation,
+ Thread* thread);
+
+ // Evaluates a unary integer operation and returns a pointer to a
+ // canonicalized RawInteger.
+ static RawInteger* UnaryIntegerEvaluate(const Object& value,
+ Token::Kind token_kind,
+ Representation representation,
+ Thread* thread);
+
+ // Evaluates a binary double operation and returns the result.
+ static double EvaluateDoubleOp(const double left,
+ const double right,
+ Token::Kind token_kind);
+
+ // Returns whether the value is an int64, and returns the int64 value
+ // through the result parameter.
+ static bool ToIntegerConstant(Value* value, int64_t* result);
+};
+
+} // namespace dart
+
+#endif // RUNTIME_VM_COMPILER_BACKEND_EVALUATOR_H_
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 1ee311b..7f7d392 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -10,6 +10,7 @@
#include "vm/bootstrap.h"
#include "vm/compiler/backend/code_statistics.h"
#include "vm/compiler/backend/constant_propagator.h"
+#include "vm/compiler/backend/evaluator.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/backend/linearscan.h"
#include "vm/compiler/backend/locations.h"
@@ -2077,73 +2078,11 @@

(64 - RepresentationBits(r)));
}

-static int64_t TruncateTo(int64_t v, Representation r) {
- switch (r) {
- case kTagged: {
- // Smi occupies word minus kSmiTagShift bits.
- const intptr_t kTruncateBits =
- (kBitsPerInt64 - kBitsPerWord) + kSmiTagShift;
- return Utils::ShiftLeftWithTruncation(v, kTruncateBits) >> kTruncateBits;
- }
- case kUnboxedInt32:
- return Utils::ShiftLeftWithTruncation(v, kBitsPerInt32) >> kBitsPerInt32;
- case kUnboxedUint32:
- return v & kMaxUint32;
- case kUnboxedInt64:
- return v;
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-static bool ToIntegerConstant(Value* value, int64_t* result) {
- if (!value->BindsToConstant()) {
- UnboxInstr* unbox = value->definition()->AsUnbox();
- if (unbox != NULL) {
- switch (unbox->representation()) {
- case kUnboxedDouble:
- case kUnboxedInt64:
- return ToIntegerConstant(unbox->value(), result);
-
- case kUnboxedUint32:
- if (ToIntegerConstant(unbox->value(), result)) {
- *result = TruncateTo(*result, kUnboxedUint32);
- return true;
- }
- break;
-
- // No need to handle Unbox<Int32>(Constant(C)) because it gets
- // canonicalized to UnboxedConstant<Int32>(C).
- case kUnboxedInt32:
- default:
- break;
- }
- }
- return false;
- }
-
- const Object& constant = value->BoundConstant();
- if (constant.IsDouble()) {
- const Double& double_constant = Double::Cast(constant);
- *result = Utils::SafeDoubleToInt<int64_t>(double_constant.value());
- return (static_cast<double>(*result) == double_constant.value());
- } else if (constant.IsSmi()) {
- *result = Smi::Cast(constant).Value();
- return true;
- } else if (constant.IsMint()) {
- *result = Mint::Cast(constant).value();
- return true;
- }
-
- return false;
-}
-
static Definition* CanonicalizeCommutativeDoubleArithmetic(Token::Kind op,
Value* left,
Value* right) {
int64_t left_value;
- if (!ToIntegerConstant(left, &left_value)) {
+ if (!Evaluator::ToIntegerConstant(left, &left_value)) {
return NULL;
}

@@ -2341,142 +2280,6 @@

return op;
}

-static bool IsRepresentable(const Integer& value, Representation rep) {
- switch (rep) {
- case kTagged: // Smi case.
- return value.IsSmi();
-
- case kUnboxedInt32:
- if (value.IsSmi() || value.IsMint()) {
- return Utils::IsInt(32, value.AsInt64Value());
- }
- return false;
-
- case kUnboxedInt64:
- return value.IsSmi() || value.IsMint();
-
- case kUnboxedUint32:
- if (value.IsSmi() || value.IsMint()) {
- return Utils::IsUint(32, value.AsInt64Value());
- }
- return false;
-
- default:
- UNREACHABLE();
- }
-
- return false;
-}
-
-RawInteger* UnaryIntegerOpInstr::Evaluate(const Integer& value) const {
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- Integer& result = Integer::Handle(zone);
-
- switch (op_kind()) {
- case Token::kNEGATE:
- result = value.ArithmeticOp(Token::kMUL, Smi::Handle(zone, Smi::New(-1)),
- Heap::kOld);
- break;
-
- case Token::kBIT_NOT:
- if (value.IsSmi()) {
- result = Integer::New(~Smi::Cast(value).Value(), Heap::kOld);
- } else if (value.IsMint()) {
- result = Integer::New(~Mint::Cast(value).value(), Heap::kOld);
- }
- break;
-
- default:
- UNREACHABLE();
- }
-
- if (!result.IsNull()) {
- if (!IsRepresentable(result, representation())) {
- // If this operation is not truncating it would deoptimize on overflow.
- // Check that we match this behavior and don't produce a value that is
- // larger than something this operation can produce. We could have
- // specialized instructions that use this value under this assumption.
- return Integer::null();
- }
-
- const char* error_str = NULL;
- result ^= result.CheckAndCanonicalize(thread, &error_str);
- if (error_str != NULL) {
- FATAL1("Failed to canonicalize: %s", error_str);
- }
- }
-
- return result.raw();
-}
-
-RawInteger* BinaryIntegerOpInstr::Evaluate(const Integer& left,
- const Integer& right) const {
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- Integer& result = Integer::Handle(zone);
-
- switch (op_kind()) {
- case Token::kTRUNCDIV:
- FALL_THROUGH;
- case Token::kMOD:
- // Check right value for zero.
- if (right.AsInt64Value() == 0) {
- break; // Will throw.
- }
- FALL_THROUGH;
- case Token::kADD:
- FALL_THROUGH;
- case Token::kSUB:
- FALL_THROUGH;
- case Token::kMUL: {
- result = left.ArithmeticOp(op_kind(), right, Heap::kOld);
- break;
- }
- case Token::kSHL:
- FALL_THROUGH;
- case Token::kSHR:
- if (right.AsInt64Value() >= 0) {
- result = left.ShiftOp(op_kind(), right, Heap::kOld);
- }
- break;
- case Token::kBIT_AND:
- FALL_THROUGH;
- case Token::kBIT_OR:
- FALL_THROUGH;
- case Token::kBIT_XOR: {
- result = left.BitOp(op_kind(), right, Heap::kOld);
- break;
- }
- case Token::kDIV:
- break;
- default:
- UNREACHABLE();
- }
-
- if (!result.IsNull()) {
- if (is_truncating()) {
- const int64_t truncated =
- TruncateTo(result.AsTruncatedInt64Value(), representation());
- result = Integer::New(truncated, Heap::kOld);
- ASSERT(IsRepresentable(result, representation()));
- } else if (!IsRepresentable(result, representation())) {
- // If this operation is not truncating it would deoptimize on overflow.
- // Check that we match this behavior and don't produce a value that is
- // larger than something this operation can produce. We could have
- // specialized instructions that use this value under this assumption.
- return Integer::null();
- }
- const char* error_str = NULL;
- result ^= result.CheckAndCanonicalize(thread, &error_str);
- if (error_str != NULL) {
- FATAL1("Failed to canonicalize: %s", error_str);
- }
- }
-
- return result.raw();
-}
-
Definition* BinaryIntegerOpInstr::CreateConstantResult(FlowGraph* flow_graph,
const Integer& result) {
Definition* result_defn = flow_graph->GetConstant(result);
@@ -2567,11 +2370,12 @@
// If both operands are constants evaluate this expression. Might
// occur due to load forwarding after constant propagation pass
// have already been run.
- if (left()->BindsToConstant() && left()->BoundConstant().IsInteger() &&
- right()->BindsToConstant() && right()->BoundConstant().IsInteger()) {
- const Integer& result =
- Integer::Handle(Evaluate(Integer::Cast(left()->BoundConstant()),
- Integer::Cast(right()->BoundConstant())));
+
+ if (left()->BindsToConstant() && right()->BindsToConstant()) {
+ const Integer& result = Integer::Handle(Evaluator::BinaryIntegerEvaluate(
+ left()->BoundConstant(), right()->BoundConstant(), op_kind(),
+ is_truncating(), representation(), Thread::Current()));
+
if (!result.IsNull()) {
return CreateConstantResult(flow_graph, result);
}
@@ -2586,7 +2390,7 @@
}

int64_t rhs;
- if (!ToIntegerConstant(right(), &rhs)) {
+ if (!Evaluator::ToIntegerConstant(right(), &rhs)) {
return this;
}

@@ -2598,7 +2402,7 @@
case Token::kBIT_AND:
case Token::kBIT_OR:
case Token::kBIT_XOR:
- rhs = TruncateTo(rhs, representation());
+ rhs = Evaluator::TruncateTo(rhs, representation());
break;
default:
break;
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index e716685..65a15cf 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -6633,8 +6633,6 @@

PRINT_OPERANDS_TO_SUPPORT

- RawInteger* Evaluate(const Integer& value) const;
-
DEFINE_INSTRUCTION_TYPE_CHECK(UnaryIntegerOp)

private:
@@ -6861,8 +6859,6 @@
// a power of two.
bool RightIsPowerOfTwoConstant() const;

- RawInteger* Evaluate(const Integer& left, const Integer& right) const;
-
virtual Definition* Canonicalize(FlowGraph* flow_graph);

virtual bool AttributesEqual(Instruction* other) const;
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index a722851..d1a5b77 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -47,6 +47,8 @@
"backend/compile_type.h",
"backend/constant_propagator.cc",
"backend/constant_propagator.h",
+ "backend/evaluator.cc",
+ "backend/evaluator.h",
"backend/flow_graph.cc",
"backend/flow_graph.h",
"backend/flow_graph_checker.cc",

To view, visit change 122172. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: sdk
Gerrit-Branch: master
Gerrit-Change-Id: I0ee4916e9e731df3dd8eb30dd5f182bc40e1dfa3
Gerrit-Change-Number: 122172
Gerrit-PatchSet: 11
Gerrit-Owner: Fizaa Luthra <fizaa...@google.com>
Gerrit-Reviewer: Aart Bik <ajc...@google.com>
Gerrit-Reviewer: Ben Konyi <bko...@google.com>
Gerrit-Reviewer: Fizaa Luthra <fizaa...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Vyacheslav Egorov <veg...@google.com>
Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
Gerrit-MessageType: merged
--

// Vyacheslav Egorov
Reply all
Reply to author
Forward
0 new messages