| Index: src/compiler/s390/instruction-selector-s390.cc
|
| diff --git a/src/compiler/s390/instruction-selector-s390.cc b/src/compiler/s390/instruction-selector-s390.cc
|
| index 2bcb822e1593a0e7efee354349ebb08a3ad30cc8..7d735969cabd3ffa26ca6ed0b80daa048cb0085d 100644
|
| --- a/src/compiler/s390/instruction-selector-s390.cc
|
| +++ b/src/compiler/s390/instruction-selector-s390.cc
|
| @@ -35,6 +35,16 @@ class S390OperandGenerator final : public OperandGenerator {
|
| return UseRegister(node);
|
| }
|
|
|
| + int64_t GetImmediate(Node* node) {
|
| + if (node->opcode() == IrOpcode::kInt32Constant)
|
| + return OpParameter<int32_t>(node);
|
| + else if (node->opcode() == IrOpcode::kInt64Constant)
|
| + return OpParameter<int64_t>(node);
|
| + else
|
| + UNIMPLEMENTED();
|
| + return 0L;
|
| + }
|
| +
|
| bool CanBeImmediate(Node* node, ImmediateMode mode) {
|
| int64_t value;
|
| if (node->opcode() == IrOpcode::kInt32Constant)
|
| @@ -132,6 +142,18 @@ class S390OperandGenerator final : public OperandGenerator {
|
| return kMode_MRR;
|
| }
|
| }
|
| +
|
| + bool CanBeBetterLeftOperand(Node* node) const {
|
| + return !selector()->IsLive(node);
|
| + }
|
| +
|
| + MachineRepresentation GetRepresentation(Node* node) {
|
| + return sequence()->GetRepresentation(selector()->GetVirtualRegister(node));
|
| + }
|
| +
|
| + bool Is64BitOperand(Node* node) {
|
| + return MachineRepresentation::kWord64 == GetRepresentation(node);
|
| + }
|
| };
|
|
|
| namespace {
|
| @@ -182,13 +204,36 @@ void VisitBinop(InstructionSelector* selector, Node* node,
|
| FlagsContinuation* cont) {
|
| S390OperandGenerator g(selector);
|
| Matcher m(node);
|
| + Node* left = m.left().node();
|
| + Node* right = m.right().node();
|
| InstructionOperand inputs[4];
|
| size_t input_count = 0;
|
| InstructionOperand outputs[2];
|
| size_t output_count = 0;
|
|
|
| - inputs[input_count++] = g.UseRegister(m.left().node());
|
| - inputs[input_count++] = g.UseOperand(m.right().node(), operand_mode);
|
| + // TODO(turbofan): match complex addressing modes.
|
| + if (left == right) {
|
| + // If both inputs refer to the same operand, enforce allocating a register
|
| + // for both of them to ensure that we don't end up generating code like
|
| + // this:
|
| + //
|
| + // mov rax, [rbp-0x10]
|
| + // add rax, [rbp-0x10]
|
| + // jo label
|
| + InstructionOperand const input = g.UseRegister(left);
|
| + inputs[input_count++] = input;
|
| + inputs[input_count++] = input;
|
| + } else if (g.CanBeImmediate(right, operand_mode)) {
|
| + inputs[input_count++] = g.UseRegister(left);
|
| + inputs[input_count++] = g.UseImmediate(right);
|
| + } else {
|
| + if (node->op()->HasProperty(Operator::kCommutative) &&
|
| + g.CanBeBetterLeftOperand(right)) {
|
| + std::swap(left, right);
|
| + }
|
| + inputs[input_count++] = g.UseRegister(left);
|
| + inputs[input_count++] = g.UseRegister(right);
|
| + }
|
|
|
| if (cont->IsBranch()) {
|
| inputs[input_count++] = g.Label(cont->true_block());
|
| @@ -1002,28 +1047,89 @@ void EmitInt32MulWithOverflow(InstructionSelector* selector, Node* node,
|
| VisitCompare(selector, kS390_Cmp32, high32_operand, temp_operand, cont);
|
| }
|
|
|
| +void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
|
| + S390OperandGenerator g(selector);
|
| + Int32BinopMatcher m(node);
|
| + Node* left = m.left().node();
|
| + Node* right = m.right().node();
|
| + if (g.CanBeImmediate(right, kInt32Imm)) {
|
| + selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
|
| + g.UseImmediate(right));
|
| + } else {
|
| + if (g.CanBeBetterLeftOperand(right)) {
|
| + std::swap(left, right);
|
| + }
|
| + selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
|
| + g.Use(right));
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| +void InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
|
| + if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
| + FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
|
| + return EmitInt32MulWithOverflow(this, node, &cont);
|
| + }
|
| + VisitMul(this, node, kS390_Mul32);
|
| + // FlagsContinuation cont;
|
| + // EmitInt32MulWithOverflow(this, node, &cont);
|
| +}
|
| +
|
| void InstructionSelector::VisitInt32Mul(Node* node) {
|
| - VisitRRR(this, kS390_Mul32, node);
|
| + S390OperandGenerator g(this);
|
| + Int32BinopMatcher m(node);
|
| + Node* left = m.left().node();
|
| + Node* right = m.right().node();
|
| + if (g.CanBeImmediate(right, kInt32Imm) &&
|
| + base::bits::IsPowerOfTwo32(g.GetImmediate(right))) {
|
| + int power = 31 - base::bits::CountLeadingZeros32(g.GetImmediate(right));
|
| + Emit(kS390_ShiftLeft32, g.DefineSameAsFirst(node), g.UseRegister(left),
|
| + g.UseImmediate(power));
|
| + return;
|
| + }
|
| + VisitMul(this, node, kS390_Mul32);
|
| }
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitInt64Mul(Node* node) {
|
| - VisitRRR(this, kS390_Mul64, node);
|
| + S390OperandGenerator g(this);
|
| + Int64BinopMatcher m(node);
|
| + Node* left = m.left().node();
|
| + Node* right = m.right().node();
|
| + if (g.CanBeImmediate(right, kInt32Imm) &&
|
| + base::bits::IsPowerOfTwo64(g.GetImmediate(right))) {
|
| + int power = 31 - base::bits::CountLeadingZeros64(g.GetImmediate(right));
|
| + Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left),
|
| + g.UseImmediate(power));
|
| + return;
|
| + }
|
| + VisitMul(this, node, kS390_Mul64);
|
| }
|
| #endif
|
|
|
| void InstructionSelector::VisitInt32MulHigh(Node* node) {
|
| S390OperandGenerator g(this);
|
| - Emit(kS390_MulHigh32, g.DefineAsRegister(node),
|
| - g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
|
| + Int32BinopMatcher m(node);
|
| + Node* left = m.left().node();
|
| + Node* right = m.right().node();
|
| + if (g.CanBeBetterLeftOperand(right)) {
|
| + std::swap(left, right);
|
| + }
|
| + Emit(kS390_MulHigh32, g.DefineAsRegister(node), g.UseRegister(left),
|
| + g.Use(right));
|
| }
|
|
|
| void InstructionSelector::VisitUint32MulHigh(Node* node) {
|
| S390OperandGenerator g(this);
|
| - Emit(kS390_MulHighU32, g.DefineAsRegister(node),
|
| - g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
|
| + Int32BinopMatcher m(node);
|
| + Node* left = m.left().node();
|
| + Node* right = m.right().node();
|
| + if (g.CanBeBetterLeftOperand(right)) {
|
| + std::swap(left, right);
|
| + }
|
| + Emit(kS390_MulHighU32, g.DefineAsRegister(node), g.UseRegister(left),
|
| + g.Use(right));
|
| }
|
|
|
| void InstructionSelector::VisitInt32Div(Node* node) {
|
| @@ -1721,15 +1827,6 @@ void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) {
|
| }
|
| #endif
|
|
|
| -void InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
|
| - if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
| - FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
|
| - return EmitInt32MulWithOverflow(this, node, &cont);
|
| - }
|
| - FlagsContinuation cont;
|
| - EmitInt32MulWithOverflow(this, node, &cont);
|
| -}
|
| -
|
| void InstructionSelector::VisitFloat32Equal(Node* node) {
|
| FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
|
| VisitFloat32Compare(this, node, &cont);
|
|
|