| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
| 6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
| 7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 kMode_Operand2_R_LSR_I) || | 150 kMode_Operand2_R_LSR_I) || |
| 151 TryMatchShift<Int64BinopMatcher>(selector, node, opcode, | 151 TryMatchShift<Int64BinopMatcher>(selector, node, opcode, |
| 152 IrOpcode::kWord64Sar, kShift64Imm, | 152 IrOpcode::kWord64Sar, kShift64Imm, |
| 153 kMode_Operand2_R_ASR_I) || | 153 kMode_Operand2_R_ASR_I) || |
| 154 (try_ror && TryMatchShift<Int64BinopMatcher>( | 154 (try_ror && TryMatchShift<Int64BinopMatcher>( |
| 155 selector, node, opcode, IrOpcode::kWord64Ror, | 155 selector, node, opcode, IrOpcode::kWord64Ror, |
| 156 kShift64Imm, kMode_Operand2_R_ROR_I)); | 156 kShift64Imm, kMode_Operand2_R_ROR_I)); |
| 157 } | 157 } |
| 158 | 158 |
| 159 | 159 |
| 160 bool TryMatchAnyExtend(InstructionSelector* selector, Node* node, | 160 bool TryMatchAnyExtend(Arm64OperandGenerator* g, InstructionSelector* selector, |
| 161 InstructionCode* opcode) { | 161 Node* left_node, Node* right_node, |
| 162 NodeMatcher nm(node); | 162 InstructionOperand* left_op, |
| 163 InstructionOperand* right_op, InstructionCode* opcode) { |
| 164 NodeMatcher nm(right_node); |
| 165 |
| 163 if (nm.IsWord32And()) { | 166 if (nm.IsWord32And()) { |
| 164 Int32BinopMatcher m(node); | 167 Int32BinopMatcher mright(right_node); |
| 165 if (m.right().HasValue()) { | 168 if (mright.right().Is(0xff) || mright.right().Is(0xffff)) { |
| 166 if (m.right().Value() == 0xff) { | 169 int32_t mask = mright.right().Value(); |
| 167 *opcode |= AddressingModeField::encode(kMode_Operand2_R_UXTB); | 170 *left_op = g->UseRegister(left_node); |
| 168 return true; | 171 *right_op = g->UseRegister(mright.left().node()); |
| 169 } else if (m.right().Value() == 0xffff) { | 172 *opcode |= AddressingModeField::encode( |
| 170 *opcode |= AddressingModeField::encode(kMode_Operand2_R_UXTH); | 173 (mask == 0xff) ? kMode_Operand2_R_UXTB : kMode_Operand2_R_UXTH); |
| 174 return true; |
| 175 } |
| 176 } else if (nm.IsWord32Sar()) { |
| 177 Int32BinopMatcher mright(right_node); |
| 178 if (selector->CanCover(mright.node(), mright.left().node()) && |
| 179 mright.left().IsWord32Shl()) { |
| 180 Int32BinopMatcher mleft_of_right(mright.left().node()); |
| 181 if ((mright.right().Is(16) && mleft_of_right.right().Is(16)) || |
| 182 (mright.right().Is(24) && mleft_of_right.right().Is(24))) { |
| 183 int32_t shift = mright.right().Value(); |
| 184 *left_op = g->UseRegister(left_node); |
| 185 *right_op = g->UseRegister(mleft_of_right.left().node()); |
| 186 *opcode |= AddressingModeField::encode( |
| 187 (shift == 24) ? kMode_Operand2_R_SXTB : kMode_Operand2_R_SXTH); |
| 171 return true; | 188 return true; |
| 172 } | 189 } |
| 173 } | 190 } |
| 174 } | 191 } |
| 175 return false; | 192 return false; |
| 176 } | 193 } |
| 177 | 194 |
| 178 | 195 |
| 179 // Shared routine for multiple binary operations. | 196 // Shared routine for multiple binary operations. |
| 180 template <typename Matcher> | 197 template <typename Matcher> |
| 181 void VisitBinop(InstructionSelector* selector, Node* node, | 198 void VisitBinop(InstructionSelector* selector, Node* node, |
| 182 InstructionCode opcode, ImmediateMode operand_mode, | 199 InstructionCode opcode, ImmediateMode operand_mode, |
| 183 FlagsContinuation* cont) { | 200 FlagsContinuation* cont) { |
| 184 Arm64OperandGenerator g(selector); | 201 Arm64OperandGenerator g(selector); |
| 185 Matcher m(node); | 202 Matcher m(node); |
| 186 InstructionOperand inputs[4]; | 203 InstructionOperand inputs[4]; |
| 187 size_t input_count = 0; | 204 size_t input_count = 0; |
| 188 InstructionOperand outputs[2]; | 205 InstructionOperand outputs[2]; |
| 189 size_t output_count = 0; | 206 size_t output_count = 0; |
| 190 bool is_add_sub = false; | 207 bool is_add_sub = false; |
| 191 | 208 |
| 192 if (m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || m.IsInt64Sub()) { | 209 if (m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || m.IsInt64Sub()) { |
| 193 is_add_sub = true; | 210 is_add_sub = true; |
| 194 } | 211 } |
| 195 | 212 |
| 196 if (g.CanBeImmediate(m.right().node(), operand_mode)) { | 213 Node* left_node = m.left().node(); |
| 197 inputs[input_count++] = g.UseRegister(m.left().node()); | 214 Node* right_node = m.right().node(); |
| 198 inputs[input_count++] = g.UseImmediate(m.right().node()); | 215 |
| 199 } else if (TryMatchAnyShift(selector, m.right().node(), &opcode, | 216 if (g.CanBeImmediate(right_node, operand_mode)) { |
| 200 !is_add_sub)) { | 217 inputs[input_count++] = g.UseRegister(left_node); |
| 201 Matcher m_shift(m.right().node()); | 218 inputs[input_count++] = g.UseImmediate(right_node); |
| 202 inputs[input_count++] = g.UseRegister(m.left().node()); | 219 } else if (is_add_sub && |
| 220 TryMatchAnyExtend(&g, selector, left_node, right_node, &inputs[0], |
| 221 &inputs[1], &opcode)) { |
| 222 input_count += 2; |
| 223 } else if (is_add_sub && m.HasProperty(Operator::kCommutative) && |
| 224 TryMatchAnyExtend(&g, selector, right_node, left_node, &inputs[0], |
| 225 &inputs[1], &opcode)) { |
| 226 input_count += 2; |
| 227 } else if (TryMatchAnyShift(selector, right_node, &opcode, !is_add_sub)) { |
| 228 Matcher m_shift(right_node); |
| 229 inputs[input_count++] = g.UseRegister(left_node); |
| 203 inputs[input_count++] = g.UseRegister(m_shift.left().node()); | 230 inputs[input_count++] = g.UseRegister(m_shift.left().node()); |
| 204 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); | 231 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); |
| 205 } else if (m.HasProperty(Operator::kCommutative) && | 232 } else if (m.HasProperty(Operator::kCommutative) && |
| 206 TryMatchAnyShift(selector, m.left().node(), &opcode, | 233 TryMatchAnyShift(selector, left_node, &opcode, !is_add_sub)) { |
| 207 !is_add_sub)) { | 234 Matcher m_shift(left_node); |
| 208 Matcher m_shift(m.left().node()); | 235 inputs[input_count++] = g.UseRegister(right_node); |
| 209 inputs[input_count++] = g.UseRegister(m.right().node()); | |
| 210 inputs[input_count++] = g.UseRegister(m_shift.left().node()); | 236 inputs[input_count++] = g.UseRegister(m_shift.left().node()); |
| 211 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); | 237 inputs[input_count++] = g.UseImmediate(m_shift.right().node()); |
| 212 } else if (is_add_sub && | |
| 213 TryMatchAnyExtend(selector, m.right().node(), &opcode)) { | |
| 214 Matcher mright(m.right().node()); | |
| 215 inputs[input_count++] = g.UseRegister(m.left().node()); | |
| 216 inputs[input_count++] = g.UseRegister(mright.left().node()); | |
| 217 } else if (is_add_sub && m.HasProperty(Operator::kCommutative) && | |
| 218 TryMatchAnyExtend(selector, m.left().node(), &opcode)) { | |
| 219 Matcher mleft(m.left().node()); | |
| 220 inputs[input_count++] = g.UseRegister(m.right().node()); | |
| 221 inputs[input_count++] = g.UseRegister(mleft.left().node()); | |
| 222 } else { | 238 } else { |
| 223 inputs[input_count++] = g.UseRegister(m.left().node()); | 239 inputs[input_count++] = g.UseRegister(left_node); |
| 224 inputs[input_count++] = g.UseRegister(m.right().node()); | 240 inputs[input_count++] = g.UseRegister(right_node); |
| 225 } | 241 } |
| 226 | 242 |
| 227 if (cont->IsBranch()) { | 243 if (cont->IsBranch()) { |
| 228 inputs[input_count++] = g.Label(cont->true_block()); | 244 inputs[input_count++] = g.Label(cont->true_block()); |
| 229 inputs[input_count++] = g.Label(cont->false_block()); | 245 inputs[input_count++] = g.Label(cont->false_block()); |
| 230 } | 246 } |
| 231 | 247 |
| 232 outputs[output_count++] = g.DefineAsRegister(node); | 248 outputs[output_count++] = g.DefineAsRegister(node); |
| 233 if (cont->IsSet()) { | 249 if (cont->IsSet()) { |
| 234 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 250 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| (...skipping 1510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 MachineOperatorBuilder::kFloat64RoundTruncate | | 1761 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1746 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1762 MachineOperatorBuilder::kFloat64RoundTiesAway | |
| 1747 MachineOperatorBuilder::kWord32ShiftIsSafe | | 1763 MachineOperatorBuilder::kWord32ShiftIsSafe | |
| 1748 MachineOperatorBuilder::kInt32DivIsSafe | | 1764 MachineOperatorBuilder::kInt32DivIsSafe | |
| 1749 MachineOperatorBuilder::kUint32DivIsSafe; | 1765 MachineOperatorBuilder::kUint32DivIsSafe; |
| 1750 } | 1766 } |
| 1751 | 1767 |
| 1752 } // namespace compiler | 1768 } // namespace compiler |
| 1753 } // namespace internal | 1769 } // namespace internal |
| 1754 } // namespace v8 | 1770 } // namespace v8 |
| OLD | NEW |