Skip to content

Commit 2bcb736

Browse files
alexmarkovCommit Queue
authored andcommitted
[vm/compiler] Remove speculative int32 range checks
UnboxedInt32 representation is no longer speculative, so all speculative int32 range checks are removed from Unbox and IntConverter instructions. Unbox and IntConverter instructions are now always truncating. IntConverter cannot deoptimize. TEST=ci Change-Id: Ie9a83e055e8b8372859b0721ac6fbcf73da39ab8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392740 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent bdacb7d commit 2bcb736

File tree

17 files changed

+88
-483
lines changed

17 files changed

+88
-483
lines changed

runtime/vm/compiler/aot/aot_call_specializer.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ Definition* AotCallSpecializer::TryOptimizeDivisionOperation(
406406
Smi::ZoneHandle(Z, Smi::New(value)), kUnboxedInt32);
407407
InsertBefore(instr, const_def, /*env=*/nullptr, FlowGraph::kValue);
408408
return new (Z) IntConverterInstr(kUnboxedInt32, kUnboxedInt64,
409-
new (Z) Value(const_def), DeoptId::kNone);
409+
new (Z) Value(const_def));
410410
#else
411411
return new (Z) UnboxedConstantInstr(Smi::ZoneHandle(Z, Smi::New(value)),
412412
kUnboxedInt64);

