| Index: runtime/vm/intermediate_language.cc
|
| diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
|
| index 7a800233acfb0e9099b434284e344994f9850cc6..5fe6075347b6478378c6445a34a5b135baced3fa 100644
|
| --- a/runtime/vm/intermediate_language.cc
|
| +++ b/runtime/vm/intermediate_language.cc
|
| @@ -390,12 +390,12 @@ UnboxedConstantInstr::UnboxedConstantInstr(const Object& value,
|
|
|
|
|
| bool Value::BindsTo32BitMaskConstant() const {
|
| - if (!definition()->IsUnboxInteger() || !definition()->IsUnboxUint32()) {
|
| + if (!definition()->IsUnboxInt64() || !definition()->IsUnboxUint32()) {
|
| return false;
|
| }
|
| - // Two cases to consider: UnboxInteger and UnboxUint32.
|
| - if (definition()->IsUnboxInteger()) {
|
| - UnboxIntegerInstr* instr = definition()->AsUnboxInteger();
|
| + // Two cases to consider: UnboxInt64 and UnboxUint32.
|
| + if (definition()->IsUnboxInt64()) {
|
| + UnboxInt64Instr* instr = definition()->AsUnboxInt64();
|
| if (!instr->value()->BindsToConstant()) {
|
| return false;
|
| }
|
| @@ -1262,9 +1262,9 @@ bool BinaryIntegerOpInstr::RightIsPowerOfTwoConstant() const {
|
|
|
| static bool ToIntegerConstant(Value* value, int64_t* result) {
|
| if (!value->BindsToConstant()) {
|
| - if (value->definition()->IsUnboxDouble()) {
|
| - return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(),
|
| - result);
|
| + UnboxInstr* unbox = value->definition()->AsUnbox();
|
| + if ((unbox != NULL) && (unbox->representation() == kUnboxedDouble)) {
|
| + return ToIntegerConstant(unbox->value(), result);
|
| }
|
| return false;
|
| }
|
| @@ -1904,29 +1904,32 @@ static bool HasTryBlockUse(Value* use_list) {
|
| }
|
|
|
|
|
| -Definition* BoxDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
|
| +Definition* BoxInstr::Canonicalize(FlowGraph* flow_graph) {
|
| if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
|
| // Environments can accomodate any representation. No need to box.
|
| return value()->definition();
|
| }
|
|
|
| - // Fold away BoxDouble(UnboxDouble(v)) if value is known to be double.
|
| - UnboxDoubleInstr* defn = value()->definition()->AsUnboxDouble();
|
| - if ((defn != NULL) && (defn->value()->Type()->ToCid() == kDoubleCid)) {
|
| - return defn->value()->definition();
|
| + // Fold away Box<rep>(Unbox<rep>(v)) if value is known to be of the
|
| + // right class.
|
| + UnboxInstr* unbox_defn = value()->definition()->AsUnbox();
|
| + if ((unbox_defn != NULL) &&
|
| + (unbox_defn->representation() == from_representation()) &&
|
| + (unbox_defn->value()->Type()->ToCid() == Type()->ToCid())) {
|
| + return unbox_defn->value()->definition();
|
| }
|
|
|
| return this;
|
| }
|
|
|
|
|
| -bool BoxIntNInstr::ValueFitsSmi() const {
|
| +bool BoxIntegerInstr::ValueFitsSmi() const {
|
| Range* range = value()->definition()->range();
|
| return RangeUtils::Fits(range, RangeBoundary::kRangeBoundarySmi);
|
| }
|
|
|
|
|
| -Definition* BoxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
|
| +Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
|
| if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
|
| // Environments can accomodate any representation. No need to box.
|
| return value()->definition();
|
| @@ -1936,11 +1939,72 @@ Definition* BoxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
|
| }
|
|
|
|
|
| -Definition* UnboxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
|
| +Definition* BoxInt64Instr::Canonicalize(FlowGraph* flow_graph) {
|
| + Definition* replacement = BoxIntegerInstr::Canonicalize(flow_graph);
|
| + if (replacement != this) {
|
| + return replacement;
|
| + }
|
| +
|
| + UnboxedIntConverterInstr* conv =
|
| + value()->definition()->AsUnboxedIntConverter();
|
| + if (conv != NULL) {
|
| + Definition* replacement = this;
|
| +
|
| + switch (conv->from()) {
|
| + case kUnboxedInt32:
|
| + replacement = new BoxInt32Instr(conv->value()->CopyWithType());
|
| + break;
|
| + case kUnboxedUint32:
|
| + replacement = new BoxUint32Instr(conv->value()->CopyWithType());
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| +
|
| + if (replacement != this) {
|
| + flow_graph->InsertBefore(this,
|
| + replacement,
|
| + NULL,
|
| + FlowGraph::kValue);
|
| + }
|
| +
|
| + return replacement;
|
| + }
|
| +
|
| + return this;
|
| +}
|
| +
|
| +
|
| +Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) {
|
| if (!HasUses()) return NULL;
|
|
|
| - // Fold away UnboxInt<N>Instr(BoxInt<N>Instr(v)).
|
| - BoxIntNInstr* box_defn = value()->definition()->AsBoxIntN();
|
| + // Fold away Unbox<rep>(Box<rep>(v)).
|
| + BoxInstr* box_defn = value()->definition()->AsBox();
|
| + if ((box_defn != NULL) &&
|
| + (box_defn->from_representation() == representation())) {
|
| + return box_defn->value()->definition();
|
| + }
|
| +
|
| + if (representation() == kUnboxedDouble) {
|
| + ConstantInstr* c = value()->definition()->AsConstant();
|
| + if ((c != NULL) && c->value().IsDouble()) {
|
| + UnboxedConstantInstr* uc =
|
| + new UnboxedConstantInstr(c->value(), kUnboxedDouble);
|
| + flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
|
| + return uc;
|
| + }
|
| + }
|
| +
|
| + return this;
|
| +}
|
| +
|
| +
|
| +Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
|
| + if (!HasUses()) return NULL;
|
| +
|
| + // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)).
|
| + BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger();
|
| if (box_defn != NULL) {
|
| if (box_defn->value()->definition()->representation() == representation()) {
|
| return box_defn->value()->definition();
|
| @@ -1963,6 +2027,33 @@ Definition* UnboxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
|
| }
|
|
|
|
|
| +Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
|
| + Definition* replacement = UnboxIntegerInstr::Canonicalize(flow_graph);
|
| + if (replacement != this) {
|
| + return replacement;
|
| + }
|
| +
|
| + ConstantInstr* c = value()->definition()->AsConstant();
|
| + if ((c != NULL) && c->value().IsSmi()) {
|
| + if (!is_truncating() && (kSmiBits > 32)) {
|
| + // Check that constant fits into 32-bit integer.
|
| + const int64_t value =
|
| + static_cast<int64_t>(Smi::Cast(c->value()).Value());
|
| + if (!Utils::IsInt(32, value)) {
|
| + return this;
|
| + }
|
| + }
|
| +
|
| + UnboxedConstantInstr* uc =
|
| + new UnboxedConstantInstr(c->value(), kUnboxedInt32);
|
| + flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
|
| + return uc;
|
| + }
|
| +
|
| + return this;
|
| +}
|
| +
|
| +
|
| Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
|
| if (!HasUses()) return NULL;
|
|
|
| @@ -1985,7 +2076,7 @@ Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
|
| return converter;
|
| }
|
|
|
| - UnboxIntegerInstr* unbox_defn = value()->definition()->AsUnboxInteger();
|
| + UnboxInt64Instr* unbox_defn = value()->definition()->AsUnboxInt64();
|
| if (unbox_defn != NULL &&
|
| (from() == kUnboxedMint) &&
|
| (to() == kUnboxedInt32) &&
|
| @@ -2009,166 +2100,6 @@ Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
|
| }
|
|
|
|
|
| -Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
|
| - Definition* replacement = UnboxIntNInstr::Canonicalize(flow_graph);
|
| - if (replacement != this) {
|
| - return replacement;
|
| - }
|
| -
|
| - ConstantInstr* c = value()->definition()->AsConstant();
|
| - if ((c != NULL) && c->value().IsSmi()) {
|
| - if (!is_truncating() && (kSmiBits > 32)) {
|
| - // Check that constant fits into 32-bit integer.
|
| - const int64_t value =
|
| - static_cast<int64_t>(Smi::Cast(c->value()).Value());
|
| - if (!Utils::IsInt(32, value)) {
|
| - return this;
|
| - }
|
| - }
|
| -
|
| - UnboxedConstantInstr* uc =
|
| - new UnboxedConstantInstr(c->value(), kUnboxedInt32);
|
| - flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
|
| - return uc;
|
| - }
|
| -
|
| - return this;
|
| -}
|
| -
|
| -
|
| -Definition* UnboxDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
|
| - if (!HasUses()) return NULL;
|
| - // Fold away UnboxDouble(BoxDouble(v)).
|
| - BoxDoubleInstr* box_defn = value()->definition()->AsBoxDouble();
|
| - if (box_defn != NULL) {
|
| - return box_defn->value()->definition();
|
| - }
|
| -
|
| - ConstantInstr* c = value()->definition()->AsConstant();
|
| - if ((c != NULL) && c->value().IsDouble()) {
|
| - UnboxedConstantInstr* uc =
|
| - new UnboxedConstantInstr(c->value(), kUnboxedDouble);
|
| - flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
|
| - return uc;
|
| - }
|
| -
|
| - return this;
|
| -}
|
| -
|
| -
|
| -Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
|
| - if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
|
| - // Environments can accomodate any representation. No need to box.
|
| - return value()->definition();
|
| - }
|
| -
|
| - UnboxedIntConverterInstr* conv =
|
| - value()->definition()->AsUnboxedIntConverter();
|
| - if (conv != NULL) {
|
| - Definition* replacement = this;
|
| -
|
| - switch (conv->from()) {
|
| - case kUnboxedInt32:
|
| - replacement = new BoxInt32Instr(conv->value()->CopyWithType());
|
| - break;
|
| - case kUnboxedUint32:
|
| - replacement = new BoxUint32Instr(conv->value()->CopyWithType());
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - break;
|
| - }
|
| -
|
| - if (replacement != this) {
|
| - flow_graph->InsertBefore(this,
|
| - replacement,
|
| - NULL,
|
| - FlowGraph::kValue);
|
| - }
|
| -
|
| - return replacement;
|
| - }
|
| -
|
| - return this;
|
| -}
|
| -
|
| -
|
| -Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
|
| - if (!HasUses()) return NULL;
|
| - return this;
|
| -}
|
| -
|
| -
|
| -Definition* BoxFloat32x4Instr::Canonicalize(FlowGraph* flow_graph) {
|
| - if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
|
| - // Environments can accomodate any representation. No need to box.
|
| - return value()->definition();
|
| - }
|
| -
|
| - // Fold away BoxFloat32x4(UnboxFloat32x4(v)).
|
| - UnboxFloat32x4Instr* defn = value()->definition()->AsUnboxFloat32x4();
|
| - if ((defn != NULL) && (defn->value()->Type()->ToCid() == kFloat32x4Cid)) {
|
| - return defn->value()->definition();
|
| - }
|
| -
|
| - return this;
|
| -}
|
| -
|
| -
|
| -Definition* UnboxFloat32x4Instr::Canonicalize(FlowGraph* flow_graph) {
|
| - // Fold away UnboxFloat32x4(BoxFloat32x4(v)).
|
| - BoxFloat32x4Instr* defn = value()->definition()->AsBoxFloat32x4();
|
| - return (defn != NULL) ? defn->value()->definition() : this;
|
| -}
|
| -
|
| -
|
| -Definition* BoxFloat64x2Instr::Canonicalize(FlowGraph* flow_graph) {
|
| - if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
|
| - // Environments can accomodate any representation. No need to box.
|
| - return value()->definition();
|
| - }
|
| -
|
| - // Fold away BoxFloat64x2(UnboxFloat64x2(v)).
|
| - UnboxFloat64x2Instr* defn = value()->definition()->AsUnboxFloat64x2();
|
| - if ((defn != NULL) && (defn->value()->Type()->ToCid() == kFloat64x2Cid)) {
|
| - return defn->value()->definition();
|
| - }
|
| -
|
| - return this;
|
| -}
|
| -
|
| -
|
| -Definition* UnboxFloat64x2Instr::Canonicalize(FlowGraph* flow_graph) {
|
| - // Fold away UnboxFloat64x2(BoxFloat64x2(v)).
|
| - BoxFloat64x2Instr* defn = value()->definition()->AsBoxFloat64x2();
|
| - return (defn != NULL) ? defn->value()->definition() : this;
|
| -}
|
| -
|
| -
|
| -
|
| -Definition* BoxInt32x4Instr::Canonicalize(FlowGraph* flow_graph) {
|
| - if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
|
| - // Environments can accomodate any representation. No need to box.
|
| - return value()->definition();
|
| - }
|
| -
|
| - // Fold away BoxInt32x4(UnboxInt32x4(v)).
|
| - UnboxInt32x4Instr* defn = value()->definition()->AsUnboxInt32x4();
|
| - if ((defn != NULL) && (defn->value()->Type()->ToCid() == kInt32x4Cid)) {
|
| - return defn->value()->definition();
|
| - }
|
| -
|
| - return this;
|
| -}
|
| -
|
| -
|
| -Definition* UnboxInt32x4Instr::Canonicalize(FlowGraph* flow_graph) {
|
| - // Fold away UnboxInt32x4(BoxInt32x4(v)).
|
| - BoxInt32x4Instr* defn = value()->definition()->AsBoxInt32x4();
|
| - return (defn != NULL) ? defn->value()->definition() : this;
|
| -}
|
| -
|
| -
|
| Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) {
|
| Definition* defn = value()->definition();
|
| if (defn->IsComparison() && defn->HasOnlyUse(value())) {
|
| @@ -2460,6 +2391,93 @@ Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) {
|
| }
|
|
|
|
|
| +BoxInstr* BoxInstr::Create(Representation from, Value* value) {
|
| + switch (from) {
|
| + case kUnboxedInt32:
|
| + return new BoxInt32Instr(value);
|
| +
|
| + case kUnboxedUint32:
|
| + return new BoxUint32Instr(value);
|
| +
|
| + case kUnboxedMint:
|
| + return new BoxInt64Instr(value);
|
| +
|
| + case kUnboxedDouble:
|
| + case kUnboxedFloat32x4:
|
| + case kUnboxedFloat64x2:
|
| + case kUnboxedInt32x4:
|
| + return new BoxInstr(from, value);
|
| +
|
| + default:
|
| + UNREACHABLE();
|
| + return NULL;
|
| + }
|
| +}
|
| +
|
| +
|
| +UnboxInstr* UnboxInstr::Create(Representation to,
|
| + Value* value,
|
| + intptr_t deopt_id) {
|
| + switch (to) {
|
| + case kUnboxedInt32:
|
| + return new UnboxInt32Instr(value, deopt_id);
|
| +
|
| + case kUnboxedUint32:
|
| + return new UnboxUint32Instr(value, deopt_id);
|
| +
|
| + case kUnboxedMint:
|
| + return new UnboxInt64Instr(value, deopt_id);
|
| +
|
| + case kUnboxedDouble:
|
| + case kUnboxedFloat32x4:
|
| + case kUnboxedFloat64x2:
|
| + case kUnboxedInt32x4:
|
| + return new UnboxInstr(to, value, deopt_id);
|
| +
|
| + default:
|
| + UNREACHABLE();
|
| + return NULL;
|
| + }
|
| +}
|
| +
|
| +
|
| +bool UnboxInstr::CanConvertSmi() const {
|
| + switch (representation()) {
|
| + case kUnboxedDouble:
|
| + case kUnboxedMint:
|
| + return true;
|
| +
|
| + case kUnboxedFloat32x4:
|
| + case kUnboxedFloat64x2:
|
| + case kUnboxedInt32x4:
|
| + return false;
|
| +
|
| + default:
|
| + UNREACHABLE();
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +
|
| +intptr_t UnboxInstr::BoxCid() const {
|
| + switch (representation()) {
|
| + case kUnboxedMint:
|
| + return kMintCid;
|
| + case kUnboxedDouble:
|
| + return kDoubleCid;
|
| + case kUnboxedFloat32x4:
|
| + return kFloat32x4Cid;
|
| + case kUnboxedFloat64x2:
|
| + return kFloat64x2Cid;
|
| + case kUnboxedInt32x4:
|
| + return kInt32x4Cid;
|
| + default:
|
| + UNREACHABLE();
|
| + return kIllegalCid;
|
| + }
|
| +}
|
| +
|
| +
|
| // Shared code generation methods (EmitNativeCode and
|
| // MakeLocationSummary). Only assembly code that can be shared across all
|
| // architectures can be used. Machine specific register allocation and code
|
|
|