| 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 2101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2112     // We can also handle the case where the add and the compare are in the | 2112     // We can also handle the case where the add and the compare are in the | 
| 2113     // same basic block, and the compare is the only use of add in this basic | 2113     // same basic block, and the compare is the only use of add in this basic | 
| 2114     // block (the add has users in other basic blocks). | 2114     // block (the add has users in other basic blocks). | 
| 2115     cont->Overwrite(MapForFlagSettingBinop(cond)); | 2115     cont->Overwrite(MapForFlagSettingBinop(cond)); | 
| 2116     *opcode = binop_opcode; | 2116     *opcode = binop_opcode; | 
| 2117     *node = binop; | 2117     *node = binop; | 
| 2118     *immediate_mode = binop_immediate_mode; | 2118     *immediate_mode = binop_immediate_mode; | 
| 2119   } | 2119   } | 
| 2120 } | 2120 } | 
| 2121 | 2121 | 
|  | 2122 // Map {cond} to kEqual or kNotEqual, so that we can select | 
|  | 2123 // either TBZ or TBNZ when generating code for: | 
|  | 2124 // (x cmp 0), b.{cond} | 
|  | 2125 FlagsCondition MapForTbz(FlagsCondition cond) { | 
|  | 2126   switch (cond) { | 
|  | 2127     case kSignedLessThan:  // generate TBNZ | 
|  | 2128       return kNotEqual; | 
|  | 2129     case kSignedGreaterThanOrEqual:  // generate TBZ | 
|  | 2130       return kEqual; | 
|  | 2131     default: | 
|  | 2132       UNREACHABLE(); | 
|  | 2133       return cond; | 
|  | 2134   } | 
|  | 2135 } | 
|  | 2136 | 
|  | 2137 // Map {cond} to kEqual or kNotEqual, so that we can select | 
|  | 2138 // either CBZ or CBNZ when generating code for: | 
|  | 2139 // (x cmp 0), b.{cond} | 
|  | 2140 FlagsCondition MapForCbz(FlagsCondition cond) { | 
|  | 2141   switch (cond) { | 
|  | 2142     case kEqual:     // generate CBZ | 
|  | 2143     case kNotEqual:  // generate CBNZ | 
|  | 2144       return cond; | 
|  | 2145     case kUnsignedLessThanOrEqual:  // generate CBZ | 
|  | 2146       return kEqual; | 
|  | 2147     case kUnsignedGreaterThan:  // generate CBNZ | 
|  | 2148       return kNotEqual; | 
|  | 2149     default: | 
|  | 2150       UNREACHABLE(); | 
|  | 2151       return cond; | 
|  | 2152   } | 
|  | 2153 } | 
|  | 2154 | 
|  | 2155 // Try to emit TBZ, TBNZ, CBZ or CBNZ for certain comparisons of {node} | 
|  | 2156 // against zero, depending on the condition. | 
|  | 2157 bool TryEmitCbzOrTbz(InstructionSelector* selector, Node* node, Node* user, | 
|  | 2158                      FlagsCondition cond, FlagsContinuation* cont) { | 
|  | 2159   Int32BinopMatcher m_user(user); | 
|  | 2160   USE(m_user); | 
|  | 2161   DCHECK(m_user.right().Is(0) || m_user.left().Is(0)); | 
|  | 2162 | 
|  | 2163   // Only handle branches. | 
|  | 2164   if (!cont->IsBranch()) return false; | 
|  | 2165 | 
|  | 2166   switch (cond) { | 
|  | 2167     case kSignedLessThan: | 
|  | 2168     case kSignedGreaterThanOrEqual: { | 
|  | 2169       Arm64OperandGenerator g(selector); | 
|  | 2170       cont->Overwrite(MapForTbz(cond)); | 
|  | 2171       Int32Matcher m(node); | 
|  | 2172       if (m.IsFloat64ExtractHighWord32() && selector->CanCover(user, node)) { | 
|  | 2173         // SignedLessThan(Float64ExtractHighWord32(x), 0) and | 
|  | 2174         // SignedGreaterThanOrEqual(Float64ExtractHighWord32(x), 0) essentially | 
|  | 2175         // check the sign bit of a 64-bit floating point value. | 
|  | 2176         InstructionOperand temp = g.TempRegister(); | 
|  | 2177         selector->Emit(kArm64U64MoveFloat64, temp, | 
|  | 2178                        g.UseRegister(node->InputAt(0))); | 
|  | 2179         selector->Emit(cont->Encode(kArm64TestAndBranch), g.NoOutput(), temp, | 
|  | 2180                        g.TempImmediate(63), g.Label(cont->true_block()), | 
|  | 2181                        g.Label(cont->false_block())); | 
|  | 2182         return true; | 
|  | 2183       } | 
|  | 2184       selector->Emit(cont->Encode(kArm64TestAndBranch32), g.NoOutput(), | 
|  | 2185                      g.UseRegister(node), g.TempImmediate(31), | 
|  | 2186                      g.Label(cont->true_block()), g.Label(cont->false_block())); | 
|  | 2187       return true; | 
|  | 2188     } | 
|  | 2189     case kEqual: | 
|  | 2190     case kNotEqual: | 
|  | 2191     case kUnsignedLessThanOrEqual: | 
|  | 2192     case kUnsignedGreaterThan: { | 
|  | 2193       Arm64OperandGenerator g(selector); | 
|  | 2194       cont->Overwrite(MapForCbz(cond)); | 
|  | 2195       selector->Emit(cont->Encode(kArm64CompareAndBranch32), g.NoOutput(), | 
|  | 2196                      g.UseRegister(node), g.Label(cont->true_block()), | 
|  | 2197                      g.Label(cont->false_block())); | 
|  | 2198       return true; | 
|  | 2199     } | 
|  | 2200     default: | 
|  | 2201       return false; | 
|  | 2202   } | 
|  | 2203 } | 
|  | 2204 | 
| 2122 void VisitWord32Compare(InstructionSelector* selector, Node* node, | 2205 void VisitWord32Compare(InstructionSelector* selector, Node* node, | 
| 2123                         FlagsContinuation* cont) { | 2206                         FlagsContinuation* cont) { | 
| 2124   Int32BinopMatcher m(node); | 2207   Int32BinopMatcher m(node); | 
| 2125   ArchOpcode opcode = kArm64Cmp32; | 2208   ArchOpcode opcode = kArm64Cmp32; | 
| 2126   FlagsCondition cond = cont->condition(); | 2209   FlagsCondition cond = cont->condition(); | 
|  | 2210   if (m.right().Is(0)) { | 
|  | 2211     if (TryEmitCbzOrTbz(selector, m.left().node(), node, cond, cont)) return; | 
|  | 2212   } else if (m.left().Is(0)) { | 
|  | 2213     FlagsCondition commuted_cond = CommuteFlagsCondition(cond); | 
|  | 2214     if (TryEmitCbzOrTbz(selector, m.right().node(), node, commuted_cond, cont)) | 
|  | 2215       return; | 
|  | 2216   } | 
| 2127   ImmediateMode immediate_mode = kArithmeticImm; | 2217   ImmediateMode immediate_mode = kArithmeticImm; | 
| 2128   if (m.right().Is(0) && (m.left().IsInt32Add() || m.left().IsWord32And())) { | 2218   if (m.right().Is(0) && (m.left().IsInt32Add() || m.left().IsWord32And())) { | 
| 2129     // Emit flag setting add/and instructions for comparisons against zero. | 2219     // Emit flag setting add/and instructions for comparisons against zero. | 
| 2130     if (CanUseFlagSettingBinop(cond)) { | 2220     if (CanUseFlagSettingBinop(cond)) { | 
| 2131       Node* binop = m.left().node(); | 2221       Node* binop = m.left().node(); | 
| 2132       MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode, | 2222       MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode, | 
| 2133                                               cond, cont, &immediate_mode); | 2223                                               cond, cont, &immediate_mode); | 
| 2134     } | 2224     } | 
| 2135   } else if (m.left().Is(0) && | 2225   } else if (m.left().Is(0) && | 
| 2136              (m.right().IsInt32Add() || m.right().IsWord32And())) { | 2226              (m.right().IsInt32Add() || m.right().IsWord32And())) { | 
| 2137     // Same as above, but we need to commute the condition before we | 2227     // Same as above, but we need to commute the condition before we | 
| 2138     // continue with the rest of the checks. | 2228     // continue with the rest of the checks. | 
| 2139     cond = CommuteFlagsCondition(cond); | 2229     FlagsCondition commuted_cond = CommuteFlagsCondition(cond); | 
| 2140     if (CanUseFlagSettingBinop(cond)) { | 2230     if (CanUseFlagSettingBinop(commuted_cond)) { | 
| 2141       Node* binop = m.right().node(); | 2231       Node* binop = m.right().node(); | 
| 2142       MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode, | 2232       MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode, | 
| 2143                                               cond, cont, &immediate_mode); | 2233                                               commuted_cond, cont, | 
|  | 2234                                               &immediate_mode); | 
| 2144     } | 2235     } | 
| 2145   } else if (m.right().IsInt32Sub() && (cond == kEqual || cond == kNotEqual)) { | 2236   } else if (m.right().IsInt32Sub() && (cond == kEqual || cond == kNotEqual)) { | 
| 2146     // Select negated compare for comparisons with negated right input. | 2237     // Select negated compare for comparisons with negated right input. | 
| 2147     // Only do this for kEqual and kNotEqual, which do not depend on the | 2238     // Only do this for kEqual and kNotEqual, which do not depend on the | 
| 2148     // C and V flags, as those flags will be different with CMN when the | 2239     // C and V flags, as those flags will be different with CMN when the | 
| 2149     // right-hand side of the original subtraction is INT_MIN. | 2240     // right-hand side of the original subtraction is INT_MIN. | 
| 2150     Node* sub = m.right().node(); | 2241     Node* sub = m.right().node(); | 
| 2151     Int32BinopMatcher msub(sub); | 2242     Int32BinopMatcher msub(sub); | 
| 2152     if (msub.left().Is(0)) { | 2243     if (msub.left().Is(0)) { | 
| 2153       bool can_cover = selector->CanCover(node, sub); | 2244       bool can_cover = selector->CanCover(node, sub); | 
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2797 // static | 2888 // static | 
| 2798 MachineOperatorBuilder::AlignmentRequirements | 2889 MachineOperatorBuilder::AlignmentRequirements | 
| 2799 InstructionSelector::AlignmentRequirements() { | 2890 InstructionSelector::AlignmentRequirements() { | 
| 2800   return MachineOperatorBuilder::AlignmentRequirements:: | 2891   return MachineOperatorBuilder::AlignmentRequirements:: | 
| 2801       FullUnalignedAccessSupport(); | 2892       FullUnalignedAccessSupport(); | 
| 2802 } | 2893 } | 
| 2803 | 2894 | 
| 2804 }  // namespace compiler | 2895 }  // namespace compiler | 
| 2805 }  // namespace internal | 2896 }  // namespace internal | 
| 2806 }  // namespace v8 | 2897 }  // namespace v8 | 
| OLD | NEW | 
|---|