| 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 2134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2145 case kUnsignedLessThanOrEqual: // generate CBZ | 2145 case kUnsignedLessThanOrEqual: // generate CBZ |
| 2146 return kEqual; | 2146 return kEqual; |
| 2147 case kUnsignedGreaterThan: // generate CBNZ | 2147 case kUnsignedGreaterThan: // generate CBNZ |
| 2148 return kNotEqual; | 2148 return kNotEqual; |
| 2149 default: | 2149 default: |
| 2150 UNREACHABLE(); | 2150 UNREACHABLE(); |
| 2151 return cond; | 2151 return cond; |
| 2152 } | 2152 } |
| 2153 } | 2153 } |
| 2154 | 2154 |
| 2155 void EmitBranchOrDeoptimize(InstructionSelector* selector, |
| 2156 InstructionCode opcode, InstructionOperand value, |
| 2157 FlagsContinuation* cont) { |
| 2158 Arm64OperandGenerator g(selector); |
| 2159 if (cont->IsBranch()) { |
| 2160 selector->Emit(cont->Encode(opcode), g.NoOutput(), value, |
| 2161 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 2162 } else { |
| 2163 DCHECK(cont->IsDeoptimize()); |
| 2164 selector->EmitDeoptimize(cont->Encode(opcode), g.NoOutput(), value, |
| 2165 cont->reason(), cont->frame_state()); |
| 2166 } |
| 2167 } |
| 2168 |
| 2155 // Try to emit TBZ, TBNZ, CBZ or CBNZ for certain comparisons of {node} | 2169 // Try to emit TBZ, TBNZ, CBZ or CBNZ for certain comparisons of {node} |
| 2156 // against zero, depending on the condition. | 2170 // against zero, depending on the condition. |
| 2157 bool TryEmitCbzOrTbz(InstructionSelector* selector, Node* node, Node* user, | 2171 bool TryEmitCbzOrTbz(InstructionSelector* selector, Node* node, Node* user, |
| 2158 FlagsCondition cond, FlagsContinuation* cont) { | 2172 FlagsCondition cond, FlagsContinuation* cont) { |
| 2159 Int32BinopMatcher m_user(user); | 2173 Int32BinopMatcher m_user(user); |
| 2160 USE(m_user); | 2174 USE(m_user); |
| 2161 DCHECK(m_user.right().Is(0) || m_user.left().Is(0)); | 2175 DCHECK(m_user.right().Is(0) || m_user.left().Is(0)); |
| 2162 | 2176 |
| 2163 // Only handle branches. | 2177 // Only handle branches and deoptimisations. |
| 2164 if (!cont->IsBranch()) return false; | 2178 if (!cont->IsBranch() && !cont->IsDeoptimize()) return false; |
| 2165 | 2179 |
| 2166 switch (cond) { | 2180 switch (cond) { |
| 2167 case kSignedLessThan: | 2181 case kSignedLessThan: |
| 2168 case kSignedGreaterThanOrEqual: { | 2182 case kSignedGreaterThanOrEqual: { |
| 2183 // We don't generate TBZ/TBNZ for deoptimisations, as they have a |
| 2184 // shorter range than conditional branches and generating them for |
| 2185 // deoptimisations results in more veneers. |
| 2186 if (cont->IsDeoptimize()) return false; |
| 2169 Arm64OperandGenerator g(selector); | 2187 Arm64OperandGenerator g(selector); |
| 2170 cont->Overwrite(MapForTbz(cond)); | 2188 cont->Overwrite(MapForTbz(cond)); |
| 2171 Int32Matcher m(node); | 2189 Int32Matcher m(node); |
| 2172 if (m.IsFloat64ExtractHighWord32() && selector->CanCover(user, node)) { | 2190 if (m.IsFloat64ExtractHighWord32() && selector->CanCover(user, node)) { |
| 2173 // SignedLessThan(Float64ExtractHighWord32(x), 0) and | 2191 // SignedLessThan(Float64ExtractHighWord32(x), 0) and |
| 2174 // SignedGreaterThanOrEqual(Float64ExtractHighWord32(x), 0) essentially | 2192 // SignedGreaterThanOrEqual(Float64ExtractHighWord32(x), 0) essentially |
| 2175 // check the sign bit of a 64-bit floating point value. | 2193 // check the sign bit of a 64-bit floating point value. |
| 2176 InstructionOperand temp = g.TempRegister(); | 2194 InstructionOperand temp = g.TempRegister(); |
| 2177 selector->Emit(kArm64U64MoveFloat64, temp, | 2195 selector->Emit(kArm64U64MoveFloat64, temp, |
| 2178 g.UseRegister(node->InputAt(0))); | 2196 g.UseRegister(node->InputAt(0))); |
| 2179 selector->Emit(cont->Encode(kArm64TestAndBranch), g.NoOutput(), temp, | 2197 selector->Emit(cont->Encode(kArm64TestAndBranch), g.NoOutput(), temp, |
| 2180 g.TempImmediate(63), g.Label(cont->true_block()), | 2198 g.TempImmediate(63), g.Label(cont->true_block()), |
| 2181 g.Label(cont->false_block())); | 2199 g.Label(cont->false_block())); |
| 2182 return true; | 2200 return true; |
| 2183 } | 2201 } |
| 2184 selector->Emit(cont->Encode(kArm64TestAndBranch32), g.NoOutput(), | 2202 selector->Emit(cont->Encode(kArm64TestAndBranch32), g.NoOutput(), |
| 2185 g.UseRegister(node), g.TempImmediate(31), | 2203 g.UseRegister(node), g.TempImmediate(31), |
| 2186 g.Label(cont->true_block()), g.Label(cont->false_block())); | 2204 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 2187 return true; | 2205 return true; |
| 2188 } | 2206 } |
| 2189 case kEqual: | 2207 case kEqual: |
| 2190 case kNotEqual: | 2208 case kNotEqual: |
| 2191 case kUnsignedLessThanOrEqual: | 2209 case kUnsignedLessThanOrEqual: |
| 2192 case kUnsignedGreaterThan: { | 2210 case kUnsignedGreaterThan: { |
| 2193 Arm64OperandGenerator g(selector); | 2211 Arm64OperandGenerator g(selector); |
| 2194 cont->Overwrite(MapForCbz(cond)); | 2212 cont->Overwrite(MapForCbz(cond)); |
| 2195 selector->Emit(cont->Encode(kArm64CompareAndBranch32), g.NoOutput(), | 2213 EmitBranchOrDeoptimize(selector, kArm64CompareAndBranch32, |
| 2196 g.UseRegister(node), g.Label(cont->true_block()), | 2214 g.UseRegister(node), cont); |
| 2197 g.Label(cont->false_block())); | |
| 2198 return true; | 2215 return true; |
| 2199 } | 2216 } |
| 2200 default: | 2217 default: |
| 2201 return false; | 2218 return false; |
| 2202 } | 2219 } |
| 2203 } | 2220 } |
| 2204 | 2221 |
| 2205 void VisitWord32Compare(InstructionSelector* selector, Node* node, | 2222 void VisitWord32Compare(InstructionSelector* selector, Node* node, |
| 2206 FlagsContinuation* cont) { | 2223 FlagsContinuation* cont) { |
| 2207 Int32BinopMatcher m(node); | 2224 Int32BinopMatcher m(node); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2373 // Attempt to merge the Word64Equal(Word64And(x, y), 0) comparison | 2390 // Attempt to merge the Word64Equal(Word64And(x, y), 0) comparison |
| 2374 // into a tbz/tbnz instruction. | 2391 // into a tbz/tbnz instruction. |
| 2375 if (TryEmitTestAndBranch<Uint64BinopMatcher, kArm64TestAndBranch>( | 2392 if (TryEmitTestAndBranch<Uint64BinopMatcher, kArm64TestAndBranch>( |
| 2376 selector, left, cont)) { | 2393 selector, left, cont)) { |
| 2377 return; | 2394 return; |
| 2378 } | 2395 } |
| 2379 return VisitWordCompare(selector, left, kArm64Tst, cont, true, | 2396 return VisitWordCompare(selector, left, kArm64Tst, cont, true, |
| 2380 kLogical64Imm); | 2397 kLogical64Imm); |
| 2381 } | 2398 } |
| 2382 // Merge the Word64Equal(x, 0) comparison into a cbz instruction. | 2399 // Merge the Word64Equal(x, 0) comparison into a cbz instruction. |
| 2383 if (cont->IsBranch()) { | 2400 if (cont->IsBranch() || cont->IsDeoptimize()) { |
| 2384 selector->Emit(cont->Encode(kArm64CompareAndBranch), g.NoOutput(), | 2401 EmitBranchOrDeoptimize(selector, |
| 2385 g.UseRegister(left), g.Label(cont->true_block()), | 2402 cont->Encode(kArm64CompareAndBranch), |
| 2386 g.Label(cont->false_block())); | 2403 g.UseRegister(left), cont); |
| 2387 return; | 2404 return; |
| 2388 } | 2405 } |
| 2389 } | 2406 } |
| 2390 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, | 2407 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, |
| 2391 kArithmeticImm); | 2408 kArithmeticImm); |
| 2392 } | 2409 } |
| 2393 case IrOpcode::kInt64LessThan: | 2410 case IrOpcode::kInt64LessThan: |
| 2394 cont->OverwriteAndNegateIfEqual(kSignedLessThan); | 2411 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
| 2395 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, | 2412 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, |
| 2396 kArithmeticImm); | 2413 kArithmeticImm); |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2888 // static | 2905 // static |
| 2889 MachineOperatorBuilder::AlignmentRequirements | 2906 MachineOperatorBuilder::AlignmentRequirements |
| 2890 InstructionSelector::AlignmentRequirements() { | 2907 InstructionSelector::AlignmentRequirements() { |
| 2891 return MachineOperatorBuilder::AlignmentRequirements:: | 2908 return MachineOperatorBuilder::AlignmentRequirements:: |
| 2892 FullUnalignedAccessSupport(); | 2909 FullUnalignedAccessSupport(); |
| 2893 } | 2910 } |
| 2894 | 2911 |
| 2895 } // namespace compiler | 2912 } // namespace compiler |
| 2896 } // namespace internal | 2913 } // namespace internal |
| 2897 } // namespace v8 | 2914 } // namespace v8 |
| OLD | NEW |