| 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 | |
| 333 HInstruction handleIdentityCheck(HInvokeBinary node) { | 296 HInstruction handleIdentityCheck(HInvokeBinary node) { |
| 334 HInstruction left = node.left; | 297 HInstruction left = node.left; |
| 335 HInstruction right = node.right; | 298 HInstruction right = node.right; |
| 336 HType leftType = left.propagatedType; | 299 HType leftType = left.propagatedType; |
| 337 HType rightType = right.propagatedType; | 300 HType rightType = right.propagatedType; |
| 338 assert(!leftType.isConflicting() && !rightType.isConflicting()); | 301 assert(!leftType.isConflicting() && !rightType.isConflicting()); |
| 339 | 302 |
| 340 // We don't optimize on numbers to preserve the runtime semantics. | 303 // We don't optimize on numbers to preserve the runtime semantics. |
| 341 if (!(left.isNumber() && right.isNumber()) && | 304 if (!(left.isNumber() && right.isNumber()) && |
| 342 leftType.intersection(rightType).isConflicting()) { | 305 leftType.intersection(rightType).isConflicting()) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 | 347 |
| 385 HInstruction visitEquals(HEquals node) { | 348 HInstruction visitEquals(HEquals node) { |
| 386 HInstruction left = node.left; | 349 HInstruction left = node.left; |
| 387 HInstruction right = node.right; | 350 HInstruction right = node.right; |
| 388 | 351 |
| 389 if (node.builtin) { | 352 if (node.builtin) { |
| 390 return foldBuiltinEqualsCheck(node); | 353 return foldBuiltinEqualsCheck(node); |
| 391 } | 354 } |
| 392 | 355 |
| 393 if (left.isConstant() && right.isConstant()) { | 356 if (left.isConstant() && right.isConstant()) { |
| 394 return super.visitEquals(node); | 357 return visitInvokeBinary(node); |
| 395 } | 358 } |
| 396 | 359 |
| 397 if (left.isNonPrimitive()) { | 360 if (left.isNonPrimitive()) { |
| 398 HNonPrimitiveType type = left.propagatedType; | 361 HNonPrimitiveType type = left.propagatedType; |
| 399 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); | 362 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); |
| 400 if (element !== null) { | 363 if (element !== null) { |
| 401 // If the left-hand side is guaranteed to be a non-primitive | 364 // If the left-hand side is guaranteed to be a non-primitive |
| 402 // type and and it defines operator==, we emit a call to that | 365 // type and and it defines operator==, we emit a call to that |
| 403 // operator. | 366 // operator. |
| 404 return super.visitEquals(node); | 367 return visitInvokeBinary(node); |
| 405 } else if (right.isConstantNull()) { | 368 } else if (right.isConstantNull()) { |
| 406 return graph.addConstantBool(false); | 369 return graph.addConstantBool(false); |
| 407 } else { | 370 } else { |
| 408 // We can just emit an identity check because the type does | 371 // We can just emit an identity check because the type does |
| 409 // not implement operator=. | 372 // not implement operator=. |
| 410 return foldBuiltinEqualsCheck(node); | 373 return foldBuiltinEqualsCheck(node); |
| 411 } | 374 } |
| 412 } | 375 } |
| 413 | 376 |
| 414 if (right.isConstantNull()) { | 377 if (right.isConstantNull()) { |
| 415 if (left.propagatedType.isUseful()) { | 378 if (left.propagatedType.isUseful()) { |
| 416 return graph.addConstantBool(false); | 379 return graph.addConstantBool(false); |
| 417 } else { | 380 } else { |
| 418 // TODO(floitsch): cache interceptors. | 381 // TODO(floitsch): cache interceptors. |
| 419 Interceptors interceptors = compiler.builder.interceptors; | 382 HStatic target = new HStatic( |
| 420 Element targetElement = interceptors.getEqualsNullInterceptor(); | 383 compiler.builder.interceptors.getEqualsNullInterceptor()); |
| 421 bool onlyUsedInBoolify = allUsersAreBoolifies(node); | |
| 422 if (onlyUsedInBoolify) { | |
| 423 targetElement = interceptors.getBoolifiedVersionOf(targetElement); | |
| 424 } | |
| 425 HStatic target = new HStatic(targetElement); | |
| 426 node.block.addBefore(node, target); | 384 node.block.addBefore(node, target); |
| 427 HEquals result = new HEquals(target, node.left, node.right); | 385 return new HEquals(target, node.left, node.right); |
| 428 if (onlyUsedInBoolify) { | |
| 429 result.usesBoolifiedInterceptor = true; | |
| 430 result.propagatedType = HType.BOOLEAN; | |
| 431 } | |
| 432 return result; | |
| 433 } | 386 } |
| 434 } | 387 } |
| 435 | 388 |
| 436 // All other cases are dealt with by the [visitRelational] and | 389 // All other cases are dealt with by the [visitInvokeBinary]. |
| 437 // [visitInvokeBinary], which are visited by invoking the [super]'s | 390 return visitInvokeBinary(node); |
| 438 // visit method. | |
| 439 return super.visitEquals(node); | |
| 440 } | 391 } |
| 441 | 392 |
| 442 HInstruction visitTypeGuard(HTypeGuard node) { | 393 HInstruction visitTypeGuard(HTypeGuard node) { |
| 443 HInstruction value = node.guarded; | 394 HInstruction value = node.guarded; |
| 444 // If the union of the types is still the guarded type than the incoming | 395 // If the union of the types is still the guarded type than the incoming |
| 445 // type was a subtype of the guarded type, and no check is required. | 396 // type was a subtype of the guarded type, and no check is required. |
| 446 HType combinedType = value.propagatedType.union(node.guardedType); | 397 HType combinedType = value.propagatedType.union(node.guardedType); |
| 447 return (combinedType == value.propagatedType) ? value : node; | 398 return (combinedType == value.propagatedType) ? value : node; |
| 448 } | 399 } |
| 449 | 400 |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 965 } | 916 } |
| 966 } | 917 } |
| 967 if (!canBeMoved) continue; | 918 if (!canBeMoved) continue; |
| 968 | 919 |
| 969 // This is safe because we are running after GVN. | 920 // This is safe because we are running after GVN. |
| 970 // TODO(ngeoffray): ensure GVN has been run. | 921 // TODO(ngeoffray): ensure GVN has been run. |
| 971 set_.add(current); | 922 set_.add(current); |
| 972 } | 923 } |
| 973 } | 924 } |
| 974 } | 925 } |
| OLD | NEW |