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

Side by Side Diff: pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart

Issue 2561533002: dart2js: Constant folding and specialization for remainder (Closed)
Patch Set: improve range analysis of remainder Created 3 years, 11 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
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('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 import '../compiler.dart' show Compiler; 5 import '../compiler.dart' show Compiler;
6 import '../constants/constant_system.dart'; 6 import '../constants/constant_system.dart';
7 import '../constants/values.dart'; 7 import '../constants/values.dart';
8 import '../elements/elements.dart'; 8 import '../elements/elements.dart';
9 import '../js_backend/js_backend.dart'; 9 import '../js_backend/js_backend.dart';
10 import '../types/types.dart'; 10 import '../types/types.dart';
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 if (name == '>=') return const GreaterEqualSpecializer(); 67 if (name == '>=') return const GreaterEqualSpecializer();
68 return const InvokeDynamicSpecializer(); 68 return const InvokeDynamicSpecializer();
69 } 69 }
70 if (selector.isCall) { 70 if (selector.isCall) {
71 if (selector.namedArguments.length == 0) { 71 if (selector.namedArguments.length == 0) {
72 int argumentCount = selector.argumentCount; 72 int argumentCount = selector.argumentCount;
73 if (argumentCount == 0) { 73 if (argumentCount == 0) {
74 if (name == 'round') return const RoundSpecializer(); 74 if (name == 'round') return const RoundSpecializer();
75 } else if (argumentCount == 1) { 75 } else if (argumentCount == 1) {
76 if (name == 'codeUnitAt') return const CodeUnitAtSpecializer(); 76 if (name == 'codeUnitAt') return const CodeUnitAtSpecializer();
77 if (name == 'remainder') return const RemainderSpecializer();
77 } 78 }
78 } 79 }
79 } 80 }
80 return const InvokeDynamicSpecializer(); 81 return const InvokeDynamicSpecializer();
81 } 82 }
82 } 83 }
83 84
84 class IndexAssignSpecializer extends InvokeDynamicSpecializer { 85 class IndexAssignSpecializer extends InvokeDynamicSpecializer {
85 const IndexAssignSpecializer(); 86 const IndexAssignSpecializer();
86 87
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld); 301 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld);
301 } 302 }
302 303
303 BinaryOperation operation(ConstantSystem constantSystem) { 304 BinaryOperation operation(ConstantSystem constantSystem) {
304 return constantSystem.modulo; 305 return constantSystem.modulo;
305 } 306 }
306 307
307 HInstruction newBuiltinVariant( 308 HInstruction newBuiltinVariant(
308 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { 309 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) {
309 // Modulo cannot be mapped to the native operator (different semantics). 310 // Modulo cannot be mapped to the native operator (different semantics).
310 // TODO(sra): For non-negative values we can use JavaScript's %. 311
312 // We can use HRemainder if both inputs are non-negative and the receiver
313 // cannot be -0.0. Note that -0.0 is considered to be an int, so until we
314 // track -0.0 precisely, we have to syntatically filter inputs that cannot
315 // generate -0.0.
316 bool canBePositiveZero(HInstruction input) {
317 if (input is HConstant) {
318 ConstantValue value = input.constant;
319 if (value is DoubleConstantValue && value.isZero) return true;
320 if (value is IntConstantValue && value.isZero) return true;
321 return false;
322 }
323 return true;
324 }
325
326 bool inPhi = false;
327 bool canBeNegativeZero(HInstruction input) {
328 if (input is HConstant) {
329 ConstantValue value = input.constant;
330 if (value is DoubleConstantValue && value.isMinusZero) return true;
331 return false;
332 }
333 if (input is HAdd) {
334 // '+' can only generate -0.0 when both inputs are -0.0.
335 return canBeNegativeZero(input.left) && canBeNegativeZero(input.right);
336 }
337 if (input is HSubtract) {
338 return canBeNegativeZero(input.left) && canBePositiveZero(input.right);
339 }
340 if (input is HPhi) {
341 if (inPhi) return true;
342 inPhi = true;
343 bool result = input.inputs.any(canBeNegativeZero);
344 inPhi = false;
345 return result;
346 }
347 return true;
348 }
349
350 if (inputsArePositiveIntegers(instruction, closedWorld) &&
351 !canBeNegativeZero(instruction.getDartReceiver(closedWorld))) {
352 return new HRemainder(
353 instruction.inputs[1],
354 instruction.inputs[2],
355 instruction.selector,
356 computeTypeFromInputTypes(instruction, compiler, closedWorld));
357 }
358 // TODO(sra):
359 // a % N --> a & (N-1), N=2^k, where a>=0, does not have -0.0 problem.
360
361 // TODO(sra): We could avoid problems with -0.0 if we generate x % y as (x +
362 // 0) % y, but we would have to fix HAdd optimizations.
363
364 // TODO(sra): We could replace $mod with HRemainder when we don't care about
365 // a -0.0 result (e.g. a % 10 == 0, a[i % 3]). This is tricky, since we
366 // don't want to ruin GVN opportunities.
311 return null; 367 return null;
312 } 368 }
313 } 369 }
314 370
371 class RemainderSpecializer extends BinaryArithmeticSpecializer {
372 const RemainderSpecializer();
373
374 TypeMask computeTypeFromInputTypes(
375 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) {
376 if (inputsArePositiveIntegers(instruction, closedWorld)) {
377 return closedWorld.commonMasks.positiveIntType;
378 }
379 return super.computeTypeFromInputTypes(instruction, compiler, closedWorld);
380 }
381
382 BinaryOperation operation(ConstantSystem constantSystem) {
383 return constantSystem.remainder;
384 }
385
386 HInstruction newBuiltinVariant(
387 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) {
388 JavaScriptBackend backend = compiler.backend;
389 return new HRemainder(
390 instruction.inputs[1],
391 instruction.inputs[2],
392 instruction.selector,
393 computeTypeFromInputTypes(instruction, compiler, closedWorld));
394 }
395 }
396
315 class MultiplySpecializer extends BinaryArithmeticSpecializer { 397 class MultiplySpecializer extends BinaryArithmeticSpecializer {
316 const MultiplySpecializer(); 398 const MultiplySpecializer();
317 399
318 BinaryOperation operation(ConstantSystem constantSystem) { 400 BinaryOperation operation(ConstantSystem constantSystem) {
319 return constantSystem.multiply; 401 return constantSystem.multiply;
320 } 402 }
321 403
322 TypeMask computeTypeFromInputTypes( 404 TypeMask computeTypeFromInputTypes(
323 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { 405 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) {
324 if (inputsArePositiveIntegers(instruction, closedWorld)) { 406 if (inputsArePositiveIntegers(instruction, closedWorld)) {
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) { 858 HInvokeDynamic instruction, Compiler compiler, ClosedWorld closedWorld) {
777 HInstruction receiver = instruction.getDartReceiver(closedWorld); 859 HInstruction receiver = instruction.getDartReceiver(closedWorld);
778 if (receiver.isNumberOrNull(closedWorld)) { 860 if (receiver.isNumberOrNull(closedWorld)) {
779 // Even if there is no builtin equivalent instruction, we know the 861 // Even if there is no builtin equivalent instruction, we know the
780 // instruction does not have any side effect, and that it can be GVN'ed. 862 // instruction does not have any side effect, and that it can be GVN'ed.
781 clearAllSideEffects(instruction); 863 clearAllSideEffects(instruction);
782 } 864 }
783 return null; 865 return null;
784 } 866 }
785 } 867 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698