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 org.jikesrvm.VM;
018    import org.jikesrvm.compilers.opt.controlflow.BranchOptimizations;
019    import org.jikesrvm.compilers.opt.controlflow.BranchSimplifier;
020    import org.jikesrvm.compilers.opt.driver.CompilerPhase;
021    import org.jikesrvm.compilers.opt.ir.Move;
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.Register;
026    import org.jikesrvm.compilers.opt.ir.operand.ConstantOperand;
027    import org.jikesrvm.compilers.opt.ir.operand.Operand;
028    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
029    
030    /**
031     * Perform local constant propagation for a factored basic block.
032     * Orthogonal to the constant propagation performed in Simple
033     * since here we use flow-sensitive analysis within a basic block.
034     */
035    public class LocalConstantProp extends CompilerPhase {
036    
037      @Override
038      public final boolean shouldPerform(OptOptions options) {
039        return options.LOCAL_CONSTANT_PROP;
040      }
041    
042      @Override
043      public final String getName() {
044        return "Local ConstantProp";
045      }
046    
047      @Override
048      public void reportAdditionalStats() {
049        VM.sysWrite("  ");
050        VM.sysWrite(container.counter1 / container.counter2 * 100, 2);
051        VM.sysWrite("% Infrequent BBs");
052      }
053    
054      /**
055       * Return this instance of this phase. This phase contains no
056       * per-compilation instance fields.
057       * @param ir not used
058       * @return this
059       */
060      @Override
061      public CompilerPhase newExecution(IR ir) {
062        return this;
063      }
064    
065      /**
066       * Perform Local Constant propagation for a method.
067       *
068       * @param ir the IR to optimize
069       */
070      @Override
071      public void perform(IR ir) {
072        // info is a mapping from Register to ConstantOperand.
073        HashMap<Register, ConstantOperand> info = new HashMap<Register, ConstantOperand>();
074        boolean runBranchOpts = false;
075    
076        /* Visit each basic block and apply the optimization */
077        for (BasicBlock bb = ir.firstBasicBlockInCodeOrder(); bb != null; bb = bb.nextBasicBlockInCodeOrder()) {
078          if (bb.isEmpty()) continue; /* skip over trivial blocks */
079          container.counter2++;
080          if (bb.getInfrequent()) {
081            container.counter1++;
082            if (ir.options.FREQ_FOCUS_EFFORT) continue;
083          }
084    
085          /* Iterate over all instructions in the basic block */
086          for (Instruction s = bb.firstRealInstruction(), next, sentinel = bb.lastInstruction(); s != sentinel; s = next) {
087            next = s.nextInstructionInCodeOrder();
088    
089            /* Do we known anything ? */
090            if (!info.isEmpty()) {
091              /* Transform: attempt to propagate constants */
092              int numUses = s.getNumberOfPureUses();
093              if (numUses > 0) {
094                boolean didSomething = false;
095                int numDefs = s.getNumberOfDefs();
096                for (int idx = numDefs; idx < numUses + numDefs; idx++) {
097                  Operand use = s.getOperand(idx);
098                  if (use instanceof RegisterOperand) {
099                    RegisterOperand rUse = (RegisterOperand)use;
100                    Operand value = info.get(rUse.getRegister());
101                    if (value != null) {
102                      didSomething = true;
103                      s.putOperand(idx, value.copy());
104                    }
105                  }
106                }
107                if (didSomething) {
108                  Simplifier.simplify(ir.IRStage == IR.HIR, ir.regpool, ir.options, s);
109                }
110              }
111    
112              /* KILL: Remove bindings for all registers defined by this instruction */
113              for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements();) {
114                Operand def = e.nextElement();
115                if (def != null) {
116                  /* Don't bother special casing the case where we are defining another constant; GEN will handle that */
117                  /* Don't attempt to remove redundant assignments; let dead code elimination handle that */
118                  Register defReg = ((RegisterOperand)def).getRegister();
119                  info.remove(defReg);
120                }
121              }
122            }
123    
124            /* GEN: If this is a move operation with a constant RHS, then it defines a constant */
125            if (Move.conforms(s) && Move.getVal(s).isConstant()) {
126              info.put(Move.getResult(s).getRegister(), (ConstantOperand)Move.getVal(s));
127            }
128          }
129    
130          /* End of basic block; clean up and prepare for next block */
131          info.clear();
132          runBranchOpts |= BranchSimplifier.simplify(bb, ir);
133        }
134    
135        /* End of IR.  If we simplified a branch instruction, then run branch optimizations */
136        if (runBranchOpts) {
137          new BranchOptimizations(0, true, false, false).perform(ir);
138        }
139    
140      }
141    }