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

Side by Side Diff: runtime/vm/intermediate_language_mips.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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 // This sequence is patched by a debugger breakpoint. There is no need for 104 // This sequence is patched by a debugger breakpoint. There is no need for
105 // extra NOP instructions here because the sequence patched in for a 105 // extra NOP instructions here because the sequence patched in for a
106 // breakpoint is shorter than the sequence here. 106 // breakpoint is shorter than the sequence here.
107 __ LeaveDartFrameAndReturn(); 107 __ LeaveDartFrameAndReturn();
108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, 108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
109 Isolate::kNoDeoptId, 109 Isolate::kNoDeoptId,
110 token_pos()); 110 token_pos());
111 } 111 }
112 112
113 113
114 static Condition NegateCondition(Condition condition) {
115 switch (condition) {
116 case EQ: return NE;
117 case NE: return EQ;
118 case LT: return GE;
119 case LE: return GT;
120 case GT: return LE;
121 case GE: return LT;
122 default:
123 OS::Print("Error: Condition not recognized: %d\n", condition);
124 UNIMPLEMENTED();
125 return EQ;
126 }
127 }
128
129
130 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) {
131 if (!val->BindsToConstant()) {
132 return false;
133 }
134
135 const Object& bound_constant = val->BoundConstant();
136 if (!bound_constant.IsSmi()) {
137 return false;
138 }
139
140 *smi_value = Smi::Cast(bound_constant).Value();
141 return true;
142 }
143
144
145 // Detect pattern when one value is zero and another is a power of 2.
146 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
147 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
148 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
149 }
150
151
114 bool IfThenElseInstr::IsSupported() { 152 bool IfThenElseInstr::IsSupported() {
115 return false; 153 return true;
116 } 154 }
117 155
118 156
119 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, 157 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
120 Value* v1, 158 Value* v1,
121 Value* v2) { 159 Value* v2) {
122 UNREACHABLE(); 160 if (!(comparison->IsStrictCompare() &&
123 return false; 161 !comparison->AsStrictCompare()->needs_number_check()) &&
162 !(comparison->IsEqualityCompare() &&
163 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
164 return false;
165 }
166
167 intptr_t v1_value, v2_value;
168
169 if (!BindsToSmiConstant(v1, &v1_value) ||
170 !BindsToSmiConstant(v2, &v2_value)) {
171 return false;
172 }
173
174 return true;
124 } 175 }
125 176
126 177
127 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { 178 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
128 UNREACHABLE(); 179 const intptr_t kNumInputs = 2;
129 return NULL; 180 const intptr_t kNumTemps = 0;
181 LocationSummary* locs =
182 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
183 locs->set_in(0, Location::RegisterOrConstant(left()));
184 locs->set_in(1, Location::RegisterOrConstant(right()));
185 // TODO(vegorov): support byte register constraints in the register allocator.
Florian Schneider 2013/11/05 16:57:53 Comment not relevant here.
zra 2013/11/05 18:32:13 Done.
186 locs->set_out(Location::RegisterLocation(V0));
187 return locs;
130 } 188 }
131 189
132 190
133 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 191 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
134 UNREACHABLE(); 192 const Register result = locs()->out().reg();
193 ASSERT(result == V0);
194 ASSERT(Token::IsEqualityOperator(kind()));
195
196 Location left = locs()->in(0);
197 Location right = locs()->in(1);
198 if (left.IsConstant() && right.IsConstant()) {
199 // TODO(srdjan): Determine why this instruction was not eliminated.
200 bool res = (left.constant().raw() == right.constant().raw());
201 if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) {
202 res = !res;
203 }
204 __ LoadImmediate(result,
205 reinterpret_cast<int32_t>(Smi::New(res ? if_true_ : if_false_)));
206 return;
207 }
208
209 ASSERT(!left.IsConstant() || !right.IsConstant());
210
211 // Clear upper part of the out register. We are going to use setcc on it
212 // which is a byte move.
Florian Schneider 2013/11/05 16:57:53 Update comment.
zra 2013/11/05 18:32:13 Done.
213 __ mov(result, ZR);
214
215 // Compare left and right. For now only equality comparison is supported.
216 // TODO(vegorov): reuse code from the other comparison instructions instead of
217 // generating it inline here.
218 if (left.IsConstant()) {
219 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant());
220 } else if (right.IsConstant()) {
221 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant());
222 } else {
223 __ slt(CMPRES1, left.reg(), right.reg());
224 __ slt(CMPRES2, right.reg(), left.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 switch (true_condition) {
Florian Schneider 2013/11/05 16:57:53 true_condition can only be EQ or NE here. The othe
zra 2013/11/05 18:32:13 Done.
252 case EQ:
253 __ xor_(result, CMPRES1, CMPRES2);
254 __ xori(result, result, Immediate(1));
255 break;
256 case NE: __ xor_(result, CMPRES1, CMPRES2); break;
257 case GT: __ mov(result, CMPRES2); break;
258 case GE: __ xori(result, CMPRES1, Immediate(1)); break;
259 case LT: __ mov(result, CMPRES1); break;
260 case LE: __ xori(result, CMPRES2, Immediate(1)); break;
261 default:
262 UNREACHABLE();
263 break;
264 }
265
266 if (is_power_of_two_kind) {
267 const intptr_t shift =
268 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
269 __ sll(result, result, shift + kSmiTagSize);
270 } else {
271 __ AddImmediate(result, result, -1);
272 const int32_t val =
273 Smi::RawValue(true_value) - Smi::RawValue(false_value);
274 if (Utils::IsUint(kImmBits, val)) {
Florian Schneider 2013/11/05 16:57:53 AndImmediate
zra 2013/11/05 18:32:13 Done.
275 __ andi(result, result, Immediate(val));
276 } else {
277 __ LoadImmediate(TMP, val);
278 __ and_(result, result, TMP);
279 }
280 if (false_value != 0) {
281 __ AddImmediate(result, result, Smi::RawValue(false_value));
282 }
283 }
135 } 284 }
136 285
137 286
138 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { 287 LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
139 const intptr_t kNumInputs = 0; 288 const intptr_t kNumInputs = 0;
140 const intptr_t kNumTemps = 1; 289 const intptr_t kNumTemps = 1;
141 LocationSummary* result = 290 LocationSummary* result =
142 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 291 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
143 result->set_out(Location::RegisterLocation(V0)); 292 result->set_out(Location::RegisterLocation(V0));
144 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor. 293 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor.
(...skipping 3395 matching lines...) Expand 10 before | Expand all | Expand 10 after
3540 } 3689 }
3541 3690
3542 // We can fall through if the successor is the next block in the list. 3691 // We can fall through if the successor is the next block in the list.
3543 // Otherwise, we need a jump. 3692 // Otherwise, we need a jump.
3544 if (!compiler->CanFallThroughTo(successor())) { 3693 if (!compiler->CanFallThroughTo(successor())) {
3545 __ b(compiler->GetJumpLabel(successor())); 3694 __ b(compiler->GetJumpLabel(successor()));
3546 } 3695 }
3547 } 3696 }
3548 3697
3549 3698
3550 static Condition NegateCondition(Condition condition) {
3551 switch (condition) {
3552 case EQ: return NE;
3553 case NE: return EQ;
3554 case LT: return GE;
3555 case LE: return GT;
3556 case GT: return LE;
3557 case GE: return LT;
3558 default:
3559 OS::Print("Error: Condition not recognized: %d\n", condition);
3560 UNIMPLEMENTED();
3561 return EQ;
3562 }
3563 }
3564
3565
3566 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, 3699 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
3567 bool value) { 3700 bool value) {
3568 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue"); 3701 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue");
3569 if (value && !compiler->CanFallThroughTo(true_successor())) { 3702 if (value && !compiler->CanFallThroughTo(true_successor())) {
3570 __ b(compiler->GetJumpLabel(true_successor())); 3703 __ b(compiler->GetJumpLabel(true_successor()));
3571 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { 3704 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
3572 __ b(compiler->GetJumpLabel(false_successor())); 3705 __ b(compiler->GetJumpLabel(false_successor()));
3573 } 3706 }
3574 } 3707 }
3575 3708
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
3780 compiler->GenerateCall(token_pos(), 3913 compiler->GenerateCall(token_pos(),
3781 &label, 3914 &label,
3782 PcDescriptors::kOther, 3915 PcDescriptors::kOther,
3783 locs()); 3916 locs());
3784 __ Drop(2); // Discard type arguments and receiver. 3917 __ Drop(2); // Discard type arguments and receiver.
3785 } 3918 }
3786 3919
3787 } // namespace dart 3920 } // namespace dart
3788 3921
3789 #endif // defined TARGET_ARCH_MIPS 3922 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« runtime/vm/intermediate_language_arm.cc ('K') | « runtime/vm/intermediate_language_arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698