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

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
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_x64.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_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 bool IfThenElseInstr::IsSupported() { 114 static Condition NegateCondition(Condition condition) {
115 return false; 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));
116 } 149 }
117 150
118 151
119 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, 152 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
120 Value* v1, 153 Value* v1,
121 Value* v2) { 154 Value* v2) {
122 UNREACHABLE(); 155 if (!(comparison->IsStrictCompare() &&
123 return false; 156 !comparison->AsStrictCompare()->needs_number_check()) &&
157 !(comparison->IsEqualityCompare() &&
158 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
159 return false;
160 }
161
162 intptr_t v1_value, v2_value;
163
164 if (!BindsToSmiConstant(v1, &v1_value) ||
165 !BindsToSmiConstant(v2, &v2_value)) {
166 return false;
167 }
168
169 return true;
124 } 170 }
125 171
126 172
127 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { 173 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
128 UNREACHABLE(); 174 const intptr_t kNumInputs = 2;
129 return NULL; 175 const intptr_t kNumTemps = 0;
176 LocationSummary* locs =
177 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
178 locs->set_in(0, Location::RegisterOrConstant(left()));
179 locs->set_in(1, Location::RegisterOrConstant(right()));
180 locs->set_out(Location::RequiresRegister());
181 return locs;
130 } 182 }
131 183
132 184
133 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 185 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
134 UNREACHABLE(); 186 const Register result = locs()->out().reg();
187 ASSERT(Token::IsEqualityOperator(kind()));
188
189 Location left = locs()->in(0);
190 Location right = locs()->in(1);
191 if (left.IsConstant() && right.IsConstant()) {
192 // TODO(srdjan): Determine why this instruction was not eliminated.
193 bool res = (left.constant().raw() == right.constant().raw());
194 if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) {
195 res = !res;
196 }
197 __ LoadImmediate(result,
198 reinterpret_cast<int32_t>(Smi::New(res ? if_true_ : if_false_)));
199 return;
200 }
201
202 ASSERT(!left.IsConstant() || !right.IsConstant());
203
204 // Clear out register.
205 __ mov(result, ZR);
206
207 // Compare left and right. For now only equality comparison is supported.
208 // TODO(vegorov): reuse code from the other comparison instructions instead of
209 // generating it inline here.
210 if (left.IsConstant()) {
211 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant());
212 } else if (right.IsConstant()) {
213 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant());
214 } else {
215 __ slt(CMPRES1, left.reg(), right.reg());
216 __ slt(CMPRES2, right.reg(), left.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 if (true_condition == EQ) {
244 __ xor_(result, CMPRES1, CMPRES2);
245 __ xori(result, result, Immediate(1));
246 } else {
247 ASSERT(true_condition == NE);
248 __ xor_(result, CMPRES1, CMPRES2);
249 }
250
251 if (is_power_of_two_kind) {
252 const intptr_t shift =
253 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
254 __ sll(result, result, shift + kSmiTagSize);
255 } else {
256 __ AddImmediate(result, result, -1);
257 const int32_t val =
258 Smi::RawValue(true_value) - Smi::RawValue(false_value);
259 __ AndImmediate(result, result, val);
260 if (false_value != 0) {
261 __ AddImmediate(result, result, Smi::RawValue(false_value));
262 }
263 }
135 } 264 }
136 265
137 266
138 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { 267 LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
139 const intptr_t kNumInputs = 0; 268 const intptr_t kNumInputs = 0;
140 const intptr_t kNumTemps = 1; 269 const intptr_t kNumTemps = 1;
141 LocationSummary* result = 270 LocationSummary* result =
142 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 271 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
143 result->set_out(Location::RegisterLocation(V0)); 272 result->set_out(Location::RegisterLocation(V0));
144 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor. 273 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor.
(...skipping 3395 matching lines...) Expand 10 before | Expand all | Expand 10 after
3540 } 3669 }
3541 3670
3542 // We can fall through if the successor is the next block in the list. 3671 // We can fall through if the successor is the next block in the list.
3543 // Otherwise, we need a jump. 3672 // Otherwise, we need a jump.
3544 if (!compiler->CanFallThroughTo(successor())) { 3673 if (!compiler->CanFallThroughTo(successor())) {
3545 __ b(compiler->GetJumpLabel(successor())); 3674 __ b(compiler->GetJumpLabel(successor()));
3546 } 3675 }
3547 } 3676 }
3548 3677
3549 3678
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, 3679 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
3567 bool value) { 3680 bool value) {
3568 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue"); 3681 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue");
3569 if (value && !compiler->CanFallThroughTo(true_successor())) { 3682 if (value && !compiler->CanFallThroughTo(true_successor())) {
3570 __ b(compiler->GetJumpLabel(true_successor())); 3683 __ b(compiler->GetJumpLabel(true_successor()));
3571 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { 3684 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
3572 __ b(compiler->GetJumpLabel(false_successor())); 3685 __ b(compiler->GetJumpLabel(false_successor()));
3573 } 3686 }
3574 } 3687 }
3575 3688
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
3780 compiler->GenerateCall(token_pos(), 3893 compiler->GenerateCall(token_pos(),
3781 &label, 3894 &label,
3782 PcDescriptors::kOther, 3895 PcDescriptors::kOther,
3783 locs()); 3896 locs());
3784 __ Drop(2); // Discard type arguments and receiver. 3897 __ Drop(2); // Discard type arguments and receiver.
3785 } 3898 }
3786 3899
3787 } // namespace dart 3900 } // namespace dart
3788 3901
3789 #endif // defined TARGET_ARCH_MIPS 3902 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698