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

Side by Side Diff: runtime/vm/intermediate_language_x64.cc

Issue 14057004: Convert diamond shaped control flow into a single conditional instruction. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address Florian's comments Created 7 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 __ nop(1); 106 __ nop(1);
107 __ nop(1); 107 __ nop(1);
108 __ nop(1); 108 __ nop(1);
109 __ nop(1); 109 __ nop(1);
110 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, 110 compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
111 Isolate::kNoDeoptId, 111 Isolate::kNoDeoptId,
112 token_pos()); 112 token_pos());
113 } 113 }
114 114
115 115
116 static Condition NegateCondition(Condition condition) {
117 switch (condition) {
118 case EQUAL: return NOT_EQUAL;
119 case NOT_EQUAL: return EQUAL;
120 case LESS: return GREATER_EQUAL;
121 case LESS_EQUAL: return GREATER;
122 case GREATER: return LESS_EQUAL;
123 case GREATER_EQUAL: return LESS;
124 case BELOW: return ABOVE_EQUAL;
125 case BELOW_EQUAL: return ABOVE;
126 case ABOVE: return BELOW_EQUAL;
127 case ABOVE_EQUAL: return BELOW;
128 default:
129 OS::Print("Error %d\n", condition);
130 UNIMPLEMENTED();
131 return EQUAL;
132 }
133 }
134
135
136 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) {
137 if (!val->BindsToConstant()) {
138 return false;
139 }
140
141 const Object& bound_constant = val->BoundConstant();
142 if (!bound_constant.IsSmi()) {
143 return false;
144 }
145
146 *smi_value = Smi::Cast(bound_constant).Value();
147 return true;
148 }
149
150
151 // Detect pattern when one value is zero and another is a power of 2.
152 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
153 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
154 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
155 }
156
157
158 // Detect pattern when one value is increment of another.
159 static bool IsIncrementKind(intptr_t v1, intptr_t v2) {
160 return ((v1 == v2 + 1) || (v1 + 1 == v2));
161 }
162
163
164 bool IfThenElseInstr::IsSupported() {
165 return true;
166 }
167
168
169 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
170 Value* v1,
171 Value* v2) {
172 if (!(comparison->IsStrictCompare() &&
173 !comparison->AsStrictCompare()->needs_number_check()) &&
174 !(comparison->IsEqualityCompare() &&
175 (comparison->AsEqualityCompare()->receiver_class_id() == kSmiCid))) {
176 return false;
177 }
178
179 intptr_t v1_value, v2_value;
180
181 if (!BindsToSmiConstant(v1, &v1_value) ||
182 !BindsToSmiConstant(v2, &v2_value)) {
183 return false;
184 }
185
186 if (IsPowerOfTwoKind(v1_value, v2_value) ||
187 IsIncrementKind(v1_value, v2_value)) {
188 return true;
189 }
190
191 return false;
192 }
193
194
195 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
196 const intptr_t kNumInputs = 2;
197 const intptr_t kNumTemps = 0;
198 LocationSummary* locs =
199 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
200 locs->set_in(0, Location::RegisterOrConstant(left()));
201 locs->set_in(1, Location::RegisterOrConstant(right()));
202 // TODO(vegorov): support byte register constraints in the register allocator.
203 locs->set_out(Location::RegisterLocation(RDX));
204 return locs;
205 }
206
207
208 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
209 ASSERT(locs()->out().reg() == RDX);
210 ASSERT(Token::IsEqualityOperator(kind()));
211
212 Location left = locs()->in(0);
213 Location right = locs()->in(1);
214 ASSERT(!left.IsConstant() || !right.IsConstant());
215
216 // Clear upper part of the out register. We are going to use setcc on it
217 // which is a byte move.
218 __ xorq(RDX, RDX);
219
220 // Compare left and right. For now only equality comparison is supported.
221 // TODO(vegorov): reuse code from the other comparison instructions instead of
222 // generating it inline here.
223 if (left.IsConstant()) {
224 __ CompareObject(right.reg(), left.constant());
225 } else if (right.IsConstant()) {
226 __ CompareObject(left.reg(), right.constant());
227 } else {
228 __ cmpq(left.reg(), right.reg());
229 }
230
231 Condition true_condition =
232 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL
233 : NOT_EQUAL;
234
235 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
236
237 const intptr_t base = Utils::Minimum(if_true_, if_false_);
238
239 if (if_true_ == base) {
240 // We need to have zero in RDX on true_condition.
241 true_condition = NegateCondition(true_condition);
242 }
243
244 __ setcc(true_condition, DL);
245
246 if (is_power_of_two_kind) {
247 const intptr_t shift =
248 Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_));
249 __ shlq(RDX, Immediate(shift + kSmiTagSize));
250 } else {
251 ASSERT(kSmiTagSize == 1);
252 __ leaq(RDX, Address(RDX, TIMES_2, base << kSmiTagSize));
253 }
254 }
255
256
116 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { 257 LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
117 const intptr_t kNumInputs = 0; 258 const intptr_t kNumInputs = 0;
118 const intptr_t kNumTemps = 1; 259 const intptr_t kNumTemps = 1;
119 LocationSummary* result = 260 LocationSummary* result =
120 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 261 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
121 result->set_out(Location::RegisterLocation(RAX)); 262 result->set_out(Location::RegisterLocation(RAX));
122 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. 263 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor.
123 return result; 264 return result;
124 } 265 }
125 266
(...skipping 2963 matching lines...) Expand 10 before | Expand all | Expand 10 after
3089 } 3230 }
3090 3231
3091 // We can fall through if the successor is the next block in the list. 3232 // We can fall through if the successor is the next block in the list.
3092 // Otherwise, we need a jump. 3233 // Otherwise, we need a jump.
3093 if (!compiler->CanFallThroughTo(successor())) { 3234 if (!compiler->CanFallThroughTo(successor())) {
3094 __ jmp(compiler->GetJumpLabel(successor())); 3235 __ jmp(compiler->GetJumpLabel(successor()));
3095 } 3236 }
3096 } 3237 }
3097 3238
3098 3239
3099 static Condition NegateCondition(Condition condition) {
3100 switch (condition) {
3101 case EQUAL: return NOT_EQUAL;
3102 case NOT_EQUAL: return EQUAL;
3103 case LESS: return GREATER_EQUAL;
3104 case LESS_EQUAL: return GREATER;
3105 case GREATER: return LESS_EQUAL;
3106 case GREATER_EQUAL: return LESS;
3107 case BELOW: return ABOVE_EQUAL;
3108 case BELOW_EQUAL: return ABOVE;
3109 case ABOVE: return BELOW_EQUAL;
3110 case ABOVE_EQUAL: return BELOW;
3111 default:
3112 OS::Print("Error %d\n", condition);
3113 UNIMPLEMENTED();
3114 return EQUAL;
3115 }
3116 }
3117
3118
3119 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, 3240 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
3120 bool value) { 3241 bool value) {
3121 if (value && !compiler->CanFallThroughTo(true_successor())) { 3242 if (value && !compiler->CanFallThroughTo(true_successor())) {
3122 __ jmp(compiler->GetJumpLabel(true_successor())); 3243 __ jmp(compiler->GetJumpLabel(true_successor()));
3123 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { 3244 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
3124 __ jmp(compiler->GetJumpLabel(false_successor())); 3245 __ jmp(compiler->GetJumpLabel(false_successor()));
3125 } 3246 }
3126 } 3247 }
3127 3248
3128 3249
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
3356 PcDescriptors::kOther, 3477 PcDescriptors::kOther,
3357 locs()); 3478 locs());
3358 __ Drop(2); // Discard type arguments and receiver. 3479 __ Drop(2); // Discard type arguments and receiver.
3359 } 3480 }
3360 3481
3361 } // namespace dart 3482 } // namespace dart
3362 3483
3363 #undef __ 3484 #undef __
3364 3485
3365 #endif // defined TARGET_ARCH_X64 3486 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698