Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart |
| index f4c895046e6f1d03f9b2d13a489109d6346c5b1d..f76c726664e22a10a2f2d95c05df05ae6eea24bf 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart |
| @@ -26,7 +26,7 @@ class SsaInstructionSelection extends HBaseVisitor { |
| while (instruction != null) { |
| HInstruction next = instruction.next; |
| HInstruction replacement = instruction.accept(this); |
| - if (replacement != instruction) { |
| + if (replacement != instruction && replacement != null) { |
| block.rewrite(instruction, replacement); |
| // If the replacement instruction does not know its source element, use |
| @@ -137,6 +137,109 @@ class SsaInstructionSelection extends HBaseVisitor { |
| return node; |
| } |
| + |
| + HInstruction visitFieldSet(HFieldSet setter) { |
| + // Pattern match |
| + // t1 = x.f; t2 = t1 op y; x.f = t2; use(t2) --> x.f op= y |
| + // t1 = x.f; t2 = t1 + 1; x.f = t2; use(t2) --> ++x.f |
|
floitsch
2014/04/01 17:28:58
Move that line first. Otherwise the x.f op= y alwa
sra1
2014/04/01 19:51:59
Done.
|
| + // t1 = x.f; t2 = t1 + 1; x.f = t2; use(t1) --> x.f++ |
| + HBasicBlock block = setter.block; |
| + HInstruction op = setter.value; |
| + HInstruction receiver = setter.receiver; |
| + |
| + bool isMatchingRead(HInstruction candidate) { |
| + if (candidate is! HFieldGet) return false; |
| + if (candidate.element != setter.element) return false; |
| + if (candidate.receiver != setter.receiver) return false; |
| + // Recognize only three instructions in sequence in the same block. This |
| + // could be broadened to allow non-interfereing interleaved instructions. |
|
floitsch
2014/04/01 17:28:58
interfering
sra1
2014/04/01 19:51:59
Done.
|
| + if (op.block != block) return false; |
| + if (candidate.block != block) return false; |
| + if (setter.previous != op) return false; |
| + if (op.previous != candidate) return false; |
| + return true; |
| + } |
| + |
| + HInstruction noMatchingRead() { |
| + // If we have other HFieldSet optimizations, they go here. |
| + return null; |
| + } |
| + |
| + HInstruction replaceOp(HInstruction replacement, HInstruction getter) { |
| + block.addBefore(setter, replacement); |
| + block.remove(setter); |
| + block.rewrite(op, replacement); |
| + block.remove(op); |
| + block.remove(getter); |
| + return null; |
| + } |
| + |
| + HInstruction plusOrMinus(String assignOp, String incrementOp) { |
| + if (isMatchingRead(op.left)) { |
| + HFieldGet getter = op.left; |
| + HInstruction right = op.right; |
| + if (getter.usedBy.length == 1) { |
| + if (right is HConstant && right.constant.isOne) { |
| + HInstruction rmw = new HReadModifyWrite.preOp( |
| + setter.element, incrementOp, receiver, op.instructionType); |
| + return replaceOp(rmw, getter); |
| + } else { |
| + HInstruction rmw = new HReadModifyWrite.assignOp( |
| + setter.element, |
| + assignOp, |
| + receiver, right, op.instructionType); |
| + return replaceOp(rmw, getter); |
| + } |
| + } else if (op.usedBy.length == 1 && |
| + right is HConstant && |
| + right.constant.isOne) { |
| + HInstruction rmw = new HReadModifyWrite.postOp( |
| + setter.element, incrementOp, receiver, op.instructionType); |
| + block.addAfter(getter, rmw); |
| + block.remove(setter); |
| + block.remove(op); |
| + block.rewrite(getter, rmw); |
| + block.remove(getter); |
| + return null; |
| + } |
| + } |
| + return noMatchingRead(); |
| + } |
| + |
| + HInstruction simple(String assignOp) { |
| + if (isMatchingRead(op.left)) { |
| + HFieldGet getter = op.left; |
| + if (getter.usedBy.length == 1) { |
| + HInstruction rmw = new HReadModifyWrite.assignOp( |
| + setter.element, |
| + assignOp, |
| + receiver, op.right, op.instructionType); |
| + return replaceOp(rmw, getter); |
| + } |
| + } |
| + return noMatchingRead(); |
| + } |
| + |
| + HInstruction bitop(String assignOp) { |
| + // HBitAnd, HBitOr etc. are more difficult because HBitAnd(a.x, y) |
| + // sometimes needs to be forced to unsigned: a.x = (a.x & y) >>> 0. |
| + if (op.isUInt31(compiler)) return simple(assignOp); |
| + return noMatchingRead(); |
| + } |
| + |
| + if (op is HAdd) return plusOrMinus('+', '++'); |
| + if (op is HSubtract) return plusOrMinus('-', '--'); |
| + |
| + if (op is HStringConcat) return simple('+'); |
| + if (op is HMultiply) return simple('*'); |
| + if (op is HDivide) return simple('/'); |
| + |
| + if (op is HBitAnd) return bitop('&'); |
| + if (op is HBitOr) return bitop('|'); |
| + if (op is HBitXor) return bitop('^'); |
| + |
| + return noMatchingRead(); |
| + } |
| } |
| /** |