Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Side by Side Diff: src/compiler/arm64/instruction-selector-arm64.cc

Issue 2359723004: [arm64] Check sign with TBZ/TBNZ. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698