diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 2d72687d31..bd46dd8f58 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1675,8 +1675,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } return result; } else if (instr->representation().IsExternal()) { - DCHECK(instr->left()->representation().IsExternal()); - DCHECK(instr->right()->representation().IsInteger32()); + DCHECK(instr->IsConsistentExternalRepresentation()); DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseOrConstantAtStart(instr->right()); diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc index 920ea3e6c5..f914551066 100644 --- a/src/arm64/lithium-arm64.cc +++ b/src/arm64/lithium-arm64.cc @@ -901,8 +901,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } return result; } else if (instr->representation().IsExternal()) { - DCHECK(instr->left()->representation().IsExternal()); - DCHECK(instr->right()->representation().IsInteger32()); + DCHECK(instr->IsConsistentExternalRepresentation()); DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseRegisterOrConstantAtStart(instr->right()); diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 6b8768e9a9..24259c8b7b 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -1432,6 +1432,17 @@ HValue* HBitwise::Canonicalize() { } +// static +HInstruction* HAdd::New(Isolate* isolate, Zone* zone, HValue* context, + HValue* left, HValue* right, Strength strength, + ExternalAddType external_add_type) { + // For everything else, you should use the other factory method without + // ExternalAddType. + DCHECK_EQ(external_add_type, AddOfExternalAndTagged); + return new (zone) HAdd(context, left, right, strength, external_add_type); +} + + Representation HAdd::RepresentationFromInputs() { Representation left_rep = left()->representation(); if (left_rep.IsExternal()) { @@ -1445,7 +1456,11 @@ Representation HAdd::RequiredInputRepresentation(int index) { if (index == 2) { Representation left_rep = left()->representation(); if (left_rep.IsExternal()) { - return Representation::Integer32(); + if (external_add_type_ == AddOfExternalAndTagged) { + return Representation::Tagged(); + } else { + return Representation::Integer32(); + } } } return HArithmeticBinaryOperation::RequiredInputRepresentation(index); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 11e85a0c03..9d95033080 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -4830,11 +4830,21 @@ class HPower final : public HTemplateInstruction<2> { }; +enum ExternalAddType { + AddOfExternalAndTagged, + AddOfExternalAndInt32, + NoExternalAdd +}; + + class HAdd final : public HArithmeticBinaryOperation { public: static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, HValue* left, HValue* right, Strength strength = Strength::WEAK); + static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, + HValue* left, HValue* right, Strength strength, + ExternalAddType external_add_type); // Add is only commutative if two integer values are added and not if two // tagged values are added (because it might be a String concatenation). @@ -4877,6 +4887,14 @@ class HAdd final : public HArithmeticBinaryOperation { Representation RequiredInputRepresentation(int index) override; + bool IsConsistentExternalRepresentation() { + return left()->representation().IsExternal() && + ((external_add_type_ == AddOfExternalAndInt32 && + right()->representation().IsInteger32()) || + (external_add_type_ == AddOfExternalAndTagged && + right()->representation().IsTagged())); + } + DECLARE_CONCRETE_INSTRUCTION(Add) protected: @@ -4885,10 +4903,35 @@ class HAdd final : public HArithmeticBinaryOperation { Range* InferRange(Zone* zone) override; private: - HAdd(HValue* context, HValue* left, HValue* right, Strength strength) - : HArithmeticBinaryOperation(context, left, right, strength) { + HAdd(HValue* context, HValue* left, HValue* right, Strength strength, + ExternalAddType external_add_type = NoExternalAdd) + : HArithmeticBinaryOperation(context, left, right, strength), + external_add_type_(external_add_type) { SetFlag(kCanOverflow); + switch (external_add_type_) { + case AddOfExternalAndTagged: + DCHECK(left->representation().IsExternal()); + DCHECK(right->representation().IsTagged()); + SetDependsOnFlag(kNewSpacePromotion); + break; + + case NoExternalAdd: + // This is a bit of a hack: The call to this constructor is generated + // by a macro that also supports sub and mul, so it doesn't pass in + // a value for external_add_type but uses the default. + if (left->representation().IsExternal()) { + external_add_type_ = AddOfExternalAndInt32; + } + break; + + case AddOfExternalAndInt32: + // See comment above. + UNREACHABLE(); + break; + } } + + ExternalAddType external_add_type_; }; diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 7a3c373a45..b94020cbea 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -1629,8 +1629,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } else if (instr->representation().IsDouble()) { return DoArithmeticD(Token::ADD, instr); } else if (instr->representation().IsExternal()) { - DCHECK(instr->left()->representation().IsExternal()); - DCHECK(instr->right()->representation().IsInteger32()); + DCHECK(instr->IsConsistentExternalRepresentation()); DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); bool use_lea = LAddI::UseLea(instr); LOperand* left = UseRegisterAtStart(instr->left()); diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 3f0e7bfd27..733866572f 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -1622,8 +1622,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } return result; } else if (instr->representation().IsExternal()) { - DCHECK(instr->left()->representation().IsExternal()); - DCHECK(instr->right()->representation().IsInteger32()); + DCHECK(instr->IsConsistentExternalRepresentation()); DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseOrConstantAtStart(instr->right()); diff --git a/src/mips64/lithium-mips64.cc b/src/mips64/lithium-mips64.cc index 97c2d2ef75..7d06ec747f 100644 --- a/src/mips64/lithium-mips64.cc +++ b/src/mips64/lithium-mips64.cc @@ -1630,8 +1630,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } return result; } else if (instr->representation().IsExternal()) { - DCHECK(instr->left()->representation().IsExternal()); - DCHECK(instr->right()->representation().IsInteger32()); + DCHECK(instr->IsConsistentExternalRepresentation()); DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseRegisterOrConstantAtStart(instr->right()); diff --git a/src/ppc/lithium-ppc.cc b/src/ppc/lithium-ppc.cc index 296f0ac364..15782e1075 100644 --- a/src/ppc/lithium-ppc.cc +++ b/src/ppc/lithium-ppc.cc @@ -1645,8 +1645,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } return result; } else if (instr->representation().IsExternal()) { - DCHECK(instr->left()->representation().IsExternal()); - DCHECK(instr->right()->representation().IsInteger32()); + DCHECK(instr->IsConsistentExternalRepresentation()); DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); LOperand* left = UseRegisterAtStart(instr->left()); LOperand* right = UseOrConstantAtStart(instr->right()); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index f1710bd561..e41133cb00 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1619,8 +1619,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } return result; } else if (instr->representation().IsExternal()) { - DCHECK(instr->left()->representation().IsExternal()); - DCHECK(instr->right()->representation().IsInteger32()); + DCHECK(instr->IsConsistentExternalRepresentation()); DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); bool use_lea = LAddI::UseLea(instr); LOperand* left = UseRegisterAtStart(instr->left()); diff --git a/src/x87/lithium-x87.cc b/src/x87/lithium-x87.cc index 301f128e11..f421c4addf 100644 --- a/src/x87/lithium-x87.cc +++ b/src/x87/lithium-x87.cc @@ -1639,8 +1639,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } else if (instr->representation().IsDouble()) { return DoArithmeticD(Token::ADD, instr); } else if (instr->representation().IsExternal()) { - DCHECK(instr->left()->representation().IsExternal()); - DCHECK(instr->right()->representation().IsInteger32()); + DCHECK(instr->IsConsistentExternalRepresentation()); DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); bool use_lea = LAddI::UseLea(instr); LOperand* left = UseRegisterAtStart(instr->left());