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

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

Issue 58003003: Impelments IfThenElse instruction for ARM and MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_ia32.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 (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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 102
103 // No need to generate NOP instructions so that the debugger can patch the 103 // No need to generate NOP instructions so that the debugger can patch the
104 // return pattern (3 instructions) with a call to the debug stub (also 3 104 // return pattern (3 instructions) with a call to the debug stub (also 3
105 // instructions). 105 // instructions).
106 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, 106 compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
107 Isolate::kNoDeoptId, 107 Isolate::kNoDeoptId,
108 token_pos()); 108 token_pos());
109 } 109 }
110 110
111 111
112 bool IfThenElseInstr::IsSupported() { 112 static Condition NegateCondition(Condition condition) {
113 return false; 113 switch (condition) {
114 case EQ: return NE;
115 case NE: return EQ;
116 case LT: return GE;
117 case LE: return GT;
118 case GT: return LE;
119 case GE: return LT;
120 case CC: return CS;
121 case LS: return HI;
122 case HI: return LS;
123 case CS: return CC;
124 default:
125 UNREACHABLE();
126 return EQ;
127 }
128 }
129
130
131 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) {
132 if (!val->BindsToConstant()) {
133 return false;
134 }
135
136 const Object& bound_constant = val->BoundConstant();
137 if (!bound_constant.IsSmi()) {
138 return false;
139 }
140
141 *smi_value = Smi::Cast(bound_constant).Value();
142 return true;
143 }
144
145
146 // Detect pattern when one value is zero and another is a power of 2.
147 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
148 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
149 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
114 } 150 }
115 151
116 152
117 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, 153 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
118 Value* v1, 154 Value* v1,
119 Value* v2) { 155 Value* v2) {
120 UNREACHABLE(); 156 if (!(comparison->IsStrictCompare() &&
121 return false; 157 !comparison->AsStrictCompare()->needs_number_check()) &&
158 !(comparison->IsEqualityCompare() &&
159 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
160 return false;
161 }
162
163 intptr_t v1_value, v2_value;
164
165 if (!BindsToSmiConstant(v1, &v1_value) ||
166 !BindsToSmiConstant(v2, &v2_value)) {
167 return false;
168 }
169
170 return true;
122 } 171 }
123 172
124 173
125 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { 174 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
126 UNREACHABLE(); 175 const intptr_t kNumInputs = 2;
127 return NULL; 176 const intptr_t kNumTemps = 0;
177 LocationSummary* locs =
178 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
179 locs->set_in(0, Location::RegisterOrConstant(left()));
180 locs->set_in(1, Location::RegisterOrConstant(right()));
181 locs->set_out(Location::RequiresRegister());
182 return locs;
128 } 183 }
129 184
130 185
131 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 186 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
132 UNREACHABLE(); 187 const Register result = locs()->out().reg();
188 ASSERT(Token::IsEqualityOperator(kind()));
189
190 Location left = locs()->in(0);
191 Location right = locs()->in(1);
192 if (left.IsConstant() && right.IsConstant()) {
193 // TODO(srdjan): Determine why this instruction was not eliminated.
194 bool res = (left.constant().raw() == right.constant().raw());
195 if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) {
196 res = !res;
197 }
198 __ LoadImmediate(locs()->out().reg(),
199 reinterpret_cast<int32_t>(Smi::New(res ? if_true_ : if_false_)));
200 return;
201 }
202
203 ASSERT(!left.IsConstant() || !right.IsConstant());
204
205 // Clear out register.
206 __ eor(result, result, ShifterOperand(result));
207
208 // Compare left and right. For now only equality comparison is supported.
209 // TODO(vegorov): reuse code from the other comparison instructions instead of
210 // generating it inline here.
211 if (left.IsConstant()) {
212 __ CompareObject(right.reg(), left.constant());
213 } else if (right.IsConstant()) {
214 __ CompareObject(left.reg(), right.constant());
215 } else {
216 __ cmp(left.reg(), ShifterOperand(right.reg()));
217 }
218
219 Condition true_condition =
220 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQ : NE;
221
222 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
223
224 intptr_t true_value = if_true_;
225 intptr_t false_value = if_false_;
226
227 if (is_power_of_two_kind) {
228 if (true_value == 0) {
229 // We need to have zero in result on true_condition.
230 true_condition = NegateCondition(true_condition);
231 }
232 } else {
233 if (true_value == 0) {
234 // Swap values so that false_value is zero.
235 intptr_t temp = true_value;
236 true_value = false_value;
237 false_value = temp;
238 } else {
239 true_condition = NegateCondition(true_condition);
240 }
241 }
242
243 __ mov(result, ShifterOperand(1), true_condition);
244
245 if (is_power_of_two_kind) {
246 const intptr_t shift =
247 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
248 __ Lsl(result, result, shift + kSmiTagSize);
249 } else {
250 __ sub(result, result, ShifterOperand(1));
251 const int32_t val =
252 Smi::RawValue(true_value) - Smi::RawValue(false_value);
253 __ AndImmediate(result, result, val);
254 if (false_value != 0) {
255 __ AddImmediate(result, Smi::RawValue(false_value));
256 }
257 }
133 } 258 }
134 259
135 260
136 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { 261 LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
137 const intptr_t kNumInputs = 0; 262 const intptr_t kNumInputs = 0;
138 const intptr_t kNumTemps = 1; 263 const intptr_t kNumTemps = 1;
139 LocationSummary* result = 264 LocationSummary* result =
140 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 265 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
141 result->set_out(Location::RegisterLocation(R0)); 266 result->set_out(Location::RegisterLocation(R0));
142 result->set_temp(0, Location::RegisterLocation(R4)); // Arg. descriptor. 267 result->set_temp(0, Location::RegisterLocation(R4)); // Arg. descriptor.
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 if (value_is_smi == NULL) { 457 if (value_is_smi == NULL) {
333 __ b(&done, EQ); 458 __ b(&done, EQ);
334 } else { 459 } else {
335 __ b(value_is_smi, EQ); 460 __ b(value_is_smi, EQ);
336 } 461 }
337 __ LoadClassId(value_cid_reg, value_reg); 462 __ LoadClassId(value_cid_reg, value_reg);
338 __ Bind(&done); 463 __ Bind(&done);
339 } 464 }
340 465
341 466
342 static Condition NegateCondition(Condition condition) {
343 switch (condition) {
344 case EQ: return NE;
345 case NE: return EQ;
346 case LT: return GE;
347 case LE: return GT;
348 case GT: return LE;
349 case GE: return LT;
350 case CC: return CS;
351 case LS: return HI;
352 case HI: return LS;
353 case CS: return CC;
354 default:
355 UNREACHABLE();
356 return EQ;
357 }
358 }
359
360
361 static Condition FlipCondition(Condition condition) { 467 static Condition FlipCondition(Condition condition) {
362 switch (condition) { 468 switch (condition) {
363 case EQ: return EQ; 469 case EQ: return EQ;
364 case NE: return NE; 470 case NE: return NE;
365 case LT: return GT; 471 case LT: return GT;
366 case LE: return GE; 472 case LE: return GE;
367 case GT: return LT; 473 case GT: return LT;
368 case GE: return LE; 474 case GE: return LE;
369 case CC: return HI; 475 case CC: return HI;
370 case LS: return CS; 476 case LS: return CS;
(...skipping 4065 matching lines...) Expand 10 before | Expand all | Expand 10 after
4436 compiler->GenerateCall(token_pos(), 4542 compiler->GenerateCall(token_pos(),
4437 &label, 4543 &label,
4438 PcDescriptors::kOther, 4544 PcDescriptors::kOther,
4439 locs()); 4545 locs());
4440 __ Drop(2); // Discard type arguments and receiver. 4546 __ Drop(2); // Discard type arguments and receiver.
4441 } 4547 }
4442 4548
4443 } // namespace dart 4549 } // namespace dart
4444 4550
4445 #endif // defined TARGET_ARCH_ARM 4551 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698