| Index: src/compiler/mips64/instruction-selector-mips64.cc
|
| diff --git a/src/compiler/mips64/instruction-selector-mips64.cc b/src/compiler/mips64/instruction-selector-mips64.cc
|
| index 1b3b6a6d62ccfc598253072bb32c7c83934f145a..6f72c6451d1fb920c0aae444f7cf1dbeb3ff6182 100644
|
| --- a/src/compiler/mips64/instruction-selector-mips64.cc
|
| +++ b/src/compiler/mips64/instruction-selector-mips64.cc
|
| @@ -31,14 +31,25 @@ class Mips64OperandGenerator final : public OperandGenerator {
|
| return UseRegister(node);
|
| }
|
|
|
| - bool CanBeImmediate(Node* node, InstructionCode opcode) {
|
| - int64_t value;
|
| - if (node->opcode() == IrOpcode::kInt32Constant)
|
| - value = OpParameter<int32_t>(node);
|
| - else if (node->opcode() == IrOpcode::kInt64Constant)
|
| - value = OpParameter<int64_t>(node);
|
| - else
|
| - return false;
|
| + bool IsIntegerConstant(Node* node) {
|
| + return (node->opcode() == IrOpcode::kInt32Constant) ||
|
| + (node->opcode() == IrOpcode::kInt64Constant);
|
| + }
|
| +
|
| + int64_t GetIntegerConstantValue(Node* node) {
|
| + if (node->opcode() == IrOpcode::kInt32Constant) {
|
| + return OpParameter<int32_t>(node);
|
| + }
|
| + DCHECK(node->opcode() == IrOpcode::kInt64Constant);
|
| + return OpParameter<int64_t>(node);
|
| + }
|
| +
|
| + bool CanBeImmediate(Node* node, InstructionCode mode) {
|
| + return IsIntegerConstant(node) &&
|
| + CanBeImmediate(GetIntegerConstantValue(node), mode);
|
| + }
|
| +
|
| + bool CanBeImmediate(int64_t value, InstructionCode opcode) {
|
| switch (ArchOpcodeField::decode(opcode)) {
|
| case kMips64Shl:
|
| case kMips64Sar:
|
| @@ -91,6 +102,76 @@ static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode,
|
| g.UseOperand(node->InputAt(1), opcode));
|
| }
|
|
|
| +struct ExtendingLoadMatcher {
|
| + ExtendingLoadMatcher(Node* node, InstructionSelector* selector)
|
| + : matches_(false), selector_(selector), base_(nullptr), immediate_(0) {
|
| + Initialize(node);
|
| + }
|
| +
|
| + bool Matches() const { return matches_; }
|
| +
|
| + Node* base() const {
|
| + DCHECK(Matches());
|
| + return base_;
|
| + }
|
| + int64_t immediate() const {
|
| + DCHECK(Matches());
|
| + return immediate_;
|
| + }
|
| + ArchOpcode opcode() const {
|
| + DCHECK(Matches());
|
| + return opcode_;
|
| + }
|
| +
|
| + private:
|
| + bool matches_;
|
| + InstructionSelector* selector_;
|
| + Node* base_;
|
| + int64_t immediate_;
|
| + ArchOpcode opcode_;
|
| +
|
| + void Initialize(Node* node) {
|
| + Int64BinopMatcher m(node);
|
| + // When loading a 64-bit value and shifting by 32, we should
|
| + // just load and sign-extend the interesting 4 bytes instead.
|
| + // This happens, for example, when we're loading and untagging SMIs.
|
| + DCHECK(m.IsWord64Sar());
|
| + if (m.left().IsLoad() && m.right().Is(32) &&
|
| + selector_->CanCover(m.node(), m.left().node())) {
|
| + Mips64OperandGenerator g(selector_);
|
| + Node* load = m.left().node();
|
| + Node* offset = load->InputAt(1);
|
| + base_ = load->InputAt(0);
|
| + opcode_ = kMips64Lw;
|
| + if (g.CanBeImmediate(offset, opcode_)) {
|
| +#if defined(V8_TARGET_LITTLE_ENDIAN)
|
| + immediate_ = g.GetIntegerConstantValue(offset) + 4;
|
| +#elif defined(V8_TARGET_BIG_ENDIAN)
|
| + immediate_ = g.GetIntegerConstantValue(offset);
|
| +#endif
|
| + matches_ = g.CanBeImmediate(immediate_, kMips64Lw);
|
| + }
|
| + }
|
| + }
|
| +};
|
| +
|
| +bool TryEmitExtendingLoad(InstructionSelector* selector, Node* node) {
|
| + ExtendingLoadMatcher m(node, selector);
|
| + Mips64OperandGenerator g(selector);
|
| + if (m.Matches()) {
|
| + InstructionOperand inputs[2];
|
| + inputs[0] = g.UseRegister(m.base());
|
| + InstructionCode opcode =
|
| + m.opcode() | AddressingModeField::encode(kMode_MRI);
|
| + DCHECK(is_int32(m.immediate()));
|
| + inputs[1] = g.TempImmediate(static_cast<int32_t>(m.immediate()));
|
| + InstructionOperand outputs[] = {g.DefineAsRegister(node)};
|
| + selector->Emit(opcode, arraysize(outputs), outputs, arraysize(inputs),
|
| + inputs);
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
|
|
| static void VisitBinop(InstructionSelector* selector, Node* node,
|
| InstructionCode opcode, FlagsContinuation* cont) {
|
| @@ -597,6 +678,7 @@ void InstructionSelector::VisitWord64Shr(Node* node) {
|
|
|
|
|
| void InstructionSelector::VisitWord64Sar(Node* node) {
|
| + if (TryEmitExtendingLoad(this, node)) return;
|
| VisitRRO(this, kMips64Dsar, node);
|
| }
|
|
|
|
|