Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(669)

Unified Diff: src/compiler/s390/instruction-selector-s390.cc

Issue 2756733002: s390: Unify Visit(Word/Float)(32/64)(Unary/Bin)Op (Closed)
Patch Set: remove unnecessary check Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/s390/code-generator-s390.cc ('k') | src/s390/macro-assembler-s390.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 00e747856823c0d4bff3231c56513e6c803231b5..b2b3a4fe4a65cc8e2c5e00ee5735de420784380d 100644
--- a/src/compiler/s390/instruction-selector-s390.cc
+++ b/src/compiler/s390/instruction-selector-s390.cc
@@ -317,50 +317,49 @@ ArchOpcode SelectLoadOpcode(Node* node) {
return opcode;
}
-bool AutoZeroExtendsWord32ToWord64(Node* node) {
+#define RESULT_IS_WORD32_LIST(V) \
+ /* Float unary op*/ \
+ V(BitcastFloat32ToInt32) \
+ /* V(TruncateFloat64ToWord32) */ \
+ /* V(RoundFloat64ToInt32) */ \
+ /* V(TruncateFloat32ToInt32) */ \
+ /* V(TruncateFloat32ToUint32) */ \
+ /* V(TruncateFloat64ToUint32) */ \
+ /* V(ChangeFloat64ToInt32) */ \
+ /* V(ChangeFloat64ToUint32) */ \
+ /* Word32 unary op */ \
+ V(Word32Clz) \
+ V(Word32Popcnt) \
+ /* Word32 bin op */ \
+ V(Int32Add) \
+ V(Int32Sub) \
+ V(Int32Mul) \
+ V(Int32AddWithOverflow) \
+ V(Int32SubWithOverflow) \
+ V(Int32MulWithOverflow) \
+ V(Int32MulHigh) \
+ V(Uint32MulHigh) \
+ V(Int32Div) \
+ V(Uint32Div) \
+ V(Int32Mod) \
+ V(Uint32Mod) \
+ V(Word32Ror) \
+ V(Word32And) \
+ V(Word32Or) \
+ V(Word32Xor) \
+ V(Word32Shl) \
+ V(Word32Shr) \
+ V(Word32Sar)
+
+bool ProduceWord32Result(Node* node) {
#if !V8_TARGET_ARCH_S390X
return true;
#else
switch (node->opcode()) {
- case IrOpcode::kInt32Div:
- case IrOpcode::kUint32Div:
- case IrOpcode::kInt32MulHigh:
- case IrOpcode::kUint32MulHigh:
- case IrOpcode::kInt32Mod:
- case IrOpcode::kUint32Mod:
- case IrOpcode::kWord32Clz:
- case IrOpcode::kWord32Popcnt:
- case IrOpcode::kChangeUint32ToUint64:
- return true;
- default:
- return false;
- }
- return false;
-#endif
-}
-
-bool ZeroExtendsWord32ToWord64(Node* node) {
-#if !V8_TARGET_ARCH_S390X
- return true;
-#else
- switch (node->opcode()) {
- case IrOpcode::kInt32Add:
- case IrOpcode::kInt32Sub:
- case IrOpcode::kWord32And:
- case IrOpcode::kWord32Or:
- case IrOpcode::kWord32Xor:
- case IrOpcode::kWord32Shl:
- case IrOpcode::kWord32Shr:
- case IrOpcode::kWord32Sar:
- case IrOpcode::kInt32Mul:
- case IrOpcode::kWord32Ror:
- case IrOpcode::kInt32Div:
- case IrOpcode::kUint32Div:
- case IrOpcode::kInt32MulHigh:
- case IrOpcode::kInt32Mod:
- case IrOpcode::kUint32Mod:
- case IrOpcode::kWord32Popcnt:
- return true;
+#define VISITOR(name) case IrOpcode::k##name:
+ RESULT_IS_WORD32_LIST(VISITOR)
+#undef VISITOR
+ return true;
// TODO(john.yan): consider the following case to be valid
// case IrOpcode::kWord32Equal:
// case IrOpcode::kInt32LessThan:
@@ -398,10 +397,12 @@ bool ZeroExtendsWord32ToWord64(Node* node) {
#endif
}
-void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
- S390OperandGenerator g(selector);
- selector->Emit(opcode, g.DefineAsRegister(node),
- g.UseRegister(node->InputAt(0)));
+static inline bool DoZeroExtForResult(Node* node) {
+#if V8_TARGET_ARCH_S390X
+ return ProduceWord32Result(node);
+#else
+ return false;
+#endif
}
// TODO(john.yan): Create VisiteShift to match dst = src shift (R+I)
@@ -503,51 +504,59 @@ 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; }) \
+// Generate The following variations:
+// VisitWord32UnaryOp, VisitWord32BinOp,
+// VisitWord64UnaryOp, VisitWord64BinOp,
+// VisitFloat32UnaryOp, VisitFloat32BinOp,
+// VisitFloat64UnaryOp, VisitFloat64BinOp
+#define VISIT_OP_LIST_32(V) \
+ V(Word32, Unary, [](ArchOpcode opcode) { \
+ return opcode == kS390_LoadWordS32 || opcode == kS390_LoadWordU32; \
+ }) \
+ V(Float32, Unary, \
+ [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \
+ V(Float64, Unary, \
+ [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; }) \
+ V(Word32, Bin, [](ArchOpcode opcode) { \
+ return opcode == kS390_LoadWordS32 || opcode == kS390_LoadWordU32; \
+ }) \
+ V(Float32, Bin, \
+ [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \
V(Float64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; })
+#if V8_TARGET_ARCH_S390X
+#define VISIT_OP_LIST(V) \
+ VISIT_OP_LIST_32(V) \
+ V(Word64, Unary, \
+ [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; }) \
+ V(Word64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; })
+#else
+#define VISIT_OP_LIST VISIT_OP_LIST_32
+#endif
+
#define DECLARE_VISIT_HELPER_FUNCTIONS(type1, type2, canCombineWithLoad) \
- void Visit##type1##type2##Op( \
+ static inline 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) { \
+ static inline 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
+#undef VISIT_OP_LIST_32
+#undef VISIT_OP_LIST
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;
@@ -558,6 +567,16 @@ void VisitUnaryOp(InstructionSelector* selector, Node* node,
GenerateRightOperands(selector, node, input, opcode, operand_mode, inputs,
input_count, canCombineWithLoad);
+ bool input_is_word32 = ProduceWord32Result(input);
+
+ bool doZeroExt = DoZeroExtForResult(node);
+ bool canEliminateZeroExt = input_is_word32;
+
+ if (doZeroExt) {
+ // Add zero-ext indication
+ inputs[input_count++] = g.TempImmediate(!canEliminateZeroExt);
+ }
+
if (cont->IsBranch()) {
inputs[input_count++] = g.Label(cont->true_block());
inputs[input_count++] = g.Label(cont->false_block());
@@ -567,7 +586,12 @@ void VisitUnaryOp(InstructionSelector* selector, Node* node,
// 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.DefineAsRegister(node);
+ if (doZeroExt && canEliminateZeroExt) {
+ // we have to make sure result and left use the same register
+ outputs[output_count++] = g.DefineSameAsFirst(node);
+ } else {
+ outputs[output_count++] = g.DefineAsRegister(node);
+ }
} else {
outputs[output_count++] = g.DefineSameAsFirst(node);
}
@@ -617,102 +641,32 @@ void VisitBinOp(InstructionSelector* selector, Node* node,
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,
- InstructionCode opcode, OperandModes operand_mode,
- FlagsContinuation* cont) {
- 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;
+ bool left_is_word32 = ProduceWord32Result(left);
- // match left of TruncateInt64ToInt32
- if (m.left().IsTruncateInt64ToInt32() && selector->CanCover(node, left)) {
- left = left->InputAt(0);
- }
- // match right of TruncateInt64ToInt32
- if (m.right().IsTruncateInt64ToInt32() && selector->CanCover(node, right)) {
- right = right->InputAt(0);
- }
+ bool doZeroExt = DoZeroExtForResult(node);
+ bool canEliminateZeroExt = left_is_word32;
-#if V8_TARGET_ARCH_S390X
- if ((ZeroExtendsWord32ToWord64(right) || g.CanBeBetterLeftOperand(right)) &&
- node->op()->HasProperty(Operator::kCommutative) &&
- !g.CanBeImmediate(right, operand_mode)) {
- std::swap(left, right);
+ if (doZeroExt) {
+ // Add zero-ext indication
+ inputs[input_count++] = g.TempImmediate(!canEliminateZeroExt);
}
-#else
- if (node->op()->HasProperty(Operator::kCommutative) &&
- !g.CanBeImmediate(right, operand_mode) &&
- (g.CanBeBetterLeftOperand(right))) {
- std::swap(left, right);
- }
-#endif
-
- 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);
-
- inputs[input_count++] =
- g.TempImmediate(doZeroExt && (!AutoZeroExtendsWord32ToWord64(node)));
if (cont->IsBranch()) {
inputs[input_count++] = g.Label(cont->true_block());
inputs[input_count++] = g.Label(cont->false_block());
}
- if (doZeroExt && (operand_mode & OperandMode::kAllowDistinctOps) &&
+ 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
+ // 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);
+ if (doZeroExt && canEliminateZeroExt) {
+ // we have to make sure result and left use the same register
+ outputs[output_count++] = g.DefineSameAsFirst(node);
+ } else {
+ outputs[output_count++] = g.DefineAsRegister(node);
+ }
} else {
outputs[output_count++] = g.DefineSameAsFirst(node);
}
@@ -739,13 +693,6 @@ void VisitBin32op(InstructionSelector* selector, Node* node,
}
}
-void VisitBin32op(InstructionSelector* selector, Node* node, ArchOpcode opcode,
- OperandModes operand_mode) {
- FlagsContinuation cont;
- VisitBin32op(selector, node, opcode, operand_mode, &cont);
-}
-#undef VISIT_OP_LIST
-
} // namespace
void InstructionSelector::VisitLoad(Node* node) {
@@ -1013,23 +960,6 @@ static inline bool IsContiguousMask64(uint64_t value, int* mb, int* me) {
}
#endif
-// 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) {
S390OperandGenerator g(this);
@@ -1082,14 +1012,6 @@ void InstructionSelector::VisitWord64And(Node* node) {
VisitWord64BinOp(this, node, kS390_And64, And64OperandMode);
}
-void InstructionSelector::VisitWord64Or(Node* node) {
- VisitWord64BinOp(this, node, kS390_Or64, Or64OperandMode);
-}
-
-void InstructionSelector::VisitWord64Xor(Node* node) {
- VisitWord64BinOp(this, node, kS390_Xor64, Xor64OperandMode);
-}
-
void InstructionSelector::VisitWord64Shl(Node* node) {
S390OperandGenerator g(this);
Int64BinopMatcher m(node);
@@ -1171,27 +1093,31 @@ void InstructionSelector::VisitWord64Shr(Node* node) {
}
#endif
-void InstructionSelector::VisitWord32Sar(Node* node) {
- S390OperandGenerator g(this);
+static inline bool TryMatchSignExtInt16OrInt8FromWord32Sar(
+ InstructionSelector* selector, Node* node) {
+ S390OperandGenerator g(selector);
Int32BinopMatcher m(node);
- // Replace with sign extension for (x << K) >> K where K is 16 or 24.
- if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) {
+ if (selector->CanCover(node, m.left().node()) && m.left().IsWord32Shl()) {
Int32BinopMatcher mleft(m.left().node());
if (mleft.right().Is(16) && m.right().Is(16)) {
- bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node());
- Emit(kS390_ExtendSignWord16,
- doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node),
- g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt));
- return;
+ bool canEliminateZeroExt = ProduceWord32Result(mleft.left().node());
+ selector->Emit(kS390_ExtendSignWord16,
+ canEliminateZeroExt ? g.DefineSameAsFirst(node)
+ : g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()),
+ g.TempImmediate(!canEliminateZeroExt));
+ return true;
} else if (mleft.right().Is(24) && m.right().Is(24)) {
- bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node());
- Emit(kS390_ExtendSignWord8,
- doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node),
- g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt));
- return;
+ bool canEliminateZeroExt = ProduceWord32Result(mleft.left().node());
+ selector->Emit(kS390_ExtendSignWord8,
+ canEliminateZeroExt ? g.DefineSameAsFirst(node)
+ : g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()),
+ g.TempImmediate(!canEliminateZeroExt));
+ return true;
}
}
- VisitBin32op(this, node, kS390_ShiftRightArith32, Shift32OperandMode);
+ return false;
}
#if !V8_TARGET_ARCH_S390X
@@ -1302,51 +1228,6 @@ void InstructionSelector::VisitWord32PairSar(Node* node) {
}
#endif
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitWord64Sar(Node* node) {
- VisitWord64BinOp(this, node, kS390_ShiftRightArith64, Shift64OperandMode);
-}
-#endif
-
-void InstructionSelector::VisitWord32Ror(Node* node) {
- // TODO(john): match dst = ror(src1, src2 + imm)
- VisitBin32op(this, node, kS390_RotRight32,
- OperandMode::kAllowRI | OperandMode::kAllowRRR |
- OperandMode::kAllowRRI | OperandMode::kShift32Imm);
-}
-
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitWord64Ror(Node* node) {
- VisitWord64BinOp(this, node, kS390_RotRight64, Shift64OperandMode);
-}
-#endif
-
-void InstructionSelector::VisitWord32Clz(Node* node) {
- VisitRR(this, kS390_Cntlz32, node);
-}
-
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitWord64Clz(Node* node) {
- S390OperandGenerator g(this);
- Emit(kS390_Cntlz64, g.DefineAsRegister(node),
- g.UseRegister(node->InputAt(0)));
-}
-#endif
-
-void InstructionSelector::VisitWord32Popcnt(Node* node) {
- S390OperandGenerator g(this);
- Node* value = node->InputAt(0);
- Emit(kS390_Popcnt32, g.DefineAsRegister(node), g.UseRegister(value));
-}
-
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitWord64Popcnt(Node* node) {
- S390OperandGenerator g(this);
- Emit(kS390_Popcnt64, g.DefineAsRegister(node),
- g.UseRegister(node->InputAt(0)));
-}
-#endif
-
void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
#if V8_TARGET_ARCH_S390X
@@ -1384,222 +1265,329 @@ void InstructionSelector::VisitWord32ReverseBytes(Node* node) {
g.UseRegister(node->InputAt(0)));
}
-void InstructionSelector::VisitInt32Add(Node* node) {
- VisitBin32op(this, node, kS390_Add32, AddOperandMode);
-}
-
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitInt64Add(Node* node) {
- VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode);
-}
-#endif
-
-void InstructionSelector::VisitInt32Sub(Node* node) {
- S390OperandGenerator g(this);
- Int32BinopMatcher m(node);
- if (m.left().Is(0)) {
- Node* right = m.right().node();
- bool doZeroExt = ZeroExtendsWord32ToWord64(right);
- Emit(kS390_Neg32, g.DefineAsRegister(node), g.UseRegister(right),
- g.TempImmediate(doZeroExt));
- } else {
- VisitBin32op(this, node, kS390_Sub32, SubOperandMode);
- }
-}
-
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitInt64Sub(Node* node) {
- S390OperandGenerator g(this);
- Int64BinopMatcher m(node);
+template <class Matcher, ArchOpcode neg_opcode>
+static inline bool TryMatchNegFromSub(InstructionSelector* selector,
+ Node* node) {
+ S390OperandGenerator g(selector);
+ Matcher m(node);
+ static_assert(neg_opcode == kS390_Neg32 || neg_opcode == kS390_Neg64,
+ "Provided opcode is not a Neg opcode.");
if (m.left().Is(0)) {
- Emit(kS390_Neg64, g.DefineAsRegister(node),
- g.UseRegister(m.right().node()));
- } else {
- VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode);
- }
-}
-#endif
-
-void InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
- if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
- FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
- return VisitBin32op(this, node, kS390_Mul32WithOverflow,
- OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps,
- &cont);
- }
- VisitBin32op(this, node, kS390_Mul32, MulOperandMode);
-}
-
-void InstructionSelector::VisitInt32Mul(Node* node) {
- S390OperandGenerator g(this);
- Int32BinopMatcher m(node);
- Node* left = m.left().node();
- Node* right = m.right().node();
- if (g.CanBeImmediate(right, OperandMode::kInt32Imm) &&
- base::bits::IsPowerOfTwo32(g.GetImmediate(right))) {
- int power = 31 - base::bits::CountLeadingZeros32(g.GetImmediate(right));
- bool doZeroExt = !ZeroExtendsWord32ToWord64(left);
- InstructionOperand dst =
- (doZeroExt && CpuFeatures::IsSupported(DISTINCT_OPS))
- ? g.DefineAsRegister(node)
- : g.DefineSameAsFirst(node);
-
- Emit(kS390_ShiftLeft32, dst, g.UseRegister(left), g.UseImmediate(power),
- g.TempImmediate(doZeroExt));
- return;
+ Node* value = m.right().node();
+ bool doZeroExt = DoZeroExtForResult(node);
+ bool canEliminateZeroExt = ProduceWord32Result(value);
+ if (doZeroExt) {
+ selector->Emit(neg_opcode,
+ canEliminateZeroExt ? g.DefineSameAsFirst(node)
+ : g.DefineAsRegister(node),
+ g.UseRegister(value),
+ g.TempImmediate(!canEliminateZeroExt));
+ } else {
+ selector->Emit(neg_opcode, g.DefineAsRegister(node),
+ g.UseRegister(value));
+ }
+ return true;
}
- VisitBin32op(this, node, kS390_Mul32, MulOperandMode);
+ return false;
}
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitInt64Mul(Node* node) {
- S390OperandGenerator g(this);
- Int64BinopMatcher m(node);
+template <class Matcher, ArchOpcode shift_op>
+bool TryMatchShiftFromMul(InstructionSelector* selector, Node* node) {
+ S390OperandGenerator g(selector);
+ Matcher m(node);
Node* left = m.left().node();
Node* right = m.right().node();
if (g.CanBeImmediate(right, OperandMode::kInt32Imm) &&
base::bits::IsPowerOfTwo64(g.GetImmediate(right))) {
int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right));
- Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left),
- g.UseImmediate(power));
- return;
+ bool doZeroExt = DoZeroExtForResult(node);
+ bool canEliminateZeroExt = ProduceWord32Result(left);
+ InstructionOperand dst = (doZeroExt && !canEliminateZeroExt &&
+ CpuFeatures::IsSupported(DISTINCT_OPS))
+ ? g.DefineAsRegister(node)
+ : g.DefineSameAsFirst(node);
+
+ if (doZeroExt) {
+ selector->Emit(shift_op, dst, g.UseRegister(left), g.UseImmediate(power),
+ g.TempImmediate(!canEliminateZeroExt));
+ } else {
+ selector->Emit(shift_op, dst, g.UseRegister(left), g.UseImmediate(power));
+ }
+ return true;
}
- VisitWord64BinOp(this, node, kS390_Mul64, MulOperandMode);
-}
-#endif
-
-void InstructionSelector::VisitInt32MulHigh(Node* node) {
- VisitBin32op(this, node, kS390_MulHigh32,
- OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps);
-}
-
-void InstructionSelector::VisitUint32MulHigh(Node* node) {
- VisitBin32op(this, node, kS390_MulHighU32,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
-}
-
-void InstructionSelector::VisitInt32Div(Node* node) {
- VisitBin32op(this, node, kS390_Div32,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
+ return false;
}
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitInt64Div(Node* node) {
- VisitWord64BinOp(this, node, kS390_Div64,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
+template <ArchOpcode opcode>
+static inline bool TryMatchInt32OpWithOverflow(InstructionSelector* selector,
+ Node* node, OperandModes mode) {
+ if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
+ FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
+ VisitWord32BinOp(selector, node, opcode, mode, &cont);
+ return true;
+ }
+ return false;
}
-#endif
-void InstructionSelector::VisitUint32Div(Node* node) {
- VisitBin32op(this, node, kS390_DivU32,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
+static inline bool TryMatchInt32AddWithOverflow(InstructionSelector* selector,
+ Node* node) {
+ return TryMatchInt32OpWithOverflow<kS390_Add32>(selector, node,
+ AddOperandMode);
}
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitUint64Div(Node* node) {
- VisitWord64BinOp(this, node, kS390_DivU64,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
+static inline bool TryMatchInt32SubWithOverflow(InstructionSelector* selector,
+ Node* node) {
+ return TryMatchInt32OpWithOverflow<kS390_Sub32>(selector, node,
+ SubOperandMode);
}
-#endif
-void InstructionSelector::VisitInt32Mod(Node* node) {
- VisitBin32op(this, node, kS390_Mod32,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
+static inline bool TryMatchInt32MulWithOverflow(InstructionSelector* selector,
+ Node* node) {
+ if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
+ FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
+ VisitWord32BinOp(selector, node, kS390_Mul32WithOverflow,
+ OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps,
+ &cont);
+ return true;
+ }
+ return TryMatchShiftFromMul<Int32BinopMatcher, kS390_ShiftLeft32>(selector,
+ node);
}
#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitInt64Mod(Node* node) {
- VisitWord64BinOp(this, node, kS390_Mod64,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
+template <ArchOpcode opcode>
+static inline bool TryMatchInt64OpWithOverflow(InstructionSelector* selector,
+ Node* node, OperandModes mode) {
+ if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
+ FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
+ VisitWord64BinOp(selector, node, opcode, mode, &cont);
+ return true;
+ }
+ return false;
}
-#endif
-void InstructionSelector::VisitUint32Mod(Node* node) {
- VisitBin32op(this, node, kS390_ModU32,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
+static inline bool TryMatchInt64AddWithOverflow(InstructionSelector* selector,
+ Node* node) {
+ return TryMatchInt64OpWithOverflow<kS390_Add64>(selector, node,
+ AddOperandMode);
}
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitUint64Mod(Node* node) {
- VisitWord64BinOp(this, node, kS390_ModU64,
- OperandMode::kAllowRRM | OperandMode::kAllowRRR);
+static inline bool TryMatchInt64SubWithOverflow(InstructionSelector* selector,
+ Node* node) {
+ return TryMatchInt64OpWithOverflow<kS390_Sub64>(selector, node,
+ SubOperandMode);
}
#endif
+#define null ([]() { return false; })
// TODO(john.yan): place kAllowRM where available
-#define VISIT_FLOAT_UNARY_OP_LIST(V) \
+#define FLOAT_UNARY_OP_LIST_32(V) \
V(Float32, ChangeFloat32ToFloat64, kS390_Float32ToDouble, \
- OperandMode::kAllowRM) \
+ OperandMode::kAllowRM, null) \
V(Float32, BitcastFloat32ToInt32, kS390_BitcastFloat32ToInt32, \
- OperandMode::kNone) \
+ OperandMode::kNone, null) \
V(Float64, TruncateFloat64ToFloat32, kS390_DoubleToFloat32, \
- OperandMode::kNone) \
+ OperandMode::kNone, null) \
V(Float64, TruncateFloat64ToWord32, kArchTruncateDoubleToI, \
- OperandMode::kNone) \
- V(Float64, RoundFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone) \
- V(Float32, TruncateFloat32ToInt32, kS390_Float32ToInt32, OperandMode::kNone) \
+ OperandMode::kNone, null) \
+ V(Float64, RoundFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone, \
+ null) \
+ V(Float32, TruncateFloat32ToInt32, kS390_Float32ToInt32, OperandMode::kNone, \
+ null) \
V(Float32, TruncateFloat32ToUint32, kS390_Float32ToUint32, \
- OperandMode::kNone) \
- V(Float64, ChangeFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone) \
- V(Float64, ChangeFloat64ToUint32, kS390_DoubleToUint32, OperandMode::kNone) \
+ OperandMode::kNone, null) \
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)
+ OperandMode::kNone, null) \
+ V(Float64, ChangeFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone, \
+ null) \
+ V(Float64, ChangeFloat64ToUint32, kS390_DoubleToUint32, OperandMode::kNone, \
+ null) \
+ V(Float64, Float64SilenceNaN, kS390_Float64SilenceNaN, OperandMode::kNone, \
+ null) \
+ V(Float32, Float32Abs, kS390_AbsFloat, OperandMode::kNone, null) \
+ V(Float64, Float64Abs, kS390_AbsDouble, OperandMode::kNone, null) \
+ V(Float32, Float32Sqrt, kS390_SqrtFloat, OperandMode::kNone, null) \
+ V(Float64, Float64Sqrt, kS390_SqrtDouble, OperandMode::kNone, null) \
+ V(Float32, Float32RoundDown, kS390_FloorFloat, OperandMode::kNone, null) \
+ V(Float64, Float64RoundDown, kS390_FloorDouble, OperandMode::kNone, null) \
+ V(Float32, Float32RoundUp, kS390_CeilFloat, OperandMode::kNone, null) \
+ V(Float64, Float64RoundUp, kS390_CeilDouble, OperandMode::kNone, null) \
+ V(Float32, Float32RoundTruncate, kS390_TruncateFloat, OperandMode::kNone, \
+ null) \
+ V(Float64, Float64RoundTruncate, kS390_TruncateDouble, OperandMode::kNone, \
+ null) \
+ V(Float64, Float64RoundTiesAway, kS390_RoundDouble, OperandMode::kNone, \
+ null) \
+ V(Float32, Float32Neg, kS390_NegFloat, OperandMode::kNone, null) \
+ V(Float64, Float64Neg, kS390_NegDouble, OperandMode::kNone, null)
+
+#define FLOAT_BIN_OP_LIST(V) \
+ V(Float32, Float32Add, kS390_AddFloat, OperandMode::kAllowRM, null) \
+ V(Float64, Float64Add, kS390_AddDouble, OperandMode::kAllowRM, null) \
+ V(Float32, Float32Sub, kS390_SubFloat, OperandMode::kAllowRM, null) \
+ V(Float64, Float64Sub, kS390_SubDouble, OperandMode::kAllowRM, null) \
+ V(Float32, Float32Mul, kS390_MulFloat, OperandMode::kAllowRM, null) \
+ V(Float64, Float64Mul, kS390_MulDouble, OperandMode::kAllowRM, null) \
+ V(Float32, Float32Div, kS390_DivFloat, OperandMode::kAllowRM, null) \
+ V(Float64, Float64Div, kS390_DivDouble, OperandMode::kAllowRM, null) \
+ V(Float32, Float32Max, kS390_MaxFloat, OperandMode::kNone, null) \
+ V(Float64, Float64Max, kS390_MaxDouble, OperandMode::kNone, null) \
+ V(Float32, Float32Min, kS390_MinFloat, OperandMode::kNone, null) \
+ V(Float64, Float64Min, kS390_MinDouble, OperandMode::kNone, null)
+
+#define WORD32_UNARY_OP_LIST_32(V) \
+ V(Word32, Word32Clz, kS390_Cntlz32, OperandMode::kNone, null) \
+ V(Word32, Word32Popcnt, kS390_Popcnt32, OperandMode::kNone, null) \
+ V(Word32, RoundInt32ToFloat32, kS390_Int32ToFloat32, OperandMode::kNone, \
+ null) \
+ V(Word32, RoundUint32ToFloat32, kS390_Uint32ToFloat32, OperandMode::kNone, \
+ null) \
+ V(Word32, ChangeInt32ToFloat64, kS390_Int32ToDouble, OperandMode::kNone, \
+ null) \
+ V(Word32, ChangeUint32ToFloat64, kS390_Uint32ToDouble, OperandMode::kNone, \
+ null) \
+ V(Word32, BitcastInt32ToFloat32, kS390_BitcastInt32ToFloat32, \
+ OperandMode::kNone, null)
+
+#ifdef V8_TARGET_ARCH_S390X
+#define FLOAT_UNARY_OP_LIST(V) \
+ FLOAT_UNARY_OP_LIST_32(V) \
+ V(Float64, ChangeFloat64ToUint64, kS390_DoubleToUint64, OperandMode::kNone, \
+ null) \
+ V(Float64, BitcastFloat64ToInt64, kS390_BitcastDoubleToInt64, \
+ OperandMode::kNone, null)
+#define WORD32_UNARY_OP_LIST(V) \
+ WORD32_UNARY_OP_LIST_32(V) \
+ V(Word32, ChangeInt32ToInt64, kS390_ExtendSignWord32, OperandMode::kNone, \
+ null) \
+ V(Word32, ChangeUint32ToUint64, kS390_Uint32ToUint64, OperandMode::kNone, \
+ [&]() -> bool { \
+ if (ProduceWord32Result(node->InputAt(0))) { \
+ EmitIdentity(node); \
+ return true; \
+ } \
+ return false; \
+ })
-#define DECLARE_UNARY_OP(type, name, op, mode) \
- void InstructionSelector::Visit##name(Node* node) { \
- Visit##type##UnaryOp(this, node, op, mode); \
- }
+#else
+#define FLOAT_UNARY_OP_LIST(V) FLOAT_UNARY_OP_LIST_32(V)
+#define WORD32_UNARY_OP_LIST(V) WORD32_UNARY_OP_LIST_32(V)
+#endif
-VISIT_FLOAT_UNARY_OP_LIST(DECLARE_UNARY_OP);
+#define WORD32_BIN_OP_LIST(V) \
+ V(Word32, Int32Add, kS390_Add32, AddOperandMode, null) \
+ V(Word32, Int32Sub, kS390_Sub32, SubOperandMode, ([&]() { \
+ return TryMatchNegFromSub<Int32BinopMatcher, kS390_Neg32>(this, node); \
+ })) \
+ V(Word32, Int32Mul, kS390_Mul32, MulOperandMode, ([&]() { \
+ return TryMatchShiftFromMul<Int32BinopMatcher, kS390_ShiftLeft32>(this, \
+ node); \
+ })) \
+ V(Word32, Int32AddWithOverflow, kS390_Add32, AddOperandMode, \
+ ([&]() { return TryMatchInt32AddWithOverflow(this, node); })) \
+ V(Word32, Int32SubWithOverflow, kS390_Sub32, SubOperandMode, \
+ ([&]() { return TryMatchInt32SubWithOverflow(this, node); })) \
+ V(Word32, Int32MulWithOverflow, kS390_Mul32, MulOperandMode, \
+ ([&]() { return TryMatchInt32MulWithOverflow(this, node); })) \
+ V(Word32, Int32MulHigh, kS390_MulHigh32, \
+ OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, null) \
+ V(Word32, Uint32MulHigh, kS390_MulHighU32, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word32, Int32Div, kS390_Div32, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word32, Uint32Div, kS390_DivU32, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word32, Int32Mod, kS390_Mod32, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word32, Uint32Mod, kS390_ModU32, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word32, Word32Ror, kS390_RotRight32, \
+ OperandMode::kAllowRI | OperandMode::kAllowRRR | OperandMode::kAllowRRI | \
+ OperandMode::kShift32Imm, \
+ null) \
+ V(Word32, Word32And, kS390_And32, And32OperandMode, null) \
+ V(Word32, Word32Or, kS390_Or32, Or32OperandMode, null) \
+ V(Word32, Word32Xor, kS390_Xor32, Xor32OperandMode, null) \
+ V(Word32, Word32Shl, kS390_ShiftLeft32, Shift32OperandMode, null) \
+ V(Word32, Word32Shr, kS390_ShiftRight32, Shift32OperandMode, null) \
+ V(Word32, Word32Sar, kS390_ShiftRightArith32, Shift32OperandMode, \
+ [&]() { return TryMatchSignExtInt16OrInt8FromWord32Sar(this, node); })
+
+#define WORD64_UNARY_OP_LIST(V) \
+ V(Word64, Word64Popcnt, kS390_Popcnt64, OperandMode::kNone, null) \
+ V(Word64, Word64Clz, kS390_Cntlz64, OperandMode::kNone, null) \
+ V(Word64, TruncateInt64ToInt32, kS390_Int64ToInt32, OperandMode::kNone, \
+ null) \
+ V(Word64, RoundInt64ToFloat32, kS390_Int64ToFloat32, OperandMode::kNone, \
+ null) \
+ V(Word64, RoundInt64ToFloat64, kS390_Int64ToDouble, OperandMode::kNone, \
+ null) \
+ V(Word64, RoundUint64ToFloat32, kS390_Uint64ToFloat32, OperandMode::kNone, \
+ null) \
+ V(Word64, RoundUint64ToFloat64, kS390_Uint64ToDouble, OperandMode::kNone, \
+ null) \
+ V(Word64, BitcastInt64ToFloat64, kS390_BitcastInt64ToDouble, \
+ OperandMode::kNone, null)
+
+#define WORD64_BIN_OP_LIST(V) \
+ V(Word64, Int64Add, kS390_Add64, AddOperandMode, null) \
+ V(Word64, Int64Sub, kS390_Sub64, SubOperandMode, ([&]() { \
+ return TryMatchNegFromSub<Int64BinopMatcher, kS390_Neg64>(this, node); \
+ })) \
+ V(Word64, Int64AddWithOverflow, kS390_Add64, AddOperandMode, \
+ ([&]() { return TryMatchInt64AddWithOverflow(this, node); })) \
+ V(Word64, Int64SubWithOverflow, kS390_Sub64, SubOperandMode, \
+ ([&]() { return TryMatchInt64SubWithOverflow(this, node); })) \
+ V(Word64, Int64Mul, kS390_Mul64, MulOperandMode, ([&]() { \
+ return TryMatchShiftFromMul<Int64BinopMatcher, kS390_ShiftLeft64>(this, \
+ node); \
+ })) \
+ V(Word64, Int64Div, kS390_Div64, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word64, Uint64Div, kS390_DivU64, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word64, Int64Mod, kS390_Mod64, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word64, Uint64Mod, kS390_ModU64, \
+ OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
+ V(Word64, Word64Sar, kS390_ShiftRightArith64, Shift64OperandMode, null) \
+ V(Word64, Word64Ror, kS390_RotRight64, Shift64OperandMode, null) \
+ V(Word64, Word64Or, kS390_Or64, Or64OperandMode, null) \
+ V(Word64, Word64Xor, kS390_Xor64, Xor64OperandMode, null)
+
+#define DECLARE_UNARY_OP(type, name, op, mode, try_extra) \
+ void InstructionSelector::Visit##name(Node* node) { \
+ if (std::function<bool()>(try_extra)()) return; \
+ Visit##type##UnaryOp(this, node, op, mode); \
+ }
+
+#define DECLARE_BIN_OP(type, name, op, mode, try_extra) \
+ void InstructionSelector::Visit##name(Node* node) { \
+ if (std::function<bool()>(try_extra)()) return; \
+ Visit##type##BinOp(this, node, op, mode); \
+ }
+
+WORD32_BIN_OP_LIST(DECLARE_BIN_OP);
+WORD32_UNARY_OP_LIST(DECLARE_UNARY_OP);
+FLOAT_UNARY_OP_LIST(DECLARE_UNARY_OP);
+FLOAT_BIN_OP_LIST(DECLARE_BIN_OP);
#if V8_TARGET_ARCH_S390X
-VISIT_WORD64_UNARY_OP_LIST(DECLARE_UNARY_OP)
+WORD64_UNARY_OP_LIST(DECLARE_UNARY_OP)
+WORD64_BIN_OP_LIST(DECLARE_BIN_OP)
#endif
+#undef DECLARE_BIN_OP
#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);
-}
-
-void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
- VisitRR(this, kS390_Uint32ToFloat32, node);
-}
-
-void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
- VisitRR(this, kS390_Int32ToDouble, node);
-}
-
-void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
- VisitRR(this, kS390_Uint32ToDouble, node);
-}
+#undef WORD64_BIN_OP_LIST
+#undef WORD64_UNARY_OP_LIST
+#undef WORD32_BIN_OP_LIST
+#undef WORD32_UNARY_OP_LIST
+#undef FLOAT_UNARY_OP_LIST
+#undef WORD32_UNARY_OP_LIST_32
+#undef FLOAT_BIN_OP_LIST
+#undef FLOAT_BIN_OP_LIST_32
+#undef null
#if V8_TARGET_ARCH_S390X
void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
@@ -1618,66 +1606,8 @@ void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) {
VisitTryTruncateDouble(this, kS390_DoubleToUint64, node);
}
-void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
- // TODO(mbrandy): inspect input to see if nop is appropriate.
- VisitRR(this, kS390_ExtendSignWord32, node);
-}
-
-void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
- S390OperandGenerator g(this);
- Node* value = node->InputAt(0);
- if (ZeroExtendsWord32ToWord64(value)) {
- // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the
- // zero-extension is a no-op.
- return EmitIdentity(node);
- }
- VisitRR(this, kS390_Uint32ToUint64, node);
-}
-
-void InstructionSelector::VisitChangeFloat64ToUint64(Node* node) {
- VisitRR(this, kS390_DoubleToUint64, node);
-}
#endif
-void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
- VisitRR(this, kS390_BitcastInt32ToFloat32, node);
-}
-
-void InstructionSelector::VisitFloat32Add(Node* node) {
- return VisitFloat32BinOp(this, node, kS390_AddFloat, OperandMode::kAllowRM);
-}
-
-void InstructionSelector::VisitFloat64Add(Node* node) {
- // TODO(mbrandy): detect multiply-add
- return VisitFloat64BinOp(this, node, kS390_AddDouble, OperandMode::kAllowRM);
-}
-
-void InstructionSelector::VisitFloat32Sub(Node* node) {
- return VisitFloat32BinOp(this, node, kS390_SubFloat, OperandMode::kAllowRM);
-}
-
-void InstructionSelector::VisitFloat64Sub(Node* node) {
- // TODO(mbrandy): detect multiply-subtract
- return VisitFloat64BinOp(this, node, kS390_SubDouble, OperandMode::kAllowRM);
-}
-
-void InstructionSelector::VisitFloat32Mul(Node* node) {
- return VisitFloat32BinOp(this, node, kS390_MulFloat, OperandMode::kAllowRM);
-}
-
-void InstructionSelector::VisitFloat64Mul(Node* node) {
- // TODO(mbrandy): detect negate
- return VisitFloat64BinOp(this, node, kS390_MulDouble, OperandMode::kAllowRM);
-}
-
-void InstructionSelector::VisitFloat32Div(Node* node) {
- return VisitFloat32BinOp(this, node, kS390_DivFloat, OperandMode::kAllowRM);
-}
-
-void InstructionSelector::VisitFloat64Div(Node* node) {
- return VisitFloat64BinOp(this, node, kS390_DivDouble, OperandMode::kAllowRM);
-}
-
void InstructionSelector::VisitFloat64Mod(Node* node) {
S390OperandGenerator g(this);
Emit(kS390_ModDouble, g.DefineAsFixed(node, d1),
@@ -1685,22 +1615,6 @@ void InstructionSelector::VisitFloat64Mod(Node* node) {
->MarkAsCall();
}
-void InstructionSelector::VisitFloat32Max(Node* node) {
- return VisitFloat32BinOp(this, node, kS390_MaxFloat, OperandMode::kNone);
-}
-
-void InstructionSelector::VisitFloat64Max(Node* node) {
- return VisitFloat64BinOp(this, node, kS390_MaxDouble, OperandMode::kNone);
-}
-
-void InstructionSelector::VisitFloat32Min(Node* node) {
- return VisitFloat32BinOp(this, node, kS390_MinFloat, OperandMode::kNone);
-}
-
-void InstructionSelector::VisitFloat64Min(Node* node) {
- return VisitFloat64BinOp(this, node, kS390_MinDouble, OperandMode::kNone);
-}
-
void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
InstructionCode opcode) {
S390OperandGenerator g(this);
@@ -1724,44 +1638,6 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
UNREACHABLE();
}
-void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
- OperandModes mode = AddOperandMode;
- if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
- FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
- return VisitBin32op(this, node, kS390_Add32, mode, &cont);
- }
- FlagsContinuation cont;
- VisitBin32op(this, node, kS390_Add32, mode, &cont);
-}
-
-void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
- OperandModes mode = SubOperandMode;
- if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
- FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
- return VisitBin32op(this, node, kS390_Sub32, mode, &cont);
- }
- FlagsContinuation cont;
- VisitBin32op(this, node, kS390_Sub32, mode, &cont);
-}
-
-#if V8_TARGET_ARCH_S390X
-void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
- if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
- FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
- return VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode, &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 VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode, &cont);
- }
- VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode);
-}
-#endif
-
static bool CompareLogical(FlagsContinuation* cont) {
switch (cont->condition()) {
case kUnsignedLessThan:
@@ -2105,15 +1981,15 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
switch (node->opcode()) {
case IrOpcode::kInt32AddWithOverflow:
cont->OverwriteAndNegateIfEqual(kOverflow);
- return VisitBin32op(selector, node, kS390_Add32, AddOperandMode,
- cont);
+ return VisitWord32BinOp(selector, node, kS390_Add32,
+ AddOperandMode, cont);
case IrOpcode::kInt32SubWithOverflow:
cont->OverwriteAndNegateIfEqual(kOverflow);
- return VisitBin32op(selector, node, kS390_Sub32, SubOperandMode,
- cont);
+ return VisitWord32BinOp(selector, node, kS390_Sub32,
+ SubOperandMode, cont);
case IrOpcode::kInt32MulWithOverflow:
cont->OverwriteAndNegateIfEqual(kNotEqual);
- return VisitBin32op(
+ return VisitWord32BinOp(
selector, node, kS390_Mul32WithOverflow,
OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps,
cont);
@@ -2156,13 +2032,13 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
break;
case IrOpcode::kWord32Or:
if (fc == kNotEqual || fc == kEqual)
- return VisitBin32op(selector, value, kS390_Or32, Or32OperandMode,
- cont);
+ return VisitWord32BinOp(selector, value, kS390_Or32, Or32OperandMode,
+ cont);
break;
case IrOpcode::kWord32Xor:
if (fc == kNotEqual || fc == kEqual)
- return VisitBin32op(selector, value, kS390_Xor32, Xor32OperandMode,
- cont);
+ return VisitWord32BinOp(selector, value, kS390_Xor32,
+ Xor32OperandMode, cont);
break;
case IrOpcode::kWord32Sar:
case IrOpcode::kWord32Shl:
« no previous file with comments | « src/compiler/s390/code-generator-s390.cc ('k') | src/s390/macro-assembler-s390.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698