| 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 e591d3caeb132cfbec8d994710b5078dd8c695f7..3a27f191af66958a02e4c349c402d766da406f92 100644
|
| --- a/src/compiler/s390/instruction-selector-s390.cc
|
| +++ b/src/compiler/s390/instruction-selector-s390.cc
|
| @@ -43,20 +43,28 @@ OperandModes immediateModeMask =
|
| OperandMode::kInt32Imm | OperandMode::kInt32Imm_Negate |
|
| OperandMode::kUint32Imm | OperandMode::kInt20Imm;
|
|
|
| -#define AndOperandMode \
|
| - ((OperandMode::kBitWiseCommonMode | OperandMode::kUint32Imm | \
|
| - OperandMode::kAllowRM | (CpuFeatures::IsSupported(DISTINCT_OPS) \
|
| - ? OperandMode::kAllowRRR \
|
| - : OperandMode::kBitWiseCommonMode)))
|
| -
|
| -#define OrOperandMode AndOperandMode
|
| -#define XorOperandMode AndOperandMode
|
| -
|
| -#define ShiftOperandMode \
|
| - ((OperandMode::kBitWiseCommonMode | OperandMode::kShift64Imm | \
|
| - (CpuFeatures::IsSupported(DISTINCT_OPS) \
|
| - ? OperandMode::kAllowRRR \
|
| - : OperandMode::kBitWiseCommonMode)))
|
| +#define AndCommonMode \
|
| + ((OperandMode::kAllowRM | \
|
| + (CpuFeatures::IsSupported(DISTINCT_OPS) ? OperandMode::kAllowRRR \
|
| + : OperandMode::kNone)))
|
| +#define And64OperandMode AndCommonMode
|
| +#define Or64OperandMode And64OperandMode
|
| +#define Xor64OperandMode And64OperandMode
|
| +
|
| +#define And32OperandMode \
|
| + (AndCommonMode | OperandMode::kAllowRI | OperandMode::kUint32Imm)
|
| +#define Or32OperandMode And32OperandMode
|
| +#define Xor32OperandMode And32OperandMode
|
| +
|
| +#define Shift32OperandMode \
|
| + ((OperandMode::kAllowRI | OperandMode::kShift64Imm | \
|
| + (CpuFeatures::IsSupported(DISTINCT_OPS) \
|
| + ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \
|
| + : OperandMode::kNone)))
|
| +
|
| +#define Shift64OperandMode \
|
| + ((OperandMode::kAllowRI | OperandMode::kShift64Imm | \
|
| + OperandMode::kAllowRRR | OperandMode::kAllowRRI))
|
|
|
| #define AddOperandMode \
|
| ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm | \
|
| @@ -241,8 +249,11 @@ namespace {
|
|
|
| bool S390OpcodeOnlySupport12BitDisp(ArchOpcode opcode) {
|
| switch (opcode) {
|
| + case kS390_AddFloat:
|
| + case kS390_AddDouble:
|
| case kS390_CmpFloat:
|
| case kS390_CmpDouble:
|
| + case kS390_Float32ToDouble:
|
| return true;
|
| default:
|
| return false;
|
| @@ -319,6 +330,7 @@ bool AutoZeroExtendsWord32ToWord64(Node* node) {
|
| case IrOpcode::kUint32Mod:
|
| case IrOpcode::kWord32Clz:
|
| case IrOpcode::kWord32Popcnt:
|
| + case IrOpcode::kChangeUint32ToUint64:
|
| return true;
|
| default:
|
| return false;
|
| @@ -392,22 +404,12 @@ void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
|
| g.UseRegister(node->InputAt(0)));
|
| }
|
|
|
| -void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
|
| - S390OperandGenerator g(selector);
|
| - selector->Emit(opcode, g.DefineAsRegister(node),
|
| - g.UseRegister(node->InputAt(0)),
|
| - g.UseRegister(node->InputAt(1)));
|
| -}
|
| +// TODO(john.yan): Create VisiteShift to match dst = src shift (R+I)
|
| +#if 0
|
| +void VisitShift() { }
|
| +#endif
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| -void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node,
|
| - OperandModes operand_mode) {
|
| - S390OperandGenerator g(selector);
|
| - selector->Emit(opcode, g.DefineAsRegister(node),
|
| - g.UseRegister(node->InputAt(0)),
|
| - g.UseOperand(node->InputAt(1), operand_mode));
|
| -}
|
| -
|
| void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode,
|
| Node* node) {
|
| S390OperandGenerator g(selector);
|
| @@ -425,57 +427,151 @@ void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode,
|
| }
|
| #endif
|
|
|
| -// Shared routine for multiple binary operations.
|
| -template <typename Matcher>
|
| -void VisitBinop(InstructionSelector* selector, Node* node,
|
| - InstructionCode opcode, OperandModes operand_mode,
|
| - FlagsContinuation* cont) {
|
| +template <class CanCombineWithLoad>
|
| +void GenerateRightOperands(InstructionSelector* selector, Node* node,
|
| + Node* right, InstructionCode& opcode,
|
| + OperandModes& operand_mode,
|
| + InstructionOperand* inputs, size_t& input_count,
|
| + CanCombineWithLoad canCombineWithLoad) {
|
| 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;
|
|
|
| - // 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);
|
| + if ((operand_mode & OperandMode::kAllowImmediate) &&
|
| + g.CanBeImmediate(right, operand_mode)) {
|
| inputs[input_count++] = g.UseImmediate(right);
|
| - } else {
|
| - if (node->op()->HasProperty(Operator::kCommutative) &&
|
| - g.CanBeBetterLeftOperand(right)) {
|
| - std::swap(left, right);
|
| + // Can only be RI or RRI
|
| + operand_mode &= OperandMode::kAllowImmediate;
|
| + } else if (operand_mode & OperandMode::kAllowMemoryOperand) {
|
| + NodeMatcher mright(right);
|
| + if (mright.IsLoad() && selector->CanCover(node, right) &&
|
| + canCombineWithLoad(SelectLoadOpcode(right))) {
|
| + AddressingMode mode = g.GetEffectiveAddressMemoryOperand(
|
| + right, inputs, &input_count, OpcodeImmMode(opcode));
|
| + opcode |= AddressingModeField::encode(mode);
|
| + operand_mode &= ~OperandMode::kAllowImmediate;
|
| + if (operand_mode & OperandMode::kAllowRM)
|
| + operand_mode &= ~OperandMode::kAllowDistinctOps;
|
| + } else if (operand_mode & OperandMode::kAllowRM) {
|
| + DCHECK(!(operand_mode & OperandMode::kAllowRRM));
|
| + inputs[input_count++] = g.UseAnyExceptImmediate(right);
|
| + // Can not be Immediate
|
| + operand_mode &=
|
| + ~OperandMode::kAllowImmediate & ~OperandMode::kAllowDistinctOps;
|
| + } else if (operand_mode & OperandMode::kAllowRRM) {
|
| + DCHECK(!(operand_mode & OperandMode::kAllowRM));
|
| + inputs[input_count++] = g.UseAnyExceptImmediate(right);
|
| + // Can not be Immediate
|
| + operand_mode &= ~OperandMode::kAllowImmediate;
|
| + } else {
|
| + UNREACHABLE();
|
| }
|
| - inputs[input_count++] = g.UseRegister(left);
|
| + } else {
|
| inputs[input_count++] = g.UseRegister(right);
|
| + // Can only be RR or RRR
|
| + operand_mode &= OperandMode::kAllowRRR;
|
| }
|
| +}
|
| +
|
| +template <class CanCombineWithLoad>
|
| +void GenerateBinOpOperands(InstructionSelector* selector, Node* node,
|
| + Node* left, Node* right, InstructionCode& opcode,
|
| + OperandModes& operand_mode,
|
| + InstructionOperand* inputs, size_t& input_count,
|
| + CanCombineWithLoad canCombineWithLoad) {
|
| + S390OperandGenerator g(selector);
|
| + // left is always register
|
| + InstructionOperand const left_input = g.UseRegister(left);
|
| + inputs[input_count++] = left_input;
|
| +
|
| + if (left == right) {
|
| + inputs[input_count++] = left_input;
|
| + // Can only be RR or RRR
|
| + operand_mode &= OperandMode::kAllowRRR;
|
| + } else {
|
| + GenerateRightOperands(selector, node, right, opcode, operand_mode, inputs,
|
| + input_count, canCombineWithLoad);
|
| + }
|
| +}
|
| +
|
| +template <class CanCombineWithLoad>
|
| +void VisitUnaryOp(InstructionSelector* selector, Node* node,
|
| + InstructionCode opcode, OperandModes operand_mode,
|
| + FlagsContinuation* cont,
|
| + CanCombineWithLoad canCombineWithLoad);
|
| +
|
| +template <class CanCombineWithLoad>
|
| +void VisitBinOp(InstructionSelector* selector, Node* node,
|
| + InstructionCode opcode, OperandModes operand_mode,
|
| + FlagsContinuation* cont, CanCombineWithLoad canCombineWithLoad);
|
| +
|
| +#define VISIT_OP_LIST(V) \
|
| + V(Word64, Unary, \
|
| + [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; }) \
|
| + V(Word64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; }) \
|
| + V(Float32, Unary, \
|
| + [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \
|
| + V(Float64, Unary, \
|
| + [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; }) \
|
| + V(Float32, Bin, \
|
| + [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \
|
| + V(Float64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; })
|
| +
|
| +#define DECLARE_VISIT_HELPER_FUNCTIONS(type1, type2, canCombineWithLoad) \
|
| + void Visit##type1##type2##Op( \
|
| + InstructionSelector* selector, Node* node, InstructionCode opcode, \
|
| + OperandModes operand_mode, FlagsContinuation* cont) { \
|
| + Visit##type2##Op(selector, node, opcode, operand_mode, cont, \
|
| + canCombineWithLoad); \
|
| + } \
|
| + void Visit##type1##type2##Op(InstructionSelector* selector, Node* node, \
|
| + InstructionCode opcode, \
|
| + OperandModes operand_mode) { \
|
| + FlagsContinuation cont; \
|
| + Visit##type1##type2##Op(selector, node, opcode, operand_mode, &cont); \
|
| + }
|
| +VISIT_OP_LIST(DECLARE_VISIT_HELPER_FUNCTIONS);
|
| +#undef DECLARE_VISIT_HELPER_FUNCTIONS
|
| +
|
| +template <class CanCombineWithLoad>
|
| +void VisitUnaryOp(InstructionSelector* selector, Node* node,
|
| + InstructionCode opcode, OperandModes operand_mode,
|
| + FlagsContinuation* cont,
|
| + CanCombineWithLoad canCombineWithLoad) {
|
| +// Just to get rid of unused function warning
|
| +#define USE_VISITOR(type1, type2, canCombineWithLoad) \
|
| + { \
|
| + VisiterType dummy = Visit##type1##type2##Op; \
|
| + USE(dummy); \
|
| + }
|
| + typedef void (*VisiterType)(InstructionSelector * selector, Node * node,
|
| + InstructionCode opcode,
|
| + OperandModes operand_mode);
|
| + VISIT_OP_LIST(USE_VISITOR);
|
| +#undef USE_VISITOR
|
| +
|
| + S390OperandGenerator g(selector);
|
| + InstructionOperand inputs[8];
|
| + size_t input_count = 0;
|
| + InstructionOperand outputs[2];
|
| + size_t output_count = 0;
|
| + Node* input = node->InputAt(0);
|
| +
|
| + GenerateRightOperands(selector, node, input, opcode, operand_mode, inputs,
|
| + input_count, canCombineWithLoad);
|
|
|
| if (cont->IsBranch()) {
|
| inputs[input_count++] = g.Label(cont->true_block());
|
| inputs[input_count++] = g.Label(cont->false_block());
|
| }
|
|
|
| - if (cont->IsDeoptimize()) {
|
| - // If we can deoptimize as a result of the binop, we need to make sure that
|
| - // the deopt inputs are not overwritten by the binop result. One way
|
| + if (!cont->IsDeoptimize()) {
|
| + // If we can deoptimize as a result of the binop, we need to make sure
|
| + // that the deopt inputs are not overwritten by the binop result. One way
|
| // to achieve that is to declare the output register as same-as-first.
|
| - outputs[output_count++] = g.DefineSameAsFirst(node);
|
| - } else {
|
| outputs[output_count++] = g.DefineAsRegister(node);
|
| + } else {
|
| + outputs[output_count++] = g.DefineSameAsFirst(node);
|
| }
|
| +
|
| if (cont->IsSet()) {
|
| outputs[output_count++] = g.DefineAsRegister(cont->result());
|
| }
|
| @@ -486,6 +582,7 @@ void VisitBinop(InstructionSelector* selector, Node* node,
|
| DCHECK_GE(arraysize(outputs), output_count);
|
|
|
| opcode = cont->Encode(opcode);
|
| +
|
| if (cont->IsDeoptimize()) {
|
| selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
|
| cont->kind(), cont->reason(), cont->frame_state());
|
| @@ -497,12 +594,64 @@ void VisitBinop(InstructionSelector* selector, Node* node,
|
| }
|
| }
|
|
|
| -// Shared routine for multiple binary operations.
|
| -template <typename Matcher>
|
| -void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode,
|
| - OperandModes operand_mode) {
|
| - FlagsContinuation cont;
|
| - VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont);
|
| +template <class CanCombineWithLoad>
|
| +void VisitBinOp(InstructionSelector* selector, Node* node,
|
| + InstructionCode opcode, OperandModes operand_mode,
|
| + FlagsContinuation* cont,
|
| + CanCombineWithLoad canCombineWithLoad) {
|
| + S390OperandGenerator g(selector);
|
| + Int32BinopMatcher m(node);
|
| + Node* left = m.left().node();
|
| + Node* right = m.right().node();
|
| + InstructionOperand inputs[8];
|
| + size_t input_count = 0;
|
| + InstructionOperand outputs[2];
|
| + size_t output_count = 0;
|
| +
|
| + if (node->op()->HasProperty(Operator::kCommutative) &&
|
| + !g.CanBeImmediate(right, operand_mode) &&
|
| + (g.CanBeBetterLeftOperand(right))) {
|
| + std::swap(left, right);
|
| + }
|
| +
|
| + GenerateBinOpOperands(selector, node, left, right, opcode, operand_mode,
|
| + inputs, input_count, canCombineWithLoad);
|
| +
|
| + if (cont->IsBranch()) {
|
| + inputs[input_count++] = g.Label(cont->true_block());
|
| + inputs[input_count++] = g.Label(cont->false_block());
|
| + }
|
| +
|
| + if ((operand_mode & OperandMode::kAllowDistinctOps) &&
|
| + // If we can deoptimize as a result of the binop, we need to make sure
|
| + // that the deopt inputs are not overwritten by the binop result. One way
|
| + // to achieve that is to declare the output register as same-as-first.
|
| + !cont->IsDeoptimize()) {
|
| + outputs[output_count++] = g.DefineAsRegister(node);
|
| + } else {
|
| + outputs[output_count++] = g.DefineSameAsFirst(node);
|
| + }
|
| +
|
| + if (cont->IsSet()) {
|
| + outputs[output_count++] = g.DefineAsRegister(cont->result());
|
| + }
|
| +
|
| + DCHECK_NE(0u, input_count);
|
| + DCHECK_NE(0u, output_count);
|
| + DCHECK_GE(arraysize(inputs), input_count);
|
| + DCHECK_GE(arraysize(outputs), output_count);
|
| +
|
| + opcode = cont->Encode(opcode);
|
| +
|
| + if (cont->IsDeoptimize()) {
|
| + selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
|
| + cont->kind(), cont->reason(), cont->frame_state());
|
| + } else if (cont->IsTrap()) {
|
| + inputs[input_count++] = g.UseImmediate(cont->trap_id());
|
| + selector->Emit(opcode, output_count, outputs, input_count, inputs);
|
| + } else {
|
| + selector->Emit(opcode, output_count, outputs, input_count, inputs);
|
| + }
|
| }
|
|
|
| void VisitBin32op(InstructionSelector* selector, Node* node,
|
| @@ -540,56 +689,11 @@ void VisitBin32op(InstructionSelector* selector, Node* node,
|
| }
|
| #endif
|
|
|
| - // left is always register
|
| - InstructionOperand const left_input = g.UseRegister(left);
|
| - inputs[input_count++] = left_input;
|
| -
|
| - // 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
|
| - inputs[input_count++] = left_input;
|
| - // Can only be RR or RRR
|
| - operand_mode &= OperandMode::kAllowRRR;
|
| - } else if ((operand_mode & OperandMode::kAllowImmediate) &&
|
| - g.CanBeImmediate(right, operand_mode)) {
|
| - inputs[input_count++] = g.UseImmediate(right);
|
| - // Can only be RI or RRI
|
| - operand_mode &= OperandMode::kAllowImmediate;
|
| - } else if (operand_mode & OperandMode::kAllowMemoryOperand) {
|
| - NodeMatcher mright(right);
|
| - if (mright.IsLoad() && selector->CanCover(node, right) &&
|
| - SelectLoadOpcode(right) == kS390_LoadWordU32) {
|
| - AddressingMode mode =
|
| - g.GetEffectiveAddressMemoryOperand(right, inputs, &input_count);
|
| - opcode |= AddressingModeField::encode(mode);
|
| - operand_mode &= ~OperandMode::kAllowImmediate;
|
| - if (operand_mode & OperandMode::kAllowRM)
|
| - operand_mode &= ~OperandMode::kAllowDistinctOps;
|
| - } else if (operand_mode & OperandMode::kAllowRM) {
|
| - DCHECK(!(operand_mode & OperandMode::kAllowRRM));
|
| - inputs[input_count++] = g.Use(right);
|
| - // Can not be Immediate
|
| - operand_mode &=
|
| - ~OperandMode::kAllowImmediate & ~OperandMode::kAllowDistinctOps;
|
| - } else if (operand_mode & OperandMode::kAllowRRM) {
|
| - DCHECK(!(operand_mode & OperandMode::kAllowRM));
|
| - inputs[input_count++] = g.Use(right);
|
| - // Can not be Immediate
|
| - operand_mode &= ~OperandMode::kAllowImmediate;
|
| - } else {
|
| - UNREACHABLE();
|
| - }
|
| - } else {
|
| - inputs[input_count++] = g.UseRegister(right);
|
| - // Can only be RR or RRR
|
| - operand_mode &= OperandMode::kAllowRRR;
|
| - }
|
| + GenerateBinOpOperands(selector, node, left, right, opcode, operand_mode,
|
| + inputs, input_count, [](ArchOpcode opcode) {
|
| + return opcode == kS390_LoadWordU32 ||
|
| + opcode == kS390_LoadWordS32;
|
| + });
|
|
|
| bool doZeroExt =
|
| AutoZeroExtendsWord32ToWord64(node) || !ZeroExtendsWord32ToWord64(left);
|
| @@ -640,6 +744,7 @@ void VisitBin32op(InstructionSelector* selector, Node* node, ArchOpcode opcode,
|
| FlagsContinuation cont;
|
| VisitBin32op(selector, node, opcode, operand_mode, &cont);
|
| }
|
| +#undef VISIT_OP_LIST
|
|
|
| } // namespace
|
|
|
| @@ -908,9 +1013,22 @@ static inline bool IsContiguousMask64(uint64_t value, int* mb, int* me) {
|
| }
|
| #endif
|
|
|
| -void InstructionSelector::VisitWord32And(Node* node) {
|
| - VisitBin32op(this, node, kS390_And32, AndOperandMode);
|
| -}
|
| +// TODO(john.yan): use list to simplify general instructions
|
| +#define WORD32_BIN_OP_LIST(V) \
|
| + /* V(name, ArchOpcode, OperandModes) */ \
|
| + V(Word32And, kS390_And32, And32OperandMode) \
|
| + V(Word32Or, kS390_Or32, Or32OperandMode) \
|
| + V(Word32Xor, kS390_Xor32, Xor32OperandMode) \
|
| + V(Word32Shl, kS390_ShiftLeft32, Shift32OperandMode) \
|
| + V(Word32Shr, kS390_ShiftRight32, Shift32OperandMode)
|
| +
|
| +#define VISITOR(name, op, mode) \
|
| + void InstructionSelector::Visit##name(Node* node) { \
|
| + VisitBin32op(this, node, op, mode); \
|
| + }
|
| +WORD32_BIN_OP_LIST(VISITOR);
|
| +#undef VISITOR
|
| +#undef WORD32_BIN_OP_LIST
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitWord64And(Node* node) {
|
| @@ -954,46 +1072,24 @@ void InstructionSelector::VisitWord64And(Node* node) {
|
| opcode = kS390_RotLeftAndClear64;
|
| mask = mb;
|
| }
|
| - if (match) {
|
| + if (match && CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
|
| Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
|
| g.TempImmediate(sh), g.TempImmediate(mask));
|
| return;
|
| }
|
| }
|
| }
|
| - VisitBinop<Int64BinopMatcher>(this, node, kS390_And64,
|
| - OperandMode::kUint32Imm);
|
| -}
|
| -#endif
|
| -
|
| -void InstructionSelector::VisitWord32Or(Node* node) {
|
| - VisitBin32op(this, node, kS390_Or32, OrOperandMode);
|
| + VisitWord64BinOp(this, node, kS390_And64, And64OperandMode);
|
| }
|
|
|
| -#if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitWord64Or(Node* node) {
|
| - Int64BinopMatcher m(node);
|
| - VisitBinop<Int64BinopMatcher>(this, node, kS390_Or64,
|
| - OperandMode::kUint32Imm);
|
| -}
|
| -#endif
|
| -
|
| -void InstructionSelector::VisitWord32Xor(Node* node) {
|
| - VisitBin32op(this, node, kS390_Xor32, XorOperandMode);
|
| + VisitWord64BinOp(this, node, kS390_Or64, Or64OperandMode);
|
| }
|
|
|
| -#if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitWord64Xor(Node* node) {
|
| - VisitBinop<Int64BinopMatcher>(this, node, kS390_Xor64,
|
| - OperandMode::kUint32Imm);
|
| -}
|
| -#endif
|
| -
|
| -void InstructionSelector::VisitWord32Shl(Node* node) {
|
| - VisitBin32op(this, node, kS390_ShiftLeft32, ShiftOperandMode);
|
| + VisitWord64BinOp(this, node, kS390_Xor64, Xor64OperandMode);
|
| }
|
|
|
| -#if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitWord64Shl(Node* node) {
|
| S390OperandGenerator g(this);
|
| Int64BinopMatcher m(node);
|
| @@ -1024,7 +1120,7 @@ void InstructionSelector::VisitWord64Shl(Node* node) {
|
| opcode = kS390_RotLeftAndClear64;
|
| mask = mb;
|
| }
|
| - if (match) {
|
| + if (match && CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
|
| Emit(opcode, g.DefineAsRegister(node),
|
| g.UseRegister(mleft.left().node()), g.TempImmediate(sh),
|
| g.TempImmediate(mask));
|
| @@ -1033,15 +1129,9 @@ void InstructionSelector::VisitWord64Shl(Node* node) {
|
| }
|
| }
|
| }
|
| - VisitRRO(this, kS390_ShiftLeft64, node, OperandMode::kShift64Imm);
|
| -}
|
| -#endif
|
| -
|
| -void InstructionSelector::VisitWord32Shr(Node* node) {
|
| - VisitBin32op(this, node, kS390_ShiftRight32, ShiftOperandMode);
|
| + VisitWord64BinOp(this, node, kS390_ShiftLeft64, Shift64OperandMode);
|
| }
|
|
|
| -#if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitWord64Shr(Node* node) {
|
| S390OperandGenerator g(this);
|
| Int64BinopMatcher m(node);
|
| @@ -1077,7 +1167,7 @@ void InstructionSelector::VisitWord64Shr(Node* node) {
|
| }
|
| }
|
| }
|
| - VisitRRO(this, kS390_ShiftRight64, node, OperandMode::kShift64Imm);
|
| + VisitWord64BinOp(this, node, kS390_ShiftRight64, Shift64OperandMode);
|
| }
|
| #endif
|
|
|
| @@ -1101,7 +1191,7 @@ void InstructionSelector::VisitWord32Sar(Node* node) {
|
| return;
|
| }
|
| }
|
| - VisitBin32op(this, node, kS390_ShiftRightArith32, ShiftOperandMode);
|
| + VisitBin32op(this, node, kS390_ShiftRightArith32, Shift32OperandMode);
|
| }
|
|
|
| #if !V8_TARGET_ARCH_S390X
|
| @@ -1214,7 +1304,7 @@ void InstructionSelector::VisitWord32PairSar(Node* node) {
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitWord64Sar(Node* node) {
|
| - VisitRRO(this, kS390_ShiftRightArith64, node, OperandMode::kShift64Imm);
|
| + VisitWord64BinOp(this, node, kS390_ShiftRightArith64, Shift64OperandMode);
|
| }
|
| #endif
|
|
|
| @@ -1227,7 +1317,7 @@ void InstructionSelector::VisitWord32Ror(Node* node) {
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitWord64Ror(Node* node) {
|
| - VisitRRO(this, kS390_RotRight64, node, OperandMode::kShift64Imm);
|
| + VisitWord64BinOp(this, node, kS390_RotRight64, Shift64OperandMode);
|
| }
|
| #endif
|
|
|
| @@ -1300,8 +1390,7 @@ void InstructionSelector::VisitInt32Add(Node* node) {
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitInt64Add(Node* node) {
|
| - VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64,
|
| - OperandMode::kInt32Imm);
|
| + VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode);
|
| }
|
| #endif
|
|
|
| @@ -1326,39 +1415,11 @@ void InstructionSelector::VisitInt64Sub(Node* node) {
|
| Emit(kS390_Neg64, g.DefineAsRegister(node),
|
| g.UseRegister(m.right().node()));
|
| } else {
|
| - VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64,
|
| - OperandMode::kInt32Imm_Negate);
|
| + VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode);
|
| }
|
| }
|
| #endif
|
|
|
| -namespace {
|
| -
|
| -void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
|
| - InstructionOperand left, InstructionOperand right,
|
| - FlagsContinuation* cont);
|
| -
|
| -#if V8_TARGET_ARCH_S390X
|
| -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, OperandMode::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));
|
| - }
|
| -}
|
| -#endif
|
| -
|
| -} // namespace
|
| -
|
| void InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
|
| if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
| FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
|
| @@ -1403,7 +1464,7 @@ void InstructionSelector::VisitInt64Mul(Node* node) {
|
| g.UseImmediate(power));
|
| return;
|
| }
|
| - VisitMul(this, node, kS390_Mul64);
|
| + VisitWord64BinOp(this, node, kS390_Mul64, MulOperandMode);
|
| }
|
| #endif
|
|
|
| @@ -1424,7 +1485,8 @@ void InstructionSelector::VisitInt32Div(Node* node) {
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitInt64Div(Node* node) {
|
| - VisitRRR(this, kS390_Div64, node);
|
| + VisitWord64BinOp(this, node, kS390_Div64,
|
| + OperandMode::kAllowRRM | OperandMode::kAllowRRR);
|
| }
|
| #endif
|
|
|
| @@ -1435,7 +1497,8 @@ void InstructionSelector::VisitUint32Div(Node* node) {
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitUint64Div(Node* node) {
|
| - VisitRRR(this, kS390_DivU64, node);
|
| + VisitWord64BinOp(this, node, kS390_DivU64,
|
| + OperandMode::kAllowRRM | OperandMode::kAllowRRR);
|
| }
|
| #endif
|
|
|
| @@ -1446,7 +1509,8 @@ void InstructionSelector::VisitInt32Mod(Node* node) {
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitInt64Mod(Node* node) {
|
| - VisitRRR(this, kS390_Mod64, node);
|
| + VisitWord64BinOp(this, node, kS390_Mod64,
|
| + OperandMode::kAllowRRM | OperandMode::kAllowRRR);
|
| }
|
| #endif
|
|
|
| @@ -1457,13 +1521,69 @@ void InstructionSelector::VisitUint32Mod(Node* node) {
|
|
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitUint64Mod(Node* node) {
|
| - VisitRRR(this, kS390_ModU64, node);
|
| + VisitWord64BinOp(this, node, kS390_ModU64,
|
| + OperandMode::kAllowRRM | OperandMode::kAllowRRR);
|
| }
|
| #endif
|
|
|
| -void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) {
|
| - VisitRR(this, kS390_Float32ToDouble, node);
|
| -}
|
| +// TODO(john.yan): place kAllowRM where available
|
| +#define VISIT_FLOAT_UNARY_OP_LIST(V) \
|
| + V(Float32, ChangeFloat32ToFloat64, kS390_Float32ToDouble, \
|
| + OperandMode::kAllowRM) \
|
| + V(Float32, BitcastFloat32ToInt32, kS390_BitcastFloat32ToInt32, \
|
| + OperandMode::kNone) \
|
| + V(Float64, TruncateFloat64ToFloat32, kS390_DoubleToFloat32, \
|
| + OperandMode::kNone) \
|
| + V(Float64, TruncateFloat64ToWord32, kArchTruncateDoubleToI, \
|
| + OperandMode::kNone) \
|
| + V(Float64, RoundFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone) \
|
| + V(Float32, TruncateFloat32ToInt32, kS390_Float32ToInt32, OperandMode::kNone) \
|
| + V(Float32, TruncateFloat32ToUint32, kS390_Float32ToUint32, \
|
| + OperandMode::kNone) \
|
| + V(Float64, ChangeFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone) \
|
| + V(Float64, ChangeFloat64ToUint32, kS390_DoubleToUint32, OperandMode::kNone) \
|
| + V(Float64, TruncateFloat64ToUint32, kS390_DoubleToUint32, \
|
| + OperandMode::kNone) \
|
| + V(Float64, Float64SilenceNaN, kS390_Float64SilenceNaN, OperandMode::kNone) \
|
| + V(Float32, Float32Abs, kS390_AbsFloat, OperandMode::kNone) \
|
| + V(Float64, Float64Abs, kS390_AbsDouble, OperandMode::kNone) \
|
| + V(Float32, Float32Sqrt, kS390_SqrtFloat, OperandMode::kNone) \
|
| + V(Float64, Float64Sqrt, kS390_SqrtDouble, OperandMode::kNone) \
|
| + V(Float32, Float32RoundDown, kS390_FloorFloat, OperandMode::kNone) \
|
| + V(Float64, Float64RoundDown, kS390_FloorDouble, OperandMode::kNone) \
|
| + V(Float32, Float32RoundUp, kS390_CeilFloat, OperandMode::kNone) \
|
| + V(Float64, Float64RoundUp, kS390_CeilDouble, OperandMode::kNone) \
|
| + V(Float32, Float32RoundTruncate, kS390_TruncateFloat, OperandMode::kNone) \
|
| + V(Float64, Float64RoundTruncate, kS390_TruncateDouble, OperandMode::kNone) \
|
| + V(Float64, Float64RoundTiesAway, kS390_RoundDouble, OperandMode::kNone) \
|
| + V(Float32, Float32Neg, kS390_NegFloat, OperandMode::kNone) \
|
| + V(Float64, Float64Neg, kS390_NegDouble, OperandMode::kNone)
|
| +
|
| +#define VISIT_WORD64_UNARY_OP_LIST(V) \
|
| + V(Word64, TruncateInt64ToInt32, kS390_Int64ToInt32, OperandMode::kNone) \
|
| + V(Word64, RoundInt64ToFloat32, kS390_Int64ToFloat32, OperandMode::kNone) \
|
| + V(Word64, RoundInt64ToFloat64, kS390_Int64ToDouble, OperandMode::kNone) \
|
| + V(Word64, RoundUint64ToFloat32, kS390_Uint64ToFloat32, OperandMode::kNone) \
|
| + V(Word64, RoundUint64ToFloat64, kS390_Uint64ToDouble, OperandMode::kNone) \
|
| + V(Word64, BitcastInt64ToFloat64, kS390_BitcastInt64ToDouble, \
|
| + OperandMode::kNone) \
|
| + V(Float64, BitcastFloat64ToInt64, kS390_BitcastDoubleToInt64, \
|
| + OperandMode::kNone)
|
| +
|
| +#define DECLARE_UNARY_OP(type, name, op, mode) \
|
| + void InstructionSelector::Visit##name(Node* node) { \
|
| + Visit##type##UnaryOp(this, node, op, mode); \
|
| + }
|
| +
|
| +VISIT_FLOAT_UNARY_OP_LIST(DECLARE_UNARY_OP);
|
| +
|
| +#if V8_TARGET_ARCH_S390X
|
| +VISIT_WORD64_UNARY_OP_LIST(DECLARE_UNARY_OP)
|
| +#endif
|
| +
|
| +#undef DECLARE_UNARY_OP
|
| +#undef VISIT_WORD64_UNARY_OP_LIST
|
| +#undef VISIT_FLOAT_UNARY_OP_LIST
|
|
|
| void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
|
| VisitRR(this, kS390_Int32ToFloat32, node);
|
| @@ -1481,18 +1601,6 @@ void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
|
| VisitRR(this, kS390_Uint32ToDouble, node);
|
| }
|
|
|
| -void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
|
| - VisitRR(this, kS390_DoubleToInt32, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
|
| - VisitRR(this, kS390_DoubleToUint32, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitTruncateFloat64ToUint32(Node* node) {
|
| - VisitRR(this, kS390_DoubleToUint32, node);
|
| -}
|
| -
|
| #if V8_TARGET_ARCH_S390X
|
| void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
|
| VisitTryTruncateDouble(this, kS390_Float32ToInt64, node);
|
| @@ -1527,102 +1635,43 @@ void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
|
| }
|
| #endif
|
|
|
| -void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
|
| - VisitRR(this, kS390_DoubleToFloat32, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
|
| - VisitRR(this, kArchTruncateDoubleToI, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
|
| - VisitRR(this, kS390_DoubleToInt32, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
|
| - VisitRR(this, kS390_Float32ToInt32, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitTruncateFloat32ToUint32(Node* node) {
|
| - VisitRR(this, kS390_Float32ToUint32, node);
|
| -}
|
| -
|
| -#if V8_TARGET_ARCH_S390X
|
| -void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
|
| - // TODO(mbrandy): inspect input to see if nop is appropriate.
|
| - VisitRR(this, kS390_Int64ToInt32, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitRoundInt64ToFloat32(Node* node) {
|
| - VisitRR(this, kS390_Int64ToFloat32, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
|
| - VisitRR(this, kS390_Int64ToDouble, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
|
| - VisitRR(this, kS390_Uint64ToFloat32, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
|
| - VisitRR(this, kS390_Uint64ToDouble, node);
|
| -}
|
| -#endif
|
| -
|
| -void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
|
| - VisitRR(this, kS390_BitcastFloat32ToInt32, node);
|
| -}
|
| -
|
| -#if V8_TARGET_ARCH_S390X
|
| -void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
|
| - VisitRR(this, kS390_BitcastDoubleToInt64, node);
|
| -}
|
| -#endif
|
| -
|
| void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
|
| VisitRR(this, kS390_BitcastInt32ToFloat32, node);
|
| }
|
|
|
| -#if V8_TARGET_ARCH_S390X
|
| -void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
|
| - VisitRR(this, kS390_BitcastInt64ToDouble, node);
|
| -}
|
| -#endif
|
| -
|
| void InstructionSelector::VisitFloat32Add(Node* node) {
|
| - VisitRRR(this, kS390_AddFloat, node);
|
| + return VisitFloat32BinOp(this, node, kS390_AddFloat, OperandMode::kAllowRM);
|
| }
|
|
|
| void InstructionSelector::VisitFloat64Add(Node* node) {
|
| // TODO(mbrandy): detect multiply-add
|
| - VisitRRR(this, kS390_AddDouble, node);
|
| + return VisitFloat64BinOp(this, node, kS390_AddDouble, OperandMode::kAllowRM);
|
| }
|
|
|
| void InstructionSelector::VisitFloat32Sub(Node* node) {
|
| - VisitRRR(this, kS390_SubFloat, node);
|
| + return VisitFloat32BinOp(this, node, kS390_SubFloat, OperandMode::kAllowRM);
|
| }
|
|
|
| void InstructionSelector::VisitFloat64Sub(Node* node) {
|
| // TODO(mbrandy): detect multiply-subtract
|
| - VisitRRR(this, kS390_SubDouble, node);
|
| + return VisitFloat64BinOp(this, node, kS390_SubDouble, OperandMode::kAllowRM);
|
| }
|
|
|
| void InstructionSelector::VisitFloat32Mul(Node* node) {
|
| - VisitRRR(this, kS390_MulFloat, node);
|
| + return VisitFloat32BinOp(this, node, kS390_MulFloat, OperandMode::kAllowRM);
|
| }
|
|
|
| void InstructionSelector::VisitFloat64Mul(Node* node) {
|
| // TODO(mbrandy): detect negate
|
| - VisitRRR(this, kS390_MulDouble, node);
|
| + return VisitFloat64BinOp(this, node, kS390_MulDouble, OperandMode::kAllowRM);
|
| }
|
|
|
| void InstructionSelector::VisitFloat32Div(Node* node) {
|
| - VisitRRR(this, kS390_DivFloat, node);
|
| + return VisitFloat32BinOp(this, node, kS390_DivFloat, OperandMode::kAllowRM);
|
| }
|
|
|
| void InstructionSelector::VisitFloat64Div(Node* node) {
|
| - VisitRRR(this, kS390_DivDouble, node);
|
| + return VisitFloat64BinOp(this, node, kS390_DivDouble, OperandMode::kAllowRM);
|
| }
|
|
|
| void InstructionSelector::VisitFloat64Mod(Node* node) {
|
| @@ -1633,35 +1682,19 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
|
| }
|
|
|
| void InstructionSelector::VisitFloat32Max(Node* node) {
|
| - VisitRRR(this, kS390_MaxFloat, node);
|
| + return VisitFloat32BinOp(this, node, kS390_MaxFloat, OperandMode::kNone);
|
| }
|
|
|
| void InstructionSelector::VisitFloat64Max(Node* node) {
|
| - VisitRRR(this, kS390_MaxDouble, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
|
| - VisitRR(this, kS390_Float64SilenceNaN, node);
|
| + return VisitFloat64BinOp(this, node, kS390_MaxDouble, OperandMode::kNone);
|
| }
|
|
|
| void InstructionSelector::VisitFloat32Min(Node* node) {
|
| - VisitRRR(this, kS390_MinFloat, node);
|
| + return VisitFloat32BinOp(this, node, kS390_MinFloat, OperandMode::kNone);
|
| }
|
|
|
| void InstructionSelector::VisitFloat64Min(Node* node) {
|
| - VisitRRR(this, kS390_MinDouble, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat32Abs(Node* node) {
|
| - VisitRR(this, kS390_AbsFloat, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat64Abs(Node* node) {
|
| - VisitRR(this, kS390_AbsDouble, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat32Sqrt(Node* node) {
|
| - VisitRR(this, kS390_SqrtFloat, node);
|
| + return VisitFloat64BinOp(this, node, kS390_MinDouble, OperandMode::kNone);
|
| }
|
|
|
| void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
|
| @@ -1679,38 +1712,6 @@ void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
|
| ->MarkAsCall();
|
| }
|
|
|
| -void InstructionSelector::VisitFloat64Sqrt(Node* node) {
|
| - VisitRR(this, kS390_SqrtDouble, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat32RoundDown(Node* node) {
|
| - VisitRR(this, kS390_FloorFloat, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat64RoundDown(Node* node) {
|
| - VisitRR(this, kS390_FloorDouble, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat32RoundUp(Node* node) {
|
| - VisitRR(this, kS390_CeilFloat, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat64RoundUp(Node* node) {
|
| - VisitRR(this, kS390_CeilDouble, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat32RoundTruncate(Node* node) {
|
| - VisitRR(this, kS390_TruncateFloat, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
|
| - VisitRR(this, kS390_TruncateDouble, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
|
| - VisitRR(this, kS390_RoundDouble, node);
|
| -}
|
| -
|
| void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
|
| UNREACHABLE();
|
| }
|
| @@ -1719,14 +1720,6 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
|
| UNREACHABLE();
|
| }
|
|
|
| -void InstructionSelector::VisitFloat32Neg(Node* node) {
|
| - VisitRR(this, kS390_NegFloat, node);
|
| -}
|
| -
|
| -void InstructionSelector::VisitFloat64Neg(Node* node) {
|
| - VisitRR(this, kS390_NegDouble, node);
|
| -}
|
| -
|
| void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
|
| OperandModes mode = AddOperandMode;
|
| if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
| @@ -1751,23 +1744,17 @@ void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
|
| void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
|
| if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
| FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
| - return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64,
|
| - OperandMode::kInt32Imm, &cont);
|
| + return VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode, &cont);
|
| }
|
| - FlagsContinuation cont;
|
| - VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, OperandMode::kInt32Imm,
|
| - &cont);
|
| + VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode);
|
| }
|
|
|
| void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
|
| if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
| FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
| - return VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64,
|
| - OperandMode::kInt32Imm_Negate, &cont);
|
| + return VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode, &cont);
|
| }
|
| - FlagsContinuation cont;
|
| - VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64,
|
| - OperandMode::kInt32Imm_Negate, &cont);
|
| + VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode);
|
| }
|
| #endif
|
|
|
| @@ -2129,13 +2116,12 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
|
| #if V8_TARGET_ARCH_S390X
|
| case IrOpcode::kInt64AddWithOverflow:
|
| cont->OverwriteAndNegateIfEqual(kOverflow);
|
| - return VisitBinop<Int64BinopMatcher>(
|
| - selector, node, kS390_Add64, OperandMode::kInt32Imm, cont);
|
| + return VisitWord64BinOp(selector, node, kS390_Add64,
|
| + AddOperandMode, cont);
|
| case IrOpcode::kInt64SubWithOverflow:
|
| cont->OverwriteAndNegateIfEqual(kOverflow);
|
| - return VisitBinop<Int64BinopMatcher>(
|
| - selector, node, kS390_Sub64, OperandMode::kInt32Imm_Negate,
|
| - cont);
|
| + return VisitWord64BinOp(selector, node, kS390_Sub64,
|
| + SubOperandMode, cont);
|
| #endif
|
| default:
|
| break;
|
| @@ -2165,9 +2151,15 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
|
| // can't handle overflow case.
|
| break;
|
| case IrOpcode::kWord32Or:
|
| - return VisitBin32op(selector, value, kS390_Or32, OrOperandMode, cont);
|
| + if (fc == kNotEqual || fc == kEqual)
|
| + return VisitBin32op(selector, value, kS390_Or32, Or32OperandMode,
|
| + cont);
|
| + break;
|
| case IrOpcode::kWord32Xor:
|
| - return VisitBin32op(selector, value, kS390_Xor32, XorOperandMode, cont);
|
| + if (fc == kNotEqual || fc == kEqual)
|
| + return VisitBin32op(selector, value, kS390_Xor32, Xor32OperandMode,
|
| + cont);
|
| + break;
|
| case IrOpcode::kWord32Sar:
|
| case IrOpcode::kWord32Shl:
|
| case IrOpcode::kWord32Shr:
|
| @@ -2185,10 +2177,14 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
|
| // can't handle overflow case.
|
| break;
|
| case IrOpcode::kWord64Or:
|
| - // TODO(john.yan): need to handle
|
| + if (fc == kNotEqual || fc == kEqual)
|
| + return VisitWord64BinOp(selector, value, kS390_Or64, Or64OperandMode,
|
| + cont);
|
| break;
|
| case IrOpcode::kWord64Xor:
|
| - // TODO(john.yan): need to handle
|
| + if (fc == kNotEqual || fc == kEqual)
|
| + return VisitWord64BinOp(selector, value, kS390_Xor64,
|
| + Xor64OperandMode, cont);
|
| break;
|
| case IrOpcode::kWord64Sar:
|
| case IrOpcode::kWord64Shl:
|
|
|