From 4e523d8a8fcef07115fb982fe5cf5347451be9fe Mon Sep 17 00:00:00 2001 From: "sra@google.com" Date: Thu, 11 Dec 2014 21:44:40 +0000 Subject: [PATCH] Remove trivial dead stores during dead code elimination Occasionally this optimizes a StringBuffer into a local string variable. If we had targeted inlining to inline more methods on StringBuffer we would see more examples. padRight: function(source, $length) { var result, str, t1; result = new P.StringBuffer(""); str = typeof source === "string" ? source : H.S(source); result._contents = str; for (t1 = str; t1.length < $length;) { t1 += " "; result._contents = t1; } return t1.charCodeAt(0) == 0 ? t1 : t1; }, --> padRight: function(source, $length) { var str, t1; str = typeof source === "string" ? source : H.S(source); for (t1 = str; t1.length < $length;) t1 += " "; return t1.charCodeAt(0) == 0 ? t1 : t1; }, R=floitsch@google.com Review URL: https://codereview.chromium.org//780403003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42302 260f80e4-7a28-3924-810f-c04153c831b5 --- pkg/compiler/lib/src/ssa/optimize.dart | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart index c95d5db1a16..38bf3cf0683 100644 --- a/pkg/compiler/lib/src/ssa/optimize.dart +++ b/pkg/compiler/lib/src/ssa/optimize.dart @@ -982,6 +982,8 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { final Compiler compiler; final SsaOptimizerTask optimizer; SsaLiveBlockAnalyzer analyzer; + Map trivialDeadStoreReceivers = + new Maplet(); bool eliminatedSideEffects = false; SsaDeadCodeEliminator(this.compiler, this.optimizer); @@ -1022,8 +1024,34 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { return false; } + bool isTrivialDeadStoreReceiver(HInstruction instruction) { + // For an allocation, if all the loads are dead (awaiting removal after + // SsaLoadElimination) and the only other uses are stores, then the + // allocation does not escape which makes all the stores dead too. + bool isDeadUse(HInstruction use) { + if (use is HFieldSet) { + // The use must be the receiver. Even if the use is also the argument, + // i.e. a.x = a, the store is still dead if all other uses are dead. + if (use.getDartReceiver(compiler) == instruction) return true; + } else if (use is HFieldGet) { + assert(use.getDartReceiver(compiler) == instruction); + if (isDeadCode(use)) return true; + } + return false; + } + return instruction is HForeignNew + && trivialDeadStoreReceivers.putIfAbsent(instruction, + () => instruction.usedBy.every(isDeadUse)); + } + + bool isTrivialDeadStore(HInstruction instruction) { + return instruction is HFieldSet + && isTrivialDeadStoreReceiver(instruction.getDartReceiver(compiler)); + } + bool isDeadCode(HInstruction instruction) { if (!instruction.usedBy.isEmpty) return false; + if (isTrivialDeadStore(instruction)) return true; if (instruction.sideEffects.hasSideEffects()) return false; if (instruction.canThrow() && instruction.onlyThrowsNSM()