001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt;
014    
015    import java.util.Enumeration;
016    import java.util.HashMap;
017    import java.util.HashSet;
018    import java.util.Map;
019    
020    import org.jikesrvm.VM;
021    import org.jikesrvm.compilers.opt.driver.CompilerPhase;
022    import org.jikesrvm.compilers.opt.ir.BasicBlock;
023    import org.jikesrvm.compilers.opt.ir.IR;
024    import org.jikesrvm.compilers.opt.ir.Instruction;
025    import org.jikesrvm.compilers.opt.ir.Move;
026    import org.jikesrvm.compilers.opt.ir.Register;
027    import org.jikesrvm.compilers.opt.ir.operand.Operand;
028    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
029    
030    /**
031     * Perform local copy propagation for a factored basic block.
032     * Orthogonal to the copy propagation performed in Simple
033     * since here we use flow-sensitive analysis within a basic block.
034     * <p>
035     * TODO: factor out common functionality in the various local propagation
036     * phases?
037     */
038    public class LocalCopyProp extends CompilerPhase {
039    
040      @Override
041      public final boolean shouldPerform(OptOptions options) {
042        return options.LOCAL_COPY_PROP;
043      }
044    
045      @Override
046      public final String getName() {
047        return "Local CopyProp";
048      }
049    
050      @Override
051      public void reportAdditionalStats() {
052        VM.sysWrite("  ");
053        VM.sysWrite(container.counter1 / container.counter2 * 100, 2);
054        VM.sysWrite("% Infrequent BBs");
055      }
056    
057      /**
058       * Return this instance of this phase. This phase contains no
059       * per-compilation instance fields.
060       * @param ir not used
061       * @return this
062       */
063      @Override
064      public CompilerPhase newExecution(IR ir) {
065        return this;
066      }
067    
068      /**
069       * Perform local constant propagation for a method.
070       *
071       * @param ir the IR to optimize
072       */
073      @Override
074      public void perform(IR ir) {
075        HashMap<Register, Operand> info = new HashMap<Register, Operand>();
076        for (BasicBlock bb = ir.firstBasicBlockInCodeOrder(); bb != null; bb = bb.nextBasicBlockInCodeOrder()) {
077          if (bb.isEmpty()) continue;
078          container.counter2++;
079          if (bb.getInfrequent()) {
080            container.counter1++;
081            if (ir.options.FREQ_FOCUS_EFFORT) continue;
082          }
083          // iterate over all instructions in the basic block
084          for (Instruction s = bb.firstRealInstruction(),
085              sentinel = bb.lastInstruction(); s != sentinel; s = s.nextInstructionInCodeOrder()) {
086    
087            if (!info.isEmpty()) {
088              // PROPAGATE COPIES
089              int numUses = s.getNumberOfPureUses();
090              if (numUses > 0) {
091                boolean didSomething = false;
092                for (Enumeration<Operand> e = s.getUses(); e.hasMoreElements();) {
093                  Operand use = e.nextElement();
094                  if (use instanceof RegisterOperand) {
095                    RegisterOperand rUse = (RegisterOperand) use;
096                    Operand value = info.get(rUse.getRegister());
097                    if (value != null) {
098                      didSomething = true;
099                      value = value.copy();
100                      if (value instanceof RegisterOperand) {
101                        // preserve program point specific typing!
102                        ((RegisterOperand) value).copyType(rUse);
103                      }
104                      s.replaceOperand(use, value);
105                    }
106                  }
107                }
108                if (didSomething) {
109                  Simplifier.simplify(ir.IRStage == IR.HIR, ir.regpool, ir.options, s);
110                }
111              }
112              // KILL
113              boolean killPhysicals = s.isTSPoint() || s.operator().implicitDefs != 0;
114              // kill any physical registers
115              // TODO: use a better data structure for efficiency.
116              // I'm being lazy for now in the name of avoiding
117              // premature optimization.
118              if (killPhysicals) {
119                HashSet<Register> toRemove = new HashSet<Register>();
120                for (Map.Entry<Register, Operand> entry : info.entrySet()) {
121                  Register eR = entry.getValue().asRegister().getRegister();
122                  if (killPhysicals && eR.isPhysical()) {
123                    // delay the removal to avoid ConcurrentModification with iterator.
124                    toRemove.add(entry.getKey());
125                  }
126                }
127                // Now perform the removals.
128                for (final Register aToRemove : toRemove) {
129                  info.remove(aToRemove);
130                }
131              }
132    
133              for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements();) {
134                Operand def = e.nextElement();
135                if (def != null && def.isRegister()) {
136                  Register r = def.asRegister().getRegister();
137                  info.remove(r);
138                  // also must kill any registers mapped to r
139                  // TODO: use a better data structure for efficiency.
140                  // I'm being lazy for now in the name of avoiding
141                  // premature optimization.
142                  HashSet<Register> toRemove = new HashSet<Register>();
143                  for (Map.Entry<Register, Operand> entry : info.entrySet()) {
144                    Register eR = ((RegisterOperand) entry.getValue()).getRegister();
145                    if (eR == r) {
146                      // delay the removal to avoid ConcurrentModification
147                      // with iterator.
148                      toRemove.add(entry.getKey());
149                    }
150                  }
151                  // Now perform the removals.
152                  for (final Register register : toRemove) {
153                    info.remove(register);
154                  }
155                }
156              }
157            }
158            // GEN
159            if (Move.conforms(s)) {
160              Operand val = Move.getVal(s);
161              if (val.isRegister()) {
162                RegisterOperand rhs = val.asRegister();
163                if (!rhs.getRegister().isPhysical()) {
164                  RegisterOperand lhs = Move.getResult(s);
165                  /* Only gen if the move instruction does not represent a Magic <==> non-Magic coercion */
166                  if (lhs.getType().isReferenceType() == rhs.getType().isReferenceType()) {
167                    info.put(lhs.getRegister(), val);
168                  }
169                }
170              }
171            }
172          }
173          info.clear();
174        }
175      }
176    }