| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 interface OptimizationPhase { | 5 interface OptimizationPhase { |
| 6 String get name(); | 6 String get name(); |
| 7 void visitGraph(HGraph graph); | 7 void visitGraph(HGraph graph); |
| 8 } | 8 } |
| 9 | 9 |
| 10 class SsaOptimizerTask extends CompilerTask { | 10 class SsaOptimizerTask extends CompilerTask { |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 } | 286 } |
| 287 | 287 |
| 288 if (left.isNonPrimitive() && node.operation.isUserDefinable()) { | 288 if (left.isNonPrimitive() && node.operation.isUserDefinable()) { |
| 289 SourceString methodName = Elements.constructOperatorName( | 289 SourceString methodName = Elements.constructOperatorName( |
| 290 const SourceString('operator'), node.operation.name); | 290 const SourceString('operator'), node.operation.name); |
| 291 return fromInterceptorToDynamicInvocation(node, methodName); | 291 return fromInterceptorToDynamicInvocation(node, methodName); |
| 292 } | 292 } |
| 293 return node; | 293 return node; |
| 294 } | 294 } |
| 295 | 295 |
| 296 bool allUsersAreBoolifies(HInstruction instruction) { |
| 297 List<HInstruction> users = instruction.usedBy; |
| 298 int length = users.length; |
| 299 for (int i = 0; i < length; i++) { |
| 300 if (users[i] is! HBoolify) return false; |
| 301 } |
| 302 return true; |
| 303 } |
| 304 |
| 305 HInstruction visitRelational(HRelational node) { |
| 306 if (allUsersAreBoolifies(node)) { |
| 307 Interceptors interceptors = compiler.builder.interceptors; |
| 308 HStatic oldTarget = node.target; |
| 309 Element boolifiedInterceptor = |
| 310 interceptors.getBoolifiedVersionOf(oldTarget.element); |
| 311 if (boolifiedInterceptor !== null) { |
| 312 HStatic boolifiedTarget = new HStatic(boolifiedInterceptor); |
| 313 // We don't remove the [oldTarget] in case it is used by other |
| 314 // instructions. If it is unused it will be treated as dead code and |
| 315 // discarded. |
| 316 oldTarget.block.addAfter(oldTarget, boolifiedTarget); |
| 317 // Remove us as user from the [oldTarget]. |
| 318 HBasicBlock.removeUser(oldTarget, node); |
| 319 // Replace old target with boolified target. |
| 320 assert(node.target == node.inputs[0]); |
| 321 node.inputs[0] = boolifiedTarget; |
| 322 boolifiedTarget.usedBy.add(node); |
| 323 node.usesBoolifiedInterceptor = true; |
| 324 node.propagatedType = HType.BOOLEAN; |
| 325 } |
| 326 // This node stays the same, but the Boolify node will go away. |
| 327 } |
| 328 // Note that we still have to call [super] to make sure that we end up |
| 329 // in the remaining optimizations. |
| 330 return super.visitRelational(node); |
| 331 } |
| 332 |
| 296 HInstruction handleIdentityCheck(HInvokeBinary node) { | 333 HInstruction handleIdentityCheck(HInvokeBinary node) { |
| 297 HInstruction left = node.left; | 334 HInstruction left = node.left; |
| 298 HInstruction right = node.right; | 335 HInstruction right = node.right; |
| 299 HType leftType = left.propagatedType; | 336 HType leftType = left.propagatedType; |
| 300 HType rightType = right.propagatedType; | 337 HType rightType = right.propagatedType; |
| 301 assert(!leftType.isConflicting() && !rightType.isConflicting()); | 338 assert(!leftType.isConflicting() && !rightType.isConflicting()); |
| 302 | 339 |
| 303 // We don't optimize on numbers to preserve the runtime semantics. | 340 // We don't optimize on numbers to preserve the runtime semantics. |
| 304 if (!(left.isNumber() && right.isNumber()) && | 341 if (!(left.isNumber() && right.isNumber()) && |
| 305 leftType.intersection(rightType).isConflicting()) { | 342 leftType.intersection(rightType).isConflicting()) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 | 384 |
| 348 HInstruction visitEquals(HEquals node) { | 385 HInstruction visitEquals(HEquals node) { |
| 349 HInstruction left = node.left; | 386 HInstruction left = node.left; |
| 350 HInstruction right = node.right; | 387 HInstruction right = node.right; |
| 351 | 388 |
| 352 if (node.builtin) { | 389 if (node.builtin) { |
| 353 return foldBuiltinEqualsCheck(node); | 390 return foldBuiltinEqualsCheck(node); |
| 354 } | 391 } |
| 355 | 392 |
| 356 if (left.isConstant() && right.isConstant()) { | 393 if (left.isConstant() && right.isConstant()) { |
| 357 return visitInvokeBinary(node); | 394 return super.visitEquals(node); |
| 358 } | 395 } |
| 359 | 396 |
| 360 if (left.isNonPrimitive()) { | 397 if (left.isNonPrimitive()) { |
| 361 HNonPrimitiveType type = left.propagatedType; | 398 HNonPrimitiveType type = left.propagatedType; |
| 362 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); | 399 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); |
| 363 if (element !== null) { | 400 if (element !== null) { |
| 364 // If the left-hand side is guaranteed to be a non-primitive | 401 // If the left-hand side is guaranteed to be a non-primitive |
| 365 // type and and it defines operator==, we emit a call to that | 402 // type and and it defines operator==, we emit a call to that |
| 366 // operator. | 403 // operator. |
| 367 return visitInvokeBinary(node); | 404 return super.visitEquals(node); |
| 368 } else if (right.isConstantNull()) { | 405 } else if (right.isConstantNull()) { |
| 369 return graph.addConstantBool(false); | 406 return graph.addConstantBool(false); |
| 370 } else { | 407 } else { |
| 371 // We can just emit an identity check because the type does | 408 // We can just emit an identity check because the type does |
| 372 // not implement operator=. | 409 // not implement operator=. |
| 373 return foldBuiltinEqualsCheck(node); | 410 return foldBuiltinEqualsCheck(node); |
| 374 } | 411 } |
| 375 } | 412 } |
| 376 | 413 |
| 377 if (right.isConstantNull()) { | 414 if (right.isConstantNull()) { |
| 378 if (left.propagatedType.isUseful()) { | 415 if (left.propagatedType.isUseful()) { |
| 379 return graph.addConstantBool(false); | 416 return graph.addConstantBool(false); |
| 380 } else { | 417 } else { |
| 381 // TODO(floitsch): cache interceptors. | 418 // TODO(floitsch): cache interceptors. |
| 382 HStatic target = new HStatic( | 419 Interceptors interceptors = compiler.builder.interceptors; |
| 383 compiler.builder.interceptors.getEqualsNullInterceptor()); | 420 Element targetElement = interceptors.getEqualsNullInterceptor(); |
| 421 bool onlyUsedInBoolify = allUsersAreBoolifies(node); |
| 422 if (onlyUsedInBoolify) { |
| 423 targetElement = interceptors.getBoolifiedVersionOf(targetElement); |
| 424 } |
| 425 HStatic target = new HStatic(targetElement); |
| 384 node.block.addBefore(node, target); | 426 node.block.addBefore(node, target); |
| 385 return new HEquals(target, node.left, node.right); | 427 HEquals result = new HEquals(target, node.left, node.right); |
| 428 if (onlyUsedInBoolify) { |
| 429 result.usesBoolifiedInterceptor = true; |
| 430 result.propagatedType = HType.BOOLEAN; |
| 431 } |
| 432 return result; |
| 386 } | 433 } |
| 387 } | 434 } |
| 388 | 435 |
| 389 // All other cases are dealt with by the [visitInvokeBinary]. | 436 // All other cases are dealt with by the [visitRelational] and |
| 390 return visitInvokeBinary(node); | 437 // [visitInvokeBinary], which are visited by invoking the [super]'s |
| 438 // visit method. |
| 439 return super.visitEquals(node); |
| 391 } | 440 } |
| 392 | 441 |
| 393 HInstruction visitTypeGuard(HTypeGuard node) { | 442 HInstruction visitTypeGuard(HTypeGuard node) { |
| 394 HInstruction value = node.guarded; | 443 HInstruction value = node.guarded; |
| 395 // If the union of the types is still the guarded type than the incoming | 444 // If the union of the types is still the guarded type than the incoming |
| 396 // type was a subtype of the guarded type, and no check is required. | 445 // type was a subtype of the guarded type, and no check is required. |
| 397 HType combinedType = value.propagatedType.union(node.guardedType); | 446 HType combinedType = value.propagatedType.union(node.guardedType); |
| 398 return (combinedType == value.propagatedType) ? value : node; | 447 return (combinedType == value.propagatedType) ? value : node; |
| 399 } | 448 } |
| 400 | 449 |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 } | 965 } |
| 917 } | 966 } |
| 918 if (!canBeMoved) continue; | 967 if (!canBeMoved) continue; |
| 919 | 968 |
| 920 // This is safe because we are running after GVN. | 969 // This is safe because we are running after GVN. |
| 921 // TODO(ngeoffray): ensure GVN has been run. | 970 // TODO(ngeoffray): ensure GVN has been run. |
| 922 set_.add(current); | 971 set_.add(current); |
| 923 } | 972 } |
| 924 } | 973 } |
| 925 } | 974 } |
| OLD | NEW |