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 |