Skip to content

Commit

Permalink
Version 2.13.0-90.0.dev
Browse files Browse the repository at this point in the history
Merge commit '1f828c7cb2b005fe3a278a49433738946f3550fe' into 'dev'
  • Loading branch information
Dart CI committed Mar 1, 2021
2 parents 60b27ec + 1f828c7 commit f7b05f6
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 7 deletions.
14 changes: 8 additions & 6 deletions runtime/vm/compiler/backend/il.cc
Expand Up @@ -3389,16 +3389,18 @@ Definition* IntConverterInstr::Canonicalize(FlowGraph* flow_graph) {

IntConverterInstr* box_defn = value()->definition()->AsIntConverter();
if ((box_defn != NULL) && (box_defn->representation() == from())) {
// Do not erase truncating conversions from 64-bit value to 32-bit values
// because such conversions erase upper 32 bits.
if ((box_defn->from() == kUnboxedInt64) && box_defn->is_truncating()) {
// If the first convertion can erase bits (or deoptimize) we can't
// canonicalize it away.
auto src_defn = box_defn->value()->definition();
if ((box_defn->from() == kUnboxedInt64) &&
!Range::Fits(src_defn->range(), box_defn->to())) {
return this;
}

// It's safe to discard any other conversions from and then back to the same
// integer type.
// Otherise it is safe to discard any other conversions from and then back
// to the same integer type.
if (box_defn->from() == to()) {
return box_defn->value()->definition();
return src_defn;
}

// Do not merge conversions where the first starts from Untagged or the
Expand Down
72 changes: 72 additions & 0 deletions runtime/vm/compiler/backend/il_test.cc
Expand Up @@ -7,7 +7,10 @@
#include <vector>

#include "platform/utils.h"
#include "vm/compiler/backend/block_builder.h"
#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/backend/il_test_helper.h"
#include "vm/compiler/backend/range_analysis.h"
#include "vm/unit_test.h"

namespace dart {
Expand Down Expand Up @@ -189,4 +192,73 @@ ISOLATE_UNIT_TEST_CASE(IRTest_InitializingStores) {
expected_stores_aot);
}

// Returns |true| if compiler canonicalizes away a chain of IntConverters going
// from |initial| representation to |intermediate| representation and then
// back to |initial| given that initial value has range [min_value, max_value].
bool TestIntConverterCanonicalizationRule(Thread* thread,
int64_t min_value,
int64_t max_value,
Representation initial,
Representation intermediate) {
using compiler::BlockBuilder;

CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);

FlowGraphBuilderHelper H;

// Add a variable into the scope which would provide static type for the
// parameter.
LocalVariable* v0_var =
new LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
String::Handle(Symbols::New(thread, "v0")),
AbstractType::ZoneHandle(Type::IntType()));
v0_var->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
H.flow_graph()->parsed_function().scope()->AddVariable(v0_var);

auto normal_entry = H.flow_graph()->graph_entry()->normal_entry();

Definition* v0;
ReturnInstr* ret;

{
BlockBuilder builder(H.flow_graph(), normal_entry);
v0 = builder.AddParameter(0, 0, /*with_frame=*/true, initial);
v0->set_range(Range(RangeBoundary::FromConstant(min_value),
RangeBoundary::FromConstant(max_value)));
auto conv1 = builder.AddDefinition(new IntConverterInstr(
initial, intermediate, new Value(v0), S.GetNextDeoptId()));
auto conv2 = builder.AddDefinition(new IntConverterInstr(
intermediate, initial, new Value(conv1), S.GetNextDeoptId()));
ret = builder.AddReturn(new Value(conv2));
}

H.FinishGraph();

H.flow_graph()->Canonicalize();
H.flow_graph()->Canonicalize();

return ret->value()->definition() == v0;
}

ISOLATE_UNIT_TEST_CASE(IL_IntConverterCanonicalization) {
EXPECT(TestIntConverterCanonicalizationRule(thread, kMinInt16, kMaxInt16,
kUnboxedInt64, kUnboxedInt32));
EXPECT(TestIntConverterCanonicalizationRule(thread, kMinInt32, kMaxInt32,
kUnboxedInt64, kUnboxedInt32));
EXPECT(!TestIntConverterCanonicalizationRule(
thread, kMinInt32, static_cast<int64_t>(kMaxInt32) + 1, kUnboxedInt64,
kUnboxedInt32));
EXPECT(TestIntConverterCanonicalizationRule(thread, 0, kMaxInt16,
kUnboxedInt64, kUnboxedUint32));
EXPECT(TestIntConverterCanonicalizationRule(thread, 0, kMaxInt32,
kUnboxedInt64, kUnboxedUint32));
EXPECT(TestIntConverterCanonicalizationRule(thread, 0, kMaxUint32,
kUnboxedInt64, kUnboxedUint32));
EXPECT(!TestIntConverterCanonicalizationRule(
thread, 0, static_cast<int64_t>(kMaxUint32) + 1, kUnboxedInt64,
kUnboxedUint32));
EXPECT(!TestIntConverterCanonicalizationRule(thread, -1, kMaxInt16,
kUnboxedInt64, kUnboxedUint32));
}

} // namespace dart
21 changes: 21 additions & 0 deletions runtime/vm/compiler/backend/range_analysis.h
Expand Up @@ -439,6 +439,27 @@ class Range : public ZoneAllocated {
!max().UpperBound().Overflowed(size);
}

// Returns true if this range fits without truncation into
// the given representation.
static bool Fits(Range* range, Representation rep) {
if (range == nullptr) return false;

switch (rep) {
case kUnboxedInt64:
return true;

case kUnboxedInt32:
return range->Fits(RangeBoundary::kRangeBoundaryInt32);

case kUnboxedUint32:
return range->IsWithin(0, kMaxUint32);

default:
break;
}
return false;
}

// Clamp this to be within size.
void Clamp(RangeBoundary::RangeSize size);

Expand Down
2 changes: 1 addition & 1 deletion tools/VERSION
Expand Up @@ -27,5 +27,5 @@ CHANNEL dev
MAJOR 2
MINOR 13
PATCH 0
PRERELEASE 89
PRERELEASE 90
PRERELEASE_PATCH 0

0 comments on commit f7b05f6

Please sign in to comment.