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

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: fix range analysis Created 4 years 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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 return super.computeTypeFromInputTypes(instruction, compiler); 300 return super.computeTypeFromInputTypes(instruction, compiler);
300 } 301 }
301 302
302 BinaryOperation operation(ConstantSystem constantSystem) { 303 BinaryOperation operation(ConstantSystem constantSystem) {
303 return constantSystem.modulo; 304 return constantSystem.modulo;
304 } 305 }
305 306
306 HInstruction newBuiltinVariant( 307 HInstruction newBuiltinVariant(
307 HInvokeDynamic instruction, Compiler compiler) { 308 HInvokeDynamic instruction, Compiler compiler) {
308 // Modulo cannot be mapped to the native operator (different semantics). 309 // Modulo cannot be mapped to the native operator (different semantics).
309 // TODO(sra): For non-negative values we can use JavaScript's %. 310
311 // We can use HRemainder if both inputs are non-negative and the receiver
312 // cannot be -0.0. Note that -0.0 is considered to be an int, so until we
313 // track -0.0 precisely, we have to syntatically filter inputs that cannot
314 // generate -0.0.
315 bool canBePositiveZero(HInstruction input) {
316 if (input is HConstant) {
317 ConstantValue value = input.constant;
318 if (value is DoubleConstantValue && value.isZero) return true;
319 if (value is IntConstantValue && value.isZero) return true;
320 return false;
321 }
322 return true;
323 }
324 bool inPhi = false;
325 bool canBeNegativeZero(HInstruction input) {
326 if (input is HConstant) {
327 ConstantValue value = input.constant;
328 if (value is DoubleConstantValue && value.isMinusZero) return true;
329 return false;
330 }
331 if (input is HAdd) {
332 // '+' is can only generate -0.0 when both inputs are -0.0.
Siggi Cherem (dart-lang) 2016/12/08 14:54:29 is can => can
sra1 2016/12/08 20:43:44 Done.
333 return canBeNegativeZero(input.left) && canBeNegativeZero(input.right);
334 }
335 if (input is HSubtract) {
336 return canBeNegativeZero(input.left) && canBePositiveZero(input.right);
337 }
338 if (input is HPhi) {
339 if (inPhi) return true;
340 inPhi = true;
341 bool result = input.inputs.any(canBeNegativeZero);
342 inPhi = false;
343 return result;
344 }
345 return true;
346 }
347
348 if (inputsArePositiveIntegers(instruction, compiler) &&
349 !canBeNegativeZero(instruction.getDartReceiver(compiler))) {
350 return new HRemainder(
351 instruction.inputs[1],
352 instruction.inputs[2],
353 instruction.selector,
354 computeTypeFromInputTypes(instruction, compiler));
355 }
356 // TODO(sra):
357 // a % N --> a & (N-1), N=2^k, where a>=0, does not have -0.0 problem.
358
359 // TODO(sra): We could avoid problems with -0.0 if we generate x % y as (x +
360 // 0) % y, but we would have to fix HAdd optimizations.
361
362 // TODO(sra): We could replace $mod with HRemainder when we don't care about
363 // a -0.0 result (e.g. a % 10 == 0, a[i % 3]). This is tricky, since we
364 // don't want to ruin GVN opportunities.
310 return null; 365 return null;
311 } 366 }
312 } 367 }
313 368
369 class RemainderSpecializer extends BinaryArithmeticSpecializer {
370 const RemainderSpecializer();
371
372 TypeMask computeTypeFromInputTypes(
373 HInvokeDynamic instruction, Compiler compiler) {
374 if (inputsArePositiveIntegers(instruction, compiler)) {
375 JavaScriptBackend backend = compiler.backend;
376 return backend.positiveIntType;
377 }
378 return super.computeTypeFromInputTypes(instruction, compiler);
379 }
380
381 BinaryOperation operation(ConstantSystem constantSystem) {
382 return constantSystem.remainder;
383 }
384
385 HInstruction newBuiltinVariant(
386 HInvokeDynamic instruction, Compiler compiler) {
387 JavaScriptBackend backend = compiler.backend;
388 return new HRemainder(instruction.inputs[1], instruction.inputs[2],
389 instruction.selector, computeTypeFromInputTypes(instruction, compiler));
390 }
391 }
392
314 class MultiplySpecializer extends BinaryArithmeticSpecializer { 393 class MultiplySpecializer extends BinaryArithmeticSpecializer {
315 const MultiplySpecializer(); 394 const MultiplySpecializer();
316 395
317 BinaryOperation operation(ConstantSystem constantSystem) { 396 BinaryOperation operation(ConstantSystem constantSystem) {
318 return constantSystem.multiply; 397 return constantSystem.multiply;
319 } 398 }
320 399
321 TypeMask computeTypeFromInputTypes( 400 TypeMask computeTypeFromInputTypes(
322 HInvokeDynamic instruction, Compiler compiler) { 401 HInvokeDynamic instruction, Compiler compiler) {
323 if (inputsArePositiveIntegers(instruction, compiler)) { 402 if (inputsArePositiveIntegers(instruction, compiler)) {
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 HInvokeDynamic instruction, Compiler compiler) { 842 HInvokeDynamic instruction, Compiler compiler) {
764 HInstruction receiver = instruction.getDartReceiver(compiler); 843 HInstruction receiver = instruction.getDartReceiver(compiler);
765 if (receiver.isNumberOrNull(compiler)) { 844 if (receiver.isNumberOrNull(compiler)) {
766 // Even if there is no builtin equivalent instruction, we know the 845 // Even if there is no builtin equivalent instruction, we know the
767 // instruction does not have any side effect, and that it can be GVN'ed. 846 // instruction does not have any side effect, and that it can be GVN'ed.
768 clearAllSideEffects(instruction); 847 clearAllSideEffects(instruction);
769 } 848 }
770 return null; 849 return null;
771 } 850 }
772 } 851 }
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