runtime/vm/compiler/backend/block_builder.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,9 @@ class BlockBuilder : public ValueObject {
109109
: Boxing::NativeRepresentation(rep);
110110
Definition* unboxed_value = AddDefinition(
111111
UnboxInstr::Create(unbox_rep, value, DeoptId::kNone, value_mode));
112-
if (rep != unbox_rep && unboxed_value->IsUnboxInteger()) {
113-
ASSERT(RepresentationUtils::ValueSize(rep) <
114-
RepresentationUtils::ValueSize(unbox_rep));
115-
// Mark unboxing of small unboxed integer representations as truncating.
116-
unboxed_value->AsUnboxInteger()->mark_truncating();
117-
}
112+
ASSERT((rep == unbox_rep) || !unboxed_value->IsUnboxInteger() ||
113+
(RepresentationUtils::ValueSize(rep) <
114+
RepresentationUtils::ValueSize(unbox_rep)));
118115
if (value_mode == UnboxInstr::ValueMode::kHasValidType) {
119116
// The type of |value| has already been checked and it is safe to
120117
// adjust reaching type. This is done manually because there is no type

runtime/vm/compiler/backend/constant_propagator.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,9 +1509,8 @@ void ConstantPropagator::VisitUnbox(UnboxInstr* instr) {
15091509
SetValue(instr, non_constant_);
15101510
return;
15111511
}
1512-
if (unbox_int->is_truncating() &&
1513-
((unbox_int->representation() == kUnboxedInt32) ||
1514-
(unbox_int->representation() == kUnboxedUint32))) {
1512+
if ((unbox_int->representation() == kUnboxedInt32) ||
1513+
(unbox_int->representation() == kUnboxedUint32)) {
15151514
const int64_t result_val = Evaluator::TruncateTo(
15161515
Integer::Cast(value).Value(), unbox_int->representation());
15171516
value = Integer::NewCanonical(result_val);

runtime/vm/compiler/backend/flow_graph.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,8 +1974,7 @@ void FlowGraph::InsertConversion(Representation from,
19741974

19751975
Definition* converted = nullptr;
19761976
if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) {
1977-
converted = new (Z)
1978-
IntConverterInstr(from, to, use->CopyWithType(), DeoptId::kNone);
1977+
converted = new (Z) IntConverterInstr(from, to, use->CopyWithType());
19791978
} else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) {
19801979
converted = new Int32ToDoubleInstr(use->CopyWithType());
19811980
} else if ((from == kUnboxedInt64) && (to == kUnboxedDouble) &&

runtime/vm/compiler/backend/il.cc

Lines changed: 17 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,33 +2027,6 @@ void Instruction::Goto(JoinEntryInstr* entry) {
20272027
LinkTo(new GotoInstr(entry, CompilerState::Current().GetNextDeoptId()));
20282028
}
20292029

2030-
bool IntConverterInstr::ComputeCanDeoptimize() const {
2031-
return (to() == kUnboxedInt32) && !is_truncating() &&
2032-
!RangeUtils::Fits(value()->definition()->range(),
2033-
RangeBoundary::kRangeBoundaryInt32);
2034-
}
2035-
2036-
bool UnboxIntegerInstr::ComputeCanDeoptimize() const {
2037-
if (value_mode() == ValueMode::kHasValidType) {
2038-
return false;
2039-
}
2040-
if (!value()->Type()->IsInt()) {
2041-
return true;
2042-
}
2043-
if (representation() == kUnboxedInt64 || is_truncating()) {
2044-
return false;
2045-
}
2046-
const intptr_t rep_bitsize =
2047-
RepresentationUtils::ValueSize(representation()) * kBitsPerByte;
2048-
if (value()->Type()->ToCid() == kSmiCid &&
2049-
compiler::target::kSmiBits <= rep_bitsize) {
2050-
return false;
2051-
}
2052-
return !RangeUtils::IsWithin(value()->definition()->range(),
2053-
RepresentationUtils::MinValue(representation()),
2054-
RepresentationUtils::MaxValue(representation()));
2055-
}
2056-
20572030
bool BinaryInt32OpInstr::ComputeCanDeoptimize() const {
20582031
switch (op_kind()) {
20592032
case Token::kBIT_AND:
@@ -3369,19 +3342,9 @@ Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
33693342
return box_defn->value()->definition();
33703343
} else {
33713344
// Only operate on explicit unboxed operands.
3372-
IntConverterInstr* converter = new IntConverterInstr(
3373-
from_representation, representation(),
3374-
box_defn->value()->CopyWithType(),
3375-
(representation() == kUnboxedInt32) ? GetDeoptId() : DeoptId::kNone);
3376-
// TODO(vegorov): marking resulting converter as truncating when
3377-
// unboxing can't deoptimize is a workaround for the missing
3378-
// deoptimization environment when we insert converter after
3379-
// EliminateEnvironments and there is a mismatch between predicates
3380-
// UnboxIntConverterInstr::CanDeoptimize and UnboxInt32::CanDeoptimize.
3381-
if ((representation() == kUnboxedInt32) &&
3382-
(is_truncating() || !CanDeoptimize())) {
3383-
converter->mark_truncating();
3384-
}
3345+
IntConverterInstr* converter =
3346+
new IntConverterInstr(from_representation, representation(),
3347+
box_defn->value()->CopyWithType());
33853348
flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
33863349
return converter;
33873350
}
@@ -3403,13 +3366,11 @@ Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
34033366
if (RepresentationUtils::IsRepresentable(representation(), intval)) {
34043367
return flow_graph->GetConstant(obj, representation());
34053368
}
3406-
if (is_truncating()) {
3407-
const int64_t result = Evaluator::TruncateTo(intval, representation());
3408-
return flow_graph->GetConstant(
3409-
Integer::ZoneHandle(flow_graph->zone(),
3410-
Integer::NewCanonical(result)),
3411-
representation());
3412-
}
3369+
const int64_t result = Evaluator::TruncateTo(intval, representation());
3370+
return flow_graph->GetConstant(
3371+
Integer::ZoneHandle(flow_graph->zone(),
3372+
Integer::NewCanonical(result)),
3373+
representation());
34133374
}
34143375
}
34153376

@@ -3426,11 +3387,10 @@ Definition* IntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
34263387
const int64_t value = Integer::Cast(constant->value()).Value();
34273388
const int64_t result =
34283389
Evaluator::TruncateTo(Evaluator::TruncateTo(value, from()), to());
3429-
if (is_truncating() || (value == result)) {
3430-
auto& box = Integer::Handle(Integer::New(result, Heap::kOld));
3431-
box ^= box.Canonicalize(flow_graph->thread());
3432-
return flow_graph->GetConstant(box, to());
3433-
}
3390+
return flow_graph->GetConstant(
3391+
Integer::ZoneHandle(flow_graph->zone(),
3392+
Integer::NewCanonical(result)),
3393+
to());
34343394
}
34353395
}
34363396

@@ -3461,13 +3421,9 @@ Definition* IntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
34613421
return this;
34623422
}
34633423

