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

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

Issue 10536145: Fuse comparisons that are used by branches together. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 6 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 13 matching lines...) Expand all
24 // on the stack and return the result in a fixed register EAX. 24 // on the stack and return the result in a fixed register EAX.
25 LocationSummary* Computation::MakeCallSummary() { 25 LocationSummary* Computation::MakeCallSummary() {
26 LocationSummary* result = new LocationSummary(0, 0); 26 LocationSummary* result = new LocationSummary(0, 0);
27 result->set_out(Location::RegisterLocation(EAX)); 27 result->set_out(Location::RegisterLocation(EAX));
28 return result; 28 return result;
29 } 29 }
30 30
31 31
32 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 32 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
33 computation()->EmitNativeCode(compiler); 33 computation()->EmitNativeCode(compiler);
34 __ pushl(locs()->out().reg()); 34 if (locs()->out().kind() == Location::kRegister) {
35 // TODO(vegorov): this should really happen only for comparisons fused
36 // with branches. Currrently IR does not provide an easy way to remove
37 // instructions from the graph so we just leave fused comparison in it
38 // but change its result location to be NoLocation.
39 __ pushl(locs()->out().reg());
40 }
35 } 41 }
36 42
37 43
38 LocationSummary* ReturnInstr::MakeLocationSummary() const { 44 LocationSummary* ReturnInstr::MakeLocationSummary() const {
39 const intptr_t kNumInputs = 1; 45 const intptr_t kNumInputs = 1;
40 const intptr_t kNumTemps = 1; 46 const intptr_t kNumTemps = 1;
41 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); 47 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
42 locs->set_in(0, Location::RegisterLocation(EAX)); 48 locs->set_in(0, Location::RegisterLocation(EAX));
43 locs->set_temp(0, Location::RequiresRegister()); 49 locs->set_temp(0, Location::RequiresRegister());
44 return locs; 50 return locs;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 } 162 }
157 163
158 164
159 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { 165 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) {
160 Register obj = locs()->in(0).reg(); 166 Register obj = locs()->in(0).reg();
161 Register result = locs()->out().reg(); 167 Register result = locs()->out().reg();
162 168
163 // Check that the type of the value is allowed in conditional context. 169 // Check that the type of the value is allowed in conditional context.
164 // Call the runtime if the object is not bool::true or bool::false. 170 // Call the runtime if the object is not bool::true or bool::false.
165 Label done; 171 Label done;
166 __ CompareObject(obj, Bool::ZoneHandle(Bool::True())); 172 __ CompareObject(obj, compiler->true_value());
167 __ j(EQUAL, &done, Assembler::kNearJump); 173 __ j(EQUAL, &done, Assembler::kNearJump);
168 __ CompareObject(obj, Bool::ZoneHandle(Bool::False())); 174 __ CompareObject(obj, compiler->false_value());
169 __ j(EQUAL, &done, Assembler::kNearJump); 175 __ j(EQUAL, &done, Assembler::kNearJump);
170 176
171 __ pushl(Immediate(Smi::RawValue(token_index()))); // Source location. 177 __ pushl(Immediate(Smi::RawValue(token_index()))); // Source location.
172 __ pushl(obj); // Push the source object. 178 __ pushl(obj); // Push the source object.
173 compiler->GenerateCallRuntime(cid(), 179 compiler->GenerateCallRuntime(cid(),
174 token_index(), 180 token_index(),
175 try_index(), 181 try_index(),
176 kConditionTypeErrorRuntimeEntry); 182 kConditionTypeErrorRuntimeEntry);
177 // We should never return here. 183 // We should never return here.
178 __ int3(); 184 __ int3();
179 185
180 __ Bind(&done); 186 __ Bind(&done);
181 ASSERT(obj == result); 187 ASSERT(obj == result);
182 } 188 }
183 189
184 190
185 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { 191 LocationSummary* EqualityCompareComp::MakeLocationSummary() const {
186 LocationSummary* locs = new LocationSummary(2, 0); 192 LocationSummary* locs = new LocationSummary(2, 0);
187 locs->set_in(0, Location::RequiresRegister()); 193 locs->set_in(0, Location::RequiresRegister());
188 locs->set_in(1, Location::RequiresRegister()); 194 locs->set_in(1, Location::RequiresRegister());
189 locs->set_out(Location::RegisterLocation(EAX)); 195 if (fused_with_branch() == NULL) {
196 locs->set_out(Location::RegisterLocation(EAX));
197 }
190 return locs; 198 return locs;
191 } 199 }
192 200
193 201
194 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 202 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
195 Register left = locs()->in(0).reg(); 203 Register left = locs()->in(0).reg();
196 Register right = locs()->in(1).reg(); 204 Register right = locs()->in(1).reg();
197 Register result = locs()->out().reg();
198 ASSERT(locs()->out().reg() == EAX);
199 205
200 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
201 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
202 const Immediate raw_null = 206 const Immediate raw_null =
203 Immediate(reinterpret_cast<intptr_t>(Object::null())); 207 Immediate(reinterpret_cast<intptr_t>(Object::null()));
204 Label done, load_true, non_null_compare; 208 Label done, non_null_compare;
205 __ cmpl(left, raw_null); 209 __ cmpl(left, raw_null);
206 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); 210 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump);
207 // Comparison with NULL is "===". 211 // Comparison with NULL is "===".
208 __ cmpl(left, right); 212 __ cmpl(left, right);
209 __ j(EQUAL, &load_true, Assembler::kNearJump); 213 if (fused_with_branch() == NULL) {
210 __ LoadObject(result, bool_false); 214 Register result = locs()->out().reg();
211 __ jmp(&done, Assembler::kNearJump); 215 Label load_true;
212 __ Bind(&load_true); 216 __ j(EQUAL, &load_true, Assembler::kNearJump);
213 __ LoadObject(result, bool_true); 217 __ LoadObject(result, compiler->false_value());
218 __ jmp(&done, Assembler::kNearJump);
219 __ Bind(&load_true);
220 __ LoadObject(result, compiler->true_value());
221 } else {
222 fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
223 }
214 __ jmp(&done); 224 __ jmp(&done);
215 225
216 __ Bind(&non_null_compare); 226 __ Bind(&non_null_compare);
217 __ pushl(left); 227 __ pushl(left);
218 __ pushl(right); 228 __ pushl(right);
219 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); 229 const String& operator_name = String::ZoneHandle(String::NewSymbol("=="));
220 const int kNumberOfArguments = 2; 230 const int kNumberOfArguments = 2;
221 const Array& kNoArgumentNames = Array::Handle(); 231 const Array& kNoArgumentNames = Array::Handle();
222 const int kNumArgumentsChecked = 1; 232 const int kNumArgumentsChecked = 1;
223 233
224 compiler->GenerateInstanceCall(cid(), 234 compiler->GenerateInstanceCall(cid(),
225 token_index(), 235 token_index(),
226 try_index(), 236 try_index(),
227 operator_name, 237 operator_name,
228 kNumberOfArguments, 238 kNumberOfArguments,
229 kNoArgumentNames, 239 kNoArgumentNames,
230 kNumArgumentsChecked); 240 kNumArgumentsChecked);
241 ASSERT(fused_with_branch() != NULL || locs()->out().reg() == EAX);
242
243 if (fused_with_branch() != NULL) {
244 __ CompareObject(EAX, compiler->true_value());
245 fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
246 }
247
231 __ Bind(&done); 248 __ Bind(&done);
232 } 249 }
233 250
234 251
235 LocationSummary* RelationalOpComp::MakeLocationSummary() const { 252 LocationSummary* RelationalOpComp::MakeLocationSummary() const {
236 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) { 253 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) {
237 const intptr_t kNumInputs = 2; 254 const intptr_t kNumInputs = 2;
238 const intptr_t kNumTemps = 1; 255 const intptr_t kNumTemps = 1;
239 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); 256 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
240 summary->set_in(0, Location::RequiresRegister()); 257 summary->set_in(0, Location::RequiresRegister());
241 summary->set_in(1, Location::RequiresRegister()); 258 summary->set_in(1, Location::RequiresRegister());
242 summary->set_out(Location::RequiresRegister()); 259 if (fused_with_branch() == NULL) {
260 summary->set_out(Location::RequiresRegister());
261 }
243 summary->set_temp(0, Location::RequiresRegister()); 262 summary->set_temp(0, Location::RequiresRegister());
244 return summary; 263 return summary;
245 } 264 }
246 ASSERT(operands_class_id() == kObject); 265 ASSERT(operands_class_id() == kObject);
247 return MakeCallSummary(); 266 return MakeCallSummary();
248 } 267 }
249 268
250 269
251 static Condition TokenKindToSmiCondition(Token::Kind kind) { 270 static Condition TokenKindToSmiCondition(Token::Kind kind) {
252 switch (kind) { 271 switch (kind) {
253 case Token::kEQ: return EQUAL; 272 case Token::kEQ: return EQUAL;
254 case Token::kNE: return NOT_EQUAL; 273 case Token::kNE: return NOT_EQUAL;
255 case Token::kLT: return LESS; 274 case Token::kLT: return LESS;
256 case Token::kGT: return GREATER; 275 case Token::kGT: return GREATER;
257 case Token::kLTE: return LESS_EQUAL; 276 case Token::kLTE: return LESS_EQUAL;
258 case Token::kGTE: return GREATER_EQUAL; 277 case Token::kGTE: return GREATER_EQUAL;
259 default: 278 default:
260 UNREACHABLE(); 279 UNREACHABLE();
261 return OVERFLOW; 280 return OVERFLOW;
262 } 281 }
263 } 282 }
264 283
265 284
266 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, 285 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler,
267 RelationalOpComp* comp) { 286 RelationalOpComp* comp) {
268 Register left = comp->locs()->in(0).reg(); 287 Register left = comp->locs()->in(0).reg();
269 Register right = comp->locs()->in(1).reg(); 288 Register right = comp->locs()->in(1).reg();
270 Register result = comp->locs()->out().reg();
271 Register temp = comp->locs()->temp(0).reg(); 289 Register temp = comp->locs()->temp(0).reg();
272 Label* deopt = compiler->AddDeoptStub(comp->cid(), 290 Label* deopt = compiler->AddDeoptStub(comp->cid(),
273 comp->token_index(), 291 comp->token_index(),
274 comp->try_index(), 292 comp->try_index(),
275 kDeoptSmiCompareSmis, 293 kDeoptSmiCompareSmis,
276 left, 294 left,
277 right); 295 right);
278 __ movl(temp, left); 296 __ movl(temp, left);
279 __ orl(temp, right); 297 __ orl(temp, right);
280 __ testl(temp, Immediate(kSmiTagMask)); 298 __ testl(temp, Immediate(kSmiTagMask));
281 __ j(NOT_ZERO, deopt); 299 __ j(NOT_ZERO, deopt);
282 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
283 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
284 Condition condition = TokenKindToSmiCondition(comp->kind());
285 300
286 Label done, is_true; 301 Condition true_condition = TokenKindToSmiCondition(comp->kind());
287 __ cmpl(left, right); 302 __ cmpl(left, right);
288 __ j(condition, &is_true); 303
289 __ LoadObject(result, bool_false); 304 if (comp->fused_with_branch() == NULL) {
290 __ jmp(&done); 305 Register result = comp->locs()->out().reg();
291 __ Bind(&is_true); 306 Label done, is_true;
292 __ LoadObject(result, bool_true); 307
293 __ Bind(&done); 308 __ j(true_condition, &is_true);
309 __ LoadObject(result, compiler->false_value());
310 __ jmp(&done);
311 __ Bind(&is_true);
312 __ LoadObject(result, compiler->true_value());
313 __ Bind(&done);
314 } else {
315 comp->fused_with_branch()->EmitBranchOnCondition(compiler, true_condition);
316 }
294 } 317 }
295 318
296 319
297 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 320 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
298 switch (kind) { 321 switch (kind) {
299 case Token::kEQ: return EQUAL; 322 case Token::kEQ: return EQUAL;
300 case Token::kLT: return BELOW; 323 case Token::kLT: return BELOW;
301 case Token::kGT: return ABOVE; 324 case Token::kGT: return ABOVE;
302 case Token::kLTE: return BELOW_EQUAL; 325 case Token::kLTE: return BELOW_EQUAL;
303 case Token::kGTE: return ABOVE_EQUAL; 326 case Token::kGTE: return ABOVE_EQUAL;
304 default: 327 default:
305 UNREACHABLE(); 328 UNREACHABLE();
306 return OVERFLOW; 329 return OVERFLOW;
307 } 330 }
308 } 331 }
309 332
310 333
311 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, 334 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler,
312 RelationalOpComp* comp) { 335 RelationalOpComp* comp) {
313 Register left = comp->locs()->in(0).reg(); 336 Register left = comp->locs()->in(0).reg();
314 Register right = comp->locs()->in(1).reg(); 337 Register right = comp->locs()->in(1).reg();
315 Register result = comp->locs()->out().reg();
316 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. 338 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs.
317 Register temp = comp->locs()->temp(0).reg(); 339 Register temp = comp->locs()->temp(0).reg();
318 Label* deopt = compiler->AddDeoptStub(comp->cid(), 340 Label* deopt = compiler->AddDeoptStub(comp->cid(),
319 comp->token_index(), 341 comp->token_index(),
320 comp->try_index(), 342 comp->try_index(),
321 kDeoptDoubleComparison, 343 kDeoptDoubleComparison,
322 left, 344 left,
323 right); 345 right);
324 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 346 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
325 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 347 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
326 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 348
327 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
328 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); 349 Condition true_condition = TokenKindToDoubleCondition(comp->kind());
329 Label is_false, is_true, done;
330 __ comisd(XMM0, XMM1); 350 __ comisd(XMM0, XMM1);
331 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; 351
332 __ j(true_condition, &is_true, Assembler::kNearJump); 352 if (comp->fused_with_branch() == NULL) {
333 __ Bind(&is_false); 353 Register result = comp->locs()->out().reg();
334 __ LoadObject(result, bool_false); 354 Label is_false, is_true, done;
335 __ jmp(&done); 355 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false;
336 __ Bind(&is_true); 356 __ j(true_condition, &is_true, Assembler::kNearJump);
337 __ LoadObject(result, bool_true); 357 __ Bind(&is_false);
338 __ Bind(&done); 358 __ LoadObject(result, compiler->false_value());
359 __ jmp(&done);
360 __ Bind(&is_true);
361 __ LoadObject(result, compiler->true_value());
362 __ Bind(&done);
363 } else {
364 BranchInstr* branch = comp->fused_with_branch();
365 __ j(PARITY_EVEN, compiler->GetBlockLabel(branch->false_successor()));
366 branch->EmitBranchOnCondition(compiler, true_condition);
367 }
339 } 368 }
340 369
341 370
342 371
343 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 372 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
344 if (operands_class_id() == kSmi) { 373 if (operands_class_id() == kSmi) {
345 EmitSmiRelationalOp(compiler, this); 374 EmitSmiRelationalOp(compiler, this);
346 return; 375 return;
347 } 376 }
348 if (operands_class_id() == kDouble) { 377 if (operands_class_id() == kDouble) {
(...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after
1419 __ DoubleNegate(XMM0); 1448 __ DoubleNegate(XMM0);
1420 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); 1449 __ movsd(FieldAddress(result, Double::value_offset()), XMM0);
1421 } else { 1450 } else {
1422 UNREACHABLE(); 1451 UNREACHABLE();
1423 } 1452 }
1424 } 1453 }
1425 1454
1426 1455
1427 LocationSummary* ToDoubleComp::MakeLocationSummary() const { 1456 LocationSummary* ToDoubleComp::MakeLocationSummary() const {
1428 const intptr_t kNumInputs = 1; 1457 const intptr_t kNumInputs = 1;
1429 const intptr_t kNumTemps = 1;
1430 if (from() == kDouble) { 1458 if (from() == kDouble) {
1459 const intptr_t kNumTemps = 1;
1431 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); 1460 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
1432 locs->set_in(0, Location::RequiresRegister()); 1461 locs->set_in(0, Location::RequiresRegister());
1462 locs->set_temp(0, Location::RequiresRegister());
1433 locs->set_out(Location::SameAsFirstInput()); 1463 locs->set_out(Location::SameAsFirstInput());
1434 return locs; 1464 return locs;
1435 } else { 1465 } else {
1436 ASSERT(from() == kSmi); 1466 ASSERT(from() == kSmi);
1437 return LocationSummary::Make(kNumInputs, Location::RegisterLocation(EAX)); 1467 return LocationSummary::Make(kNumInputs, Location::RegisterLocation(EAX));
1438 } 1468 }
1439 } 1469 }
1440 1470
1441 1471
1442 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1472 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 __ cvtsi2sd(XMM0, value); 1518 __ cvtsi2sd(XMM0, value);
1489 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); 1519 __ movsd(FieldAddress(result, Double::value_offset()), XMM0);
1490 } 1520 }
1491 1521
1492 1522
1493 } // namespace dart 1523 } // namespace dart
1494 1524
1495 #undef __ 1525 #undef __
1496 1526
1497 #endif // defined TARGET_ARCH_X64 1527 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698