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 */
013package org.jikesrvm.compilers.opt;
014
015import java.util.Enumeration;
016import java.util.HashMap;
017import org.jikesrvm.VM;
018import org.jikesrvm.compilers.opt.controlflow.BranchOptimizations;
019import org.jikesrvm.compilers.opt.controlflow.BranchSimplifier;
020import org.jikesrvm.compilers.opt.driver.CompilerPhase;
021import org.jikesrvm.compilers.opt.ir.Move;
022import org.jikesrvm.compilers.opt.ir.BasicBlock;
023import org.jikesrvm.compilers.opt.ir.IR;
024import org.jikesrvm.compilers.opt.ir.Instruction;
025import org.jikesrvm.compilers.opt.ir.Register;
026import org.jikesrvm.compilers.opt.ir.operand.ConstantOperand;
027import org.jikesrvm.compilers.opt.ir.operand.Operand;
028import 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 */
035public 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}