3464-
IntConverterInstr* converter = new IntConverterInstr(
3465-
first_converter->from(), representation(),
3466-
first_converter->value()->CopyWithType(),
3467-
(to() == kUnboxedInt32) ? GetDeoptId() : DeoptId::kNone);
3468-
if ((representation() == kUnboxedInt32) && is_truncating()) {
3469-
converter->mark_truncating();
3470-
}
3424+
IntConverterInstr* converter =
3425+
new IntConverterInstr(first_converter->from(), representation(),
3426+
first_converter->value()->CopyWithType());
34713427
flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
34723428
return converter;
34733429
}
@@ -3479,9 +3435,7 @@ Definition* IntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
34793435
// and code path that unboxes Mint into Int32. We should just schedule
34803436
// these instructions close to each other instead of fusing them.
34813437
Definition* replacement =
3482-
new UnboxInt32Instr(is_truncating() ? UnboxInt32Instr::kTruncate
3483-
: UnboxInt32Instr::kNoTruncation,
3484-
unbox_defn->value()->CopyWithType(), GetDeoptId(),
3438+
new UnboxInt32Instr(unbox_defn->value()->CopyWithType(), GetDeoptId(),
34853439
unbox_defn->value_mode());
34863440
flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
34873441
return replacement;
@@ -4038,12 +3992,7 @@ UnboxInstr* UnboxInstr::Create(Representation to,
40383992
UnboxInstr::ValueMode value_mode) {
40393993
switch (to) {
40403994
case kUnboxedInt32:
4041-
// We must truncate if we can't deoptimize.
4042-
return new UnboxInt32Instr(
4043-
(value_mode == UnboxInstr::ValueMode::kCheckType)
4044-
? UnboxInt32Instr::kNoTruncation
4045-
: UnboxInt32Instr::kTruncate,
4046-
value, deopt_id, value_mode);
3995+
return new UnboxInt32Instr(value, deopt_id, value_mode);
40473996

40483997
case kUnboxedUint32:
40493998
return new UnboxUint32Instr(value, deopt_id, value_mode);

runtime/vm/compiler/backend/il.h

Lines changed: 14 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8616,24 +8616,10 @@ class UnboxIntegerInstr : public UnboxInstr {
86168616
enum TruncationMode { kTruncate, kNoTruncation };
86178617

86188618
UnboxIntegerInstr(Representation representation,
8619-
TruncationMode truncation_mode,
86208619
Value* value,
86218620
intptr_t deopt_id,
86228621
ValueMode value_mode)
8623-
: UnboxInstr(representation, value, deopt_id, value_mode),
8624-
is_truncating_(truncation_mode == kTruncate) {}
8625-
8626-
bool is_truncating() const { return is_truncating_; }
8627-
8628-
void mark_truncating() { is_truncating_ = true; }
8629-
8630-
virtual bool ComputeCanDeoptimize() const;
8631-
8632-
virtual bool AttributesEqual(const Instruction& other) const {
8633-
auto const other_unbox = other.AsUnboxInteger();
8634-
return UnboxInstr::AttributesEqual(other) &&
8635-
(other_unbox->is_truncating_ == is_truncating_);
8636-
}
8622+
: UnboxInstr(representation, value, deopt_id, value_mode) {}
86378623

86388624
virtual Definition* Canonicalize(FlowGraph* flow_graph);
86398625

@@ -8643,12 +8629,7 @@ class UnboxIntegerInstr : public UnboxInstr {
86438629

86448630
PRINT_OPERANDS_TO_SUPPORT
86458631

8646-
#define FIELD_LIST(F) F(bool, is_truncating_)
8647-
8648-
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(UnboxIntegerInstr,
8649-
UnboxInstr,
8650-
FIELD_LIST)
8651-
#undef FIELD_LIST
8632+
DECLARE_EMPTY_SERIALIZATION(UnboxIntegerInstr, UnboxInstr)
86528633

86538634
private:
86548635
DISALLOW_COPY_AND_ASSIGN(UnboxIntegerInstr);
@@ -8657,15 +8638,10 @@ class UnboxIntegerInstr : public UnboxInstr {
86578638
class UnboxInteger32Instr : public UnboxIntegerInstr {
86588639
public:
86598640
UnboxInteger32Instr(Representation representation,
8660-
TruncationMode truncation_mode,
86618641
Value* value,
86628642
intptr_t deopt_id,
86638643
ValueMode value_mode)
8664-
: UnboxIntegerInstr(representation,
8665-
truncation_mode,
8666-
value,
8667-
deopt_id,
8668-
value_mode) {}
8644+
: UnboxIntegerInstr(representation, value, deopt_id, value_mode) {}
86698645

86708646
DECLARE_INSTRUCTION_BACKEND()
86718647

@@ -8678,13 +8654,7 @@ class UnboxInteger32Instr : public UnboxIntegerInstr {
86788654
class UnboxUint32Instr : public UnboxInteger32Instr {
86798655
public:
86808656
UnboxUint32Instr(Value* value, intptr_t deopt_id, ValueMode value_mode)
8681-
: UnboxInteger32Instr(kUnboxedUint32,
8682-
kTruncate,
8683-
value,
8684-
deopt_id,
8685-
value_mode) {
8686-
ASSERT(is_truncating());
8687-
}
8657+
: UnboxInteger32Instr(kUnboxedUint32, value, deopt_id, value_mode) {}
86888658

86898659
DECLARE_INSTRUCTION_NO_BACKEND(UnboxUint32)
86908660

@@ -8696,15 +8666,8 @@ class UnboxUint32Instr : public UnboxInteger32Instr {
86968666

86978667
class UnboxInt32Instr : public UnboxInteger32Instr {
86988668
public:
8699-
UnboxInt32Instr(TruncationMode truncation_mode,
8700-
Value* value,
8701-
intptr_t deopt_id,
8702-
ValueMode value_mode)
8703-
: UnboxInteger32Instr(kUnboxedInt32,
8704-
truncation_mode,
8705-
value,
8706-
deopt_id,
8707-
value_mode) {}
8669+
UnboxInt32Instr(Value* value, intptr_t deopt_id, ValueMode value_mode)
8670+
: UnboxInteger32Instr(kUnboxedInt32, value, deopt_id, value_mode) {}
87088671

87098672
DECLARE_INSTRUCTION_NO_BACKEND(UnboxInt32)
87108673

@@ -8717,11 +8680,7 @@ class UnboxInt32Instr : public UnboxInteger32Instr {
87178680
class UnboxInt64Instr : public UnboxIntegerInstr {
87188681
public:
87198682
UnboxInt64Instr(Value* value, intptr_t deopt_id, ValueMode value_mode)
8720-
: UnboxIntegerInstr(kUnboxedInt64,
8721-
kNoTruncation,
8722-
value,
8723-
deopt_id,
8724-
value_mode) {}
8683+
: UnboxIntegerInstr(kUnboxedInt64, value, deopt_id, value_mode) {}
87258684

87268685
DECLARE_INSTRUCTION_NO_BACKEND(UnboxInt64)
87278686

@@ -10788,14 +10747,10 @@ class CheckConditionInstr : public Instruction {
1078810747

1078910748
class IntConverterInstr : public TemplateDefinition<1, NoThrow, Pure> {
1079010749
public:
10791-
IntConverterInstr(Representation from,
10792-
Representation to,
10793-
Value* value,
10794-
intptr_t deopt_id)
10795-
: TemplateDefinition(deopt_id),
10750+
IntConverterInstr(Representation from, Representation to, Value* value)
10751+
: TemplateDefinition(DeoptId::kNone),
1079610752
from_representation_(from),
10797-
to_representation_(to),
10798-
is_truncating_(to == kUnboxedUint32) {
10753+
to_representation_(to) {
1079910754
ASSERT(from != to);
1080010755
// Integer conversion doesn't currently handle non-native representations.
1080110756
ASSERT_EQUAL(Boxing::NativeRepresentation(from), from);
@@ -10816,13 +10771,10 @@ class IntConverterInstr : public TemplateDefinition<1, NoThrow, Pure> {
1081610771

1081710772
Representation from() const { return from_representation_; }
1081810773
Representation to() const { return to_representation_; }
10819-
bool is_truncating() const { return is_truncating_; }
10820-
10821-
void mark_truncating() { is_truncating_ = true; }
1082210774

1082310775
Definition* Canonicalize(FlowGraph* flow_graph);
1082410776

10825-
virtual bool ComputeCanDeoptimize() const;
10777+
virtual bool ComputeCanDeoptimize() const { return false; }
1082610778

1082710779
virtual Representation representation() const { return to(); }
1082810780

@@ -10834,8 +10786,7 @@ class IntConverterInstr : public TemplateDefinition<1, NoThrow, Pure> {
1083410786
virtual bool AttributesEqual(const Instruction& other) const {
1083510787
ASSERT(other.IsIntConverter());
1083610788
auto const converter = other.AsIntConverter();
10837-
return (converter->from() == from()) && (converter->to() == to()) &&
10838-
(converter->is_truncating() == is_truncating());
10789+
return (converter->from() == from()) && (converter->to() == to());
1083910790
}
1084010791

1084110792
virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
@@ -10850,15 +10801,13 @@ class IntConverterInstr : public TemplateDefinition<1, NoThrow, Pure> {
1085010801

1085110802
DECLARE_INSTRUCTION(IntConverter);
1085210803

10853-
DECLARE_ATTRIBUTES_NAMED(("from", "to", "is_truncating"),
10854-
(from(), to(), is_truncating()))
10804+
DECLARE_ATTRIBUTES_NAMED(("from", "to"), (from(), to()))
1085510805

1085610806
PRINT_OPERANDS_TO_SUPPORT
1085710807

1085810808
#define FIELD_LIST(F) \
1085910809
F(const Representation, from_representation_) \
10860-
F(const Representation, to_representation_) \
10861-
F(bool, is_truncating_)
10810+
F(const Representation, to_representation_)
1086210811

1086310812
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(IntConverterInstr,
1086410813
TemplateDefinition,

0 commit comments

Comments
 (0)