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 |