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

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
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 static Condition NegateCondition(Condition condition) {
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));
150 }
151
152
112 bool IfThenElseInstr::IsSupported() { 153 bool IfThenElseInstr::IsSupported() {
Florian Schneider 2013/11/05 16:57:53 Now that IsSupported is true on all platform, you
zra 2013/11/05 18:32:13 Done.
113 return false; 154 return true;
114 } 155 }
115 156
116 157
117 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, 158 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
118 Value* v1, 159 Value* v1,
119 Value* v2) { 160 Value* v2) {
120 UNREACHABLE(); 161 if (!(comparison->IsStrictCompare() &&
121 return false; 162 !comparison->AsStrictCompare()->needs_number_check()) &&
163 !(comparison->IsEqualityCompare() &&
164 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
165 return false;
166 }
167
168 intptr_t v1_value, v2_value;
169
170 if (!BindsToSmiConstant(v1, &v1_value) ||
171 !BindsToSmiConstant(v2, &v2_value)) {
172 return false;
173 }
174
175 return true;
122 } 176 }
123 177
124 178
125 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { 179 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
126 UNREACHABLE(); 180 const intptr_t kNumInputs = 2;
127 return NULL; 181 const intptr_t kNumTemps = 0;
182 LocationSummary* locs =
183 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
184 locs->set_in(0, Location::RegisterOrConstant(left()));
185 locs->set_in(1, Location::RegisterOrConstant(right()));
186 // TODO(vegorov): support byte register constraints in the register allocator.
Florian Schneider 2013/11/05 16:57:53 This TODO is not relevant here.
zra 2013/11/05 18:32:13 Done.
187 locs->set_out(Location::RegisterLocation(R0));
188 return locs;
128 } 189 }
129 190
130 191
131 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 192 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
132 UNREACHABLE(); 193 const Register result = locs()->out().reg();
194 ASSERT(result == R0);
195 ASSERT(Token::IsEqualityOperator(kind()));
196
197 Location left = locs()->in(0);
198 Location right = locs()->in(1);
199 if (left.IsConstant() && right.IsConstant()) {
200 // TODO(srdjan): Determine why this instruction was not eliminated.
201 bool res = (left.constant().raw() == right.constant().raw());
202 if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) {
203 res = !res;
204 }
205 __ LoadImmediate(locs()->out().reg(),
206 reinterpret_cast<int32_t>(Smi::New(res ? if_true_ : if_false_)));
207 return;
208 }
209
210 ASSERT(!left.IsConstant() || !right.IsConstant());
211
212 // Clear upper part of the out register. We are going to use setcc on it
Florian Schneider 2013/11/05 16:57:53 Update this comment for ARM.
zra 2013/11/05 18:32:13 Done.
213 // which is a byte move.
214 __ eor(result, result, ShifterOperand(result));
215
216 // Compare left and right. For now only equality comparison is supported.
217 // TODO(vegorov): reuse code from the other comparison instructions instead of
218 // generating it inline here.
219 if (left.IsConstant()) {
220 __ CompareObject(right.reg(), left.constant());
221 } else if (right.IsConstant()) {
222 __ CompareObject(left.reg(), right.constant());
223 } else {
224 __ cmp(left.reg(), ShifterOperand(right.reg()));
225 }
226
227 Condition true_condition =
228 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQ : NE;
229
230 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
231
232 intptr_t true_value = if_true_;
233 intptr_t false_value = if_false_;
234
235 if (is_power_of_two_kind) {
236 if (true_value == 0) {
237 // We need to have zero in result on true_condition.
238 true_condition = NegateCondition(true_condition);
239 }
240 } else {
241 if (true_value == 0) {
242 // Swap values so that false_value is zero.
243 intptr_t temp = true_value;
244 true_value = false_value;
245 false_value = temp;
246 } else {
247 true_condition = NegateCondition(true_condition);
248 }
249 }
250
251 __ mov(result, ShifterOperand(1), true_condition);
252
253 if (is_power_of_two_kind) {
254 const intptr_t shift =
255 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
256 __ Lsl(result, result, shift + kSmiTagSize);
257 } else {
258 __ sub(result, result, ShifterOperand(1));
259 const int32_t val =
260 Smi::RawValue(true_value) - Smi::RawValue(false_value);
261 ShifterOperand op;
262 if (ShifterOperand::CanHold(val, &op)) {
Florian Schneider 2013/11/05 16:57:53 I'd add an AndImmediate macro-instruction for this
zra 2013/11/05 18:32:13 Done.
263 __ and_(result, result, ShifterOperand(op));
264 } else {
265 __ LoadImmediate(TMP, val);
266 __ and_(result, result, ShifterOperand(TMP));
267 }
268 if (false_value != 0) {
269 __ AddImmediate(result, Smi::RawValue(false_value));
270 }
271 }
133 } 272 }
134 273
135 274
136 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { 275 LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
137 const intptr_t kNumInputs = 0; 276 const intptr_t kNumInputs = 0;
138 const intptr_t kNumTemps = 1; 277 const intptr_t kNumTemps = 1;
139 LocationSummary* result = 278 LocationSummary* result =
140 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 279 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
141 result->set_out(Location::RegisterLocation(R0)); 280 result->set_out(Location::RegisterLocation(R0));
142 result->set_temp(0, Location::RegisterLocation(R4)); // Arg. descriptor. 281 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) { 471 if (value_is_smi == NULL) {
333 __ b(&done, EQ); 472 __ b(&done, EQ);
334 } else { 473 } else {
335 __ b(value_is_smi, EQ); 474 __ b(value_is_smi, EQ);
336 } 475 }
337 __ LoadClassId(value_cid_reg, value_reg); 476 __ LoadClassId(value_cid_reg, value_reg);
338 __ Bind(&done); 477 __ Bind(&done);
339 } 478 }
340 479
341 480
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) { 481 static Condition FlipCondition(Condition condition) {
362 switch (condition) { 482 switch (condition) {
363 case EQ: return EQ; 483 case EQ: return EQ;
364 case NE: return NE; 484 case NE: return NE;
365 case LT: return GT; 485 case LT: return GT;
366 case LE: return GE; 486 case LE: return GE;
367 case GT: return LT; 487 case GT: return LT;
368 case GE: return LE; 488 case GE: return LE;
369 case CC: return HI; 489 case CC: return HI;
370 case LS: return CS; 490 case LS: return CS;
(...skipping 4065 matching lines...) Expand 10 before | Expand all | Expand 10 after
4436 compiler->GenerateCall(token_pos(), 4556 compiler->GenerateCall(token_pos(),
4437 &label, 4557 &label,
4438 PcDescriptors::kOther, 4558 PcDescriptors::kOther,
4439 locs()); 4559 locs());
4440 __ Drop(2); // Discard type arguments and receiver. 4560 __ Drop(2); // Discard type arguments and receiver.
4441 } 4561 }
4442 4562
4443 } // namespace dart 4563 } // namespace dart
4444 4564
4445 #endif // defined TARGET_ARCH_ARM 4565 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/intermediate_language_mips.cc » ('j') | runtime/vm/intermediate_language_mips.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698