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
This commit is contained in:
sra@google.com
2014-12-11 21:44:40 +00:00
parent 3eca362877
commit 4e523d8a8f
+28
View File
@@ -982,6 +982,8 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
final Compiler compiler;
final SsaOptimizerTask optimizer;
SsaLiveBlockAnalyzer analyzer;
Map<HInstruction, bool> trivialDeadStoreReceivers =
new Maplet<HInstruction, bool>();
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()