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 2fd3f78f593ea373e8018e06cbf3eb95ff822f99..90a3d3e2f382b9ae910d41e397de178f2d02f364 100644 |
--- a/src/compiler/s390/instruction-selector-s390.cc |
+++ b/src/compiler/s390/instruction-selector-s390.cc |
@@ -13,12 +13,12 @@ namespace internal { |
namespace compiler { |
enum ImmediateMode { |
- kInt16Imm, |
- kInt16Imm_Unsigned, |
- kInt16Imm_Negate, |
- kInt16Imm_4ByteAligned, |
kShift32Imm, |
kShift64Imm, |
+ kInt32Imm, |
+ kInt32Imm_Negate, |
+ kUint32Imm, |
+ kInt20Imm, |
kNoImmediate |
}; |
@@ -48,23 +48,90 @@ class S390OperandGenerator final : public OperandGenerator { |
bool CanBeImmediate(int64_t value, ImmediateMode mode) { |
switch (mode) { |
- case kInt16Imm: |
- return is_int16(value); |
- case kInt16Imm_Unsigned: |
- return is_uint16(value); |
- case kInt16Imm_Negate: |
- return is_int16(-value); |
- case kInt16Imm_4ByteAligned: |
- return is_int16(value) && !(value & 3); |
case kShift32Imm: |
return 0 <= value && value < 32; |
case kShift64Imm: |
return 0 <= value && value < 64; |
+ case kInt32Imm: |
+ return is_int32(value); |
+ case kInt32Imm_Negate: |
+ return is_int32(-value); |
+ case kUint32Imm: |
+ return is_uint32(value); |
+ case kInt20Imm: |
+ return is_int20(value); |
case kNoImmediate: |
return false; |
} |
return false; |
} |
+ |
+ AddressingMode GenerateMemoryOperandInputs(Node* index, Node* base, |
+ Node* displacement, |
+ DisplacementMode displacement_mode, |
+ InstructionOperand inputs[], |
+ size_t* input_count) { |
+ AddressingMode mode = kMode_MRI; |
+ if (base != nullptr) { |
+ inputs[(*input_count)++] = UseRegister(base); |
+ if (index != nullptr) { |
+ inputs[(*input_count)++] = UseRegister(index); |
+ if (displacement != nullptr) { |
+ inputs[(*input_count)++] = displacement_mode |
+ ? UseNegatedImmediate(displacement) |
+ : UseImmediate(displacement); |
+ mode = kMode_MRRI; |
+ } else { |
+ mode = kMode_MRR; |
+ } |
+ } else { |
+ if (displacement == nullptr) { |
+ mode = kMode_MR; |
+ } else { |
+ inputs[(*input_count)++] = displacement_mode == kNegativeDisplacement |
+ ? UseNegatedImmediate(displacement) |
+ : UseImmediate(displacement); |
+ mode = kMode_MRI; |
+ } |
+ } |
+ } else { |
+ DCHECK_NOT_NULL(index); |
+ inputs[(*input_count)++] = UseRegister(index); |
+ if (displacement != nullptr) { |
+ inputs[(*input_count)++] = displacement_mode == kNegativeDisplacement |
+ ? UseNegatedImmediate(displacement) |
+ : UseImmediate(displacement); |
+ mode = kMode_MRI; |
+ } else { |
+ mode = kMode_MR; |
+ } |
+ } |
+ return mode; |
+ } |
+ |
+ AddressingMode GetEffectiveAddressMemoryOperand(Node* operand, |
+ InstructionOperand inputs[], |
+ size_t* input_count) { |
+#if V8_TARGET_ARCH_S390X |
+ BaseWithIndexAndDisplacement64Matcher m(operand, |
+ AddressOption::kAllowInputSwap); |
+#else |
+ BaseWithIndexAndDisplacement32Matcher m(operand, |
+ AddressOption::kAllowInputSwap); |
+#endif |
+ DCHECK(m.matches()); |
+ if ((m.displacement() == nullptr || |
+ CanBeImmediate(m.displacement(), kInt20Imm))) { |
+ DCHECK(m.scale() == 0); |
+ return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), |
+ m.displacement_mode(), inputs, |
+ input_count); |
+ } else { |
+ inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); |
+ inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); |
+ return kMode_MRR; |
+ } |
+ } |
}; |
namespace { |
@@ -167,10 +234,7 @@ void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
void InstructionSelector::VisitLoad(Node* node) { |
LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
S390OperandGenerator g(this); |
- Node* base = node->InputAt(0); |
- Node* offset = node->InputAt(1); |
ArchOpcode opcode = kArchNop; |
- ImmediateMode mode = kInt16Imm; |
switch (load_rep.representation()) { |
case MachineRepresentation::kFloat32: |
opcode = kS390_LoadFloat32; |
@@ -195,7 +259,6 @@ void InstructionSelector::VisitLoad(Node* node) { |
case MachineRepresentation::kTagged: // Fall through. |
case MachineRepresentation::kWord64: |
opcode = kS390_LoadWord64; |
- mode = kInt16Imm_4ByteAligned; |
break; |
#else |
case MachineRepresentation::kWord64: // Fall through. |
@@ -205,16 +268,14 @@ void InstructionSelector::VisitLoad(Node* node) { |
UNREACHABLE(); |
return; |
} |
- if (g.CanBeImmediate(offset, mode)) { |
- Emit(opcode | AddressingModeField::encode(kMode_MRI), |
- g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(offset)); |
- } else if (g.CanBeImmediate(base, mode)) { |
- Emit(opcode | AddressingModeField::encode(kMode_MRI), |
- g.DefineAsRegister(node), g.UseRegister(offset), g.UseImmediate(base)); |
- } else { |
- Emit(opcode | AddressingModeField::encode(kMode_MRR), |
- g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(offset)); |
- } |
+ InstructionOperand outputs[1]; |
+ outputs[0] = g.DefineAsRegister(node); |
+ InstructionOperand inputs[3]; |
+ size_t input_count = 0; |
+ AddressingMode mode = |
+ g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
+ InstructionCode code = opcode | AddressingModeField::encode(mode); |
+ Emit(code, 1, outputs, input_count, inputs); |
} |
void InstructionSelector::VisitStore(Node* node) { |
@@ -235,11 +296,7 @@ void InstructionSelector::VisitStore(Node* node) { |
inputs[input_count++] = g.UseUniqueRegister(base); |
// OutOfLineRecordWrite uses the offset in an 'AddP' instruction as well as |
// for the store itself, so we must check compatibility with both. |
- if (g.CanBeImmediate(offset, kInt16Imm) |
-#if V8_TARGET_ARCH_S390X |
- && g.CanBeImmediate(offset, kInt16Imm_4ByteAligned) |
-#endif |
- ) { |
+ if (g.CanBeImmediate(offset, kInt20Imm)) { |
inputs[input_count++] = g.UseImmediate(offset); |
addressing_mode = kMode_MRI; |
} else { |
@@ -270,7 +327,6 @@ void InstructionSelector::VisitStore(Node* node) { |
Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); |
} else { |
ArchOpcode opcode = kArchNop; |
- ImmediateMode mode = kInt16Imm; |
NodeMatcher m(value); |
switch (rep) { |
case MachineRepresentation::kFloat32: |
@@ -300,7 +356,6 @@ void InstructionSelector::VisitStore(Node* node) { |
case MachineRepresentation::kTagged: // Fall through. |
case MachineRepresentation::kWord64: |
opcode = kS390_StoreWord64; |
- mode = kInt16Imm_4ByteAligned; |
if (m.IsWord64ReverseBytes()) { |
opcode = kS390_StoreReverse64; |
value = value->InputAt(0); |
@@ -314,16 +369,16 @@ void InstructionSelector::VisitStore(Node* node) { |
UNREACHABLE(); |
return; |
} |
- if (g.CanBeImmediate(offset, mode)) { |
- Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
- g.UseRegister(base), g.UseImmediate(offset), g.UseRegister(value)); |
- } else if (g.CanBeImmediate(base, mode)) { |
- Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
- g.UseRegister(offset), g.UseImmediate(base), g.UseRegister(value)); |
- } else { |
- Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(), |
- g.UseRegister(base), g.UseRegister(offset), g.UseRegister(value)); |
- } |
+ InstructionOperand inputs[4]; |
+ size_t input_count = 0; |
+ AddressingMode addressing_mode = |
+ g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
+ InstructionCode code = |
+ opcode | AddressingModeField::encode(addressing_mode); |
+ InstructionOperand value_operand = g.UseRegister(value); |
+ inputs[input_count++] = value_operand; |
+ Emit(code, 0, static_cast<InstructionOperand*>(nullptr), input_count, |
+ inputs); |
} |
} |
@@ -374,7 +429,7 @@ void InstructionSelector::VisitCheckedLoad(Node* node) { |
AddressingMode addressingMode = kMode_MRR; |
Emit(opcode | AddressingModeField::encode(addressingMode), |
g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(offset), |
- g.UseOperand(length, kInt16Imm_Unsigned)); |
+ g.UseOperand(length, kUint32Imm)); |
} |
void InstructionSelector::VisitCheckedStore(Node* node) { |
@@ -419,7 +474,7 @@ void InstructionSelector::VisitCheckedStore(Node* node) { |
AddressingMode addressingMode = kMode_MRR; |
Emit(opcode | AddressingModeField::encode(addressingMode), g.NoOutput(), |
g.UseRegister(base), g.UseRegister(offset), |
- g.UseOperand(length, kInt16Imm_Unsigned), g.UseRegister(value)); |
+ g.UseOperand(length, kUint32Imm), g.UseRegister(value)); |
} |
static inline bool IsContiguousMask32(uint32_t value, int* mb, int* me) { |
@@ -477,7 +532,7 @@ void InstructionSelector::VisitWord32And(Node* node) { |
return; |
} |
} |
- VisitBinop<Int32BinopMatcher>(this, node, kS390_And32, kInt16Imm_Unsigned); |
+ VisitBinop<Int32BinopMatcher>(this, node, kS390_And32, kUint32Imm); |
} |
#if V8_TARGET_ARCH_S390X |
@@ -529,19 +584,19 @@ void InstructionSelector::VisitWord64And(Node* node) { |
} |
} |
} |
- VisitBinop<Int64BinopMatcher>(this, node, kS390_And64, kInt16Imm_Unsigned); |
+ VisitBinop<Int64BinopMatcher>(this, node, kS390_And64, kUint32Imm); |
} |
#endif |
void InstructionSelector::VisitWord32Or(Node* node) { |
Int32BinopMatcher m(node); |
- VisitBinop<Int32BinopMatcher>(this, node, kS390_Or32, kInt16Imm_Unsigned); |
+ VisitBinop<Int32BinopMatcher>(this, node, kS390_Or32, kUint32Imm); |
} |
#if V8_TARGET_ARCH_S390X |
void InstructionSelector::VisitWord64Or(Node* node) { |
Int64BinopMatcher m(node); |
- VisitBinop<Int64BinopMatcher>(this, node, kS390_Or64, kInt16Imm_Unsigned); |
+ VisitBinop<Int64BinopMatcher>(this, node, kS390_Or64, kUint32Imm); |
} |
#endif |
@@ -551,7 +606,7 @@ void InstructionSelector::VisitWord32Xor(Node* node) { |
if (m.right().Is(-1)) { |
Emit(kS390_Not32, g.DefineAsRegister(node), g.UseRegister(m.left().node())); |
} else { |
- VisitBinop<Int32BinopMatcher>(this, node, kS390_Xor32, kInt16Imm_Unsigned); |
+ VisitBinop<Int32BinopMatcher>(this, node, kS390_Xor32, kUint32Imm); |
} |
} |
@@ -562,7 +617,7 @@ void InstructionSelector::VisitWord64Xor(Node* node) { |
if (m.right().Is(-1)) { |
Emit(kS390_Not64, g.DefineAsRegister(node), g.UseRegister(m.left().node())); |
} else { |
- VisitBinop<Int64BinopMatcher>(this, node, kS390_Xor64, kInt16Imm_Unsigned); |
+ VisitBinop<Int64BinopMatcher>(this, node, kS390_Xor64, kUint32Imm); |
} |
} |
#endif |
@@ -874,12 +929,12 @@ void InstructionSelector::VisitWord32ReverseBytes(Node* node) { |
} |
void InstructionSelector::VisitInt32Add(Node* node) { |
- VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt16Imm); |
+ VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm); |
} |
#if V8_TARGET_ARCH_S390X |
void InstructionSelector::VisitInt64Add(Node* node) { |
- VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt16Imm); |
+ VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm); |
} |
#endif |
@@ -890,7 +945,7 @@ void InstructionSelector::VisitInt32Sub(Node* node) { |
Emit(kS390_Neg32, g.DefineAsRegister(node), |
g.UseRegister(m.right().node())); |
} else { |
- VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt16Imm_Negate); |
+ VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt32Imm_Negate); |
} |
} |
@@ -902,7 +957,7 @@ void InstructionSelector::VisitInt64Sub(Node* node) { |
Emit(kS390_Neg64, g.DefineAsRegister(node), |
g.UseRegister(m.right().node())); |
} else { |
- VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt16Imm_Negate); |
+ VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt32Imm_Negate); |
} |
} |
#endif |
@@ -1254,21 +1309,21 @@ void InstructionSelector::VisitFloat64Neg(Node* node) { |
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
- return VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt16Imm, |
+ return VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm, |
&cont); |
} |
FlagsContinuation cont; |
- VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt16Imm, &cont); |
+ VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm, &cont); |
} |
void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
return VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, |
- kInt16Imm_Negate, &cont); |
+ kInt32Imm_Negate, &cont); |
} |
FlagsContinuation cont; |
- VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt16Imm_Negate, |
+ VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt32Imm_Negate, |
&cont); |
} |
@@ -1276,21 +1331,21 @@ 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, kInt16Imm, |
+ return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm, |
&cont); |
} |
FlagsContinuation cont; |
- VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt16Imm, &cont); |
+ VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm, &cont); |
} |
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, |
- kInt16Imm_Negate, &cont); |
+ kInt32Imm_Negate, &cont); |
} |
FlagsContinuation cont; |
- VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt16Imm_Negate, |
+ VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt32Imm_Negate, |
&cont); |
} |
#endif |
@@ -1353,14 +1408,14 @@ void VisitWordCompare(InstructionSelector* selector, Node* node, |
void VisitWord32Compare(InstructionSelector* selector, Node* node, |
FlagsContinuation* cont) { |
- ImmediateMode mode = (CompareLogical(cont) ? kInt16Imm_Unsigned : kInt16Imm); |
+ ImmediateMode mode = (CompareLogical(cont) ? kUint32Imm : kInt32Imm); |
VisitWordCompare(selector, node, kS390_Cmp32, cont, false, mode); |
} |
#if V8_TARGET_ARCH_S390X |
void VisitWord64Compare(InstructionSelector* selector, Node* node, |
FlagsContinuation* cont) { |
- ImmediateMode mode = (CompareLogical(cont) ? kInt16Imm_Unsigned : kInt16Imm); |
+ ImmediateMode mode = (CompareLogical(cont) ? kUint32Imm : kUint32Imm); |
VisitWordCompare(selector, node, kS390_Cmp64, cont, false, mode); |
} |
#endif |
@@ -1467,11 +1522,11 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
case IrOpcode::kInt32AddWithOverflow: |
cont->OverwriteAndNegateIfEqual(kOverflow); |
return VisitBinop<Int32BinopMatcher>( |
- selector, node, kS390_Add32, kInt16Imm, cont); |
+ selector, node, kS390_Add32, kInt32Imm, cont); |
case IrOpcode::kInt32SubWithOverflow: |
cont->OverwriteAndNegateIfEqual(kOverflow); |
return VisitBinop<Int32BinopMatcher>( |
- selector, node, kS390_Sub32, kInt16Imm_Negate, cont); |
+ selector, node, kS390_Sub32, kInt32Imm_Negate, cont); |
case IrOpcode::kInt32MulWithOverflow: |
cont->OverwriteAndNegateIfEqual(kNotEqual); |
return EmitInt32MulWithOverflow(selector, node, cont); |
@@ -1479,11 +1534,11 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
case IrOpcode::kInt64AddWithOverflow: |
cont->OverwriteAndNegateIfEqual(kOverflow); |
return VisitBinop<Int64BinopMatcher>( |
- selector, node, kS390_Add64, kInt16Imm, cont); |
+ selector, node, kS390_Add64, kInt32Imm, cont); |
case IrOpcode::kInt64SubWithOverflow: |
cont->OverwriteAndNegateIfEqual(kOverflow); |
return VisitBinop<Int64BinopMatcher>( |
- selector, node, kS390_Sub64, kInt16Imm_Negate, cont); |
+ selector, node, kS390_Sub64, kInt32Imm_Negate, cont); |
#endif |
default: |
break; |
@@ -1495,7 +1550,7 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
return VisitWord32Compare(selector, value, cont); |
case IrOpcode::kWord32And: |
return VisitWordCompare(selector, value, kS390_Tst32, cont, true, |
- kInt16Imm_Unsigned); |
+ kUint32Imm); |
// TODO(mbrandy): Handle? |
// case IrOpcode::kInt32Add: |
// case IrOpcode::kWord32Or: |
@@ -1509,7 +1564,7 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
return VisitWord64Compare(selector, value, cont); |
case IrOpcode::kWord64And: |
return VisitWordCompare(selector, value, kS390_Tst64, cont, true, |
- kInt16Imm_Unsigned); |
+ kUint32Imm); |
// TODO(mbrandy): Handle? |
// case IrOpcode::kInt64Add: |
// case IrOpcode::kWord64Or: |