1 cananian 1.1.2.1 // DeadCodeElimination.java, created Wed Feb 16 12:58:13 2000 by cananian 2 cananian 1.1.2.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Analysis.Tree; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Analysis.Liveness; 7 cananian 1.1.2.1 import harpoon.Analysis.DataFlow.LiveVars; 8 cananian 1.1.2.1 import harpoon.ClassFile.HCode; 9 cananian 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 10 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 11 cananian 1.1.2.2 import harpoon.IR.Properties.CFGrapher; 12 cananian 1.1.2.2 import harpoon.IR.Properties.UseDefer; 13 cananian 1.1.2.2 import harpoon.IR.Tree.CanonicalTreeCode; 14 cananian 1.1.2.2 import harpoon.IR.Tree.DerivationGenerator; 15 jwhaley 1.1.2.5 import harpoon.IR.Tree.EXPR; 16 cananian 1.1.2.2 import harpoon.IR.Tree.Exp; 17 cananian 1.1.2.2 import harpoon.IR.Tree.MOVE; 18 cananian 1.1.2.2 import harpoon.IR.Tree.SEQ; 19 cananian 1.1.2.2 import harpoon.IR.Tree.Stm; 20 cananian 1.1.2.2 import harpoon.IR.Tree.TEMP; 21 cananian 1.1.2.2 import harpoon.IR.Tree.Tree; 22 cananian 1.1.2.2 import harpoon.IR.Tree.TreeFactory; 23 cananian 1.1.2.2 import harpoon.IR.Tree.TreeKind; 24 cananian 1.1.2.1 import harpoon.Temp.Temp; 25 cananian 1.1.2.1 import harpoon.Util.Util; 26 cananian 1.1.2.1 27 cananian 1.1.2.1 import java.util.Arrays; 28 cananian 1.1.2.1 import java.util.Collections; 29 cananian 1.1.2.1 import java.util.HashSet; 30 cananian 1.1.2.1 import java.util.Iterator; 31 cananian 1.1.2.1 import java.util.List; 32 cananian 1.1.2.1 import java.util.Set; 33 cananian 1.1.2.1 34 cananian 1.1.2.1 /** 35 cananian 1.1.2.1 * <code>DeadCodeElimination</code> removes unused MOVEs, useless 36 jwhaley 1.1.2.5 * EXPRs, and whatever other cruft it can detect using a liveness 37 cananian 1.1.2.1 * analysis. 38 cananian 1.1.2.1 * 39 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 40 cananian 1.5 * @version $Id: DeadCodeElimination.java,v 1.5 2003/03/11 18:46:47 cananian Exp $ 41 cananian 1.1.2.1 */ 42 cananian 1.1.2.1 public abstract class DeadCodeElimination extends Simplification { 43 cananian 1.1.2.1 // hide constructor 44 cananian 1.1.2.1 private DeadCodeElimination() { } 45 cananian 1.1.2.1 46 cananian 1.1.2.1 /** Code factory for applying DeadCodeElimination to a 47 cananian 1.1.2.1 * canonical tree. Clones the tree before doing 48 cananian 1.1.2.1 * DCE in-place. */ 49 cananian 1.1.2.1 public static HCodeFactory codeFactory(final HCodeFactory parent) { 50 cananian 1.3.2.1 assert parent.getCodeName().equals(CanonicalTreeCode.codename); 51 cananian 1.1.2.1 return new HCodeFactory() { 52 cananian 1.1.2.1 public HCode convert(HMethod m) { 53 cananian 1.1.2.1 HCode hc = parent.convert(m); 54 cananian 1.1.2.1 if (hc!=null) { 55 cananian 1.1.2.1 harpoon.IR.Tree.Code code = (harpoon.IR.Tree.Code) hc; 56 cananian 1.1.2.1 // clone code... 57 cananian 1.1.2.6 code = (harpoon.IR.Tree.Code) code.clone(m).hcode(); 58 cananian 1.1.2.1 DerivationGenerator dg = null; 59 cananian 1.1.2.1 try { 60 cananian 1.1.2.1 dg = (DerivationGenerator) code.getTreeDerivation(); 61 cananian 1.1.2.1 } catch (ClassCastException ex) { /* i guess not */ } 62 cananian 1.1.2.1 // ...do liveness analysis and modify cloned code in-place. 63 cananian 1.1.2.1 simplify((Stm)code.getRootElement(), dg, HCE_RULES(code)); 64 cananian 1.1.2.3 hc = code; 65 cananian 1.1.2.1 } 66 cananian 1.1.2.1 return hc; 67 cananian 1.1.2.1 } 68 cananian 1.1.2.1 public String getCodeName() { return parent.getCodeName(); } 69 cananian 1.1.2.1 public void clear(HMethod m) { parent.clear(m); } 70 cananian 1.1.2.1 }; 71 cananian 1.1.2.1 } 72 cananian 1.1.2.1 73 cananian 1.5 public static List<Rule> HCE_RULES(final harpoon.IR.Tree.Code code) { 74 cananian 1.1.2.1 // compute liveness 75 cananian 1.5 final CFGrapher<Tree> cfgr = code.getGrapher(); 76 cananian 1.5 final UseDefer<Tree> ud = code.getUseDefer(); 77 cananian 1.1.2.1 final Liveness l = new LiveVars(code, cfgr, ud, Collections.EMPTY_SET); 78 cananian 1.1.2.1 // now collect info about dead moves. 79 cananian 1.5 final Set<MOVE> deadMoves = new HashSet<MOVE>(); 80 cananian 1.5 for (Iterator<Tree> it=code.getElementsI(); it.hasNext(); ) { 81 cananian 1.5 Tree tr = it.next(); 82 cananian 1.1.2.1 if (tr.kind() == TreeKind.MOVE && 83 cananian 1.1.2.1 ((MOVE)tr).getDst().kind() == TreeKind.TEMP) { 84 cananian 1.1.2.1 Temp temp = ((TEMP) ((MOVE) tr).getDst()).temp; 85 cananian 1.1.2.1 Set liveOut = l.getLiveOut(tr); 86 cananian 1.1.2.1 if (!liveOut.contains(temp)) // a MOVE to an unused temp. 87 cananian 1.5 deadMoves.add((MOVE)tr); 88 cananian 1.1.2.1 } 89 cananian 1.1.2.1 } 90 cananian 1.1.2.1 // debugging 91 cananian 1.1.2.1 System.err.print("["+deadMoves.size()+" DEAD MOVES]"); 92 cananian 1.1.2.1 93 cananian 1.1.2.1 return Arrays.asList(new Rule[] { 94 jwhaley 1.1.2.5 // remove expressions of the form EXPR(CONST(c)) or EXPR(TEMP(t)) 95 cananian 1.1.2.1 // 96 jwhaley 1.1.2.5 // SEQ(EXPR(CONST(c)), s1) --> s1 97 jwhaley 1.1.2.5 // SEQ(s1, EXPR(CONST(c)) --> s1 98 jwhaley 1.1.2.5 // SEQ(EXPR(TEMP(t)), s1) --> s1 99 jwhaley 1.1.2.5 // SEQ(s1, EXPR(TEMP(t))) --> s1 100 cananian 1.1.2.1 new Rule("removeNop") { 101 cananian 1.1.2.1 public boolean match(Stm s) { 102 cananian 1.1.2.1 if (s.kind() != TreeKind.SEQ) return false; 103 cananian 1.1.2.1 SEQ seq = (SEQ) s; 104 cananian 1.1.2.1 return isNop(seq.getLeft()) || isNop(seq.getRight()); 105 cananian 1.1.2.1 } 106 cananian 1.1.2.1 public Stm apply(TreeFactory tf,Stm s,DerivationGenerator dg) { 107 cananian 1.1.2.1 SEQ seq = (SEQ) s; 108 cananian 1.1.2.1 if (isNop(seq.getLeft())) return seq.getRight(); 109 cananian 1.1.2.1 if (isNop(seq.getRight())) return seq.getLeft(); 110 cananian 1.1.2.1 throw new Error("Neither side is a Nop!"); 111 cananian 1.1.2.1 } 112 cananian 1.1.2.1 private boolean isNop(Stm s) { 113 jwhaley 1.1.2.5 if (s.kind() != TreeKind.EXPR) return false; 114 jwhaley 1.1.2.5 EXPR exp = (EXPR) s; 115 cananian 1.1.2.1 return contains(_KIND(exp.getExp()), _CONST|_TEMP); 116 cananian 1.1.2.1 } 117 cananian 1.1.2.1 }, 118 jwhaley 1.1.2.5 // MOVE(t1, e) --> EXPR(e) if t1 is dead after move 119 cananian 1.1.2.1 new Rule("deadMoves") { 120 cananian 1.1.2.1 public boolean match(Stm s) { 121 cananian 1.1.2.1 return deadMoves.contains(s); 122 cananian 1.1.2.1 } 123 cananian 1.1.2.1 public Stm apply(TreeFactory tf,Stm s,DerivationGenerator dg) { 124 cananian 1.1.2.1 MOVE move = (MOVE) s; 125 jwhaley 1.1.2.5 return new EXPR(tf, move, move.getSrc()); 126 cananian 1.1.2.1 } 127 cananian 1.1.2.1 }, 128 cananian 1.1.2.1 }); 129 cananian 1.1.2.1 } 130 cananian 1.2 }