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.regalloc;
014
015import java.util.Enumeration;
016
017import org.jikesrvm.compilers.opt.ir.BasicBlock;
018import org.jikesrvm.compilers.opt.ir.IR;
019import org.jikesrvm.compilers.opt.ir.Instruction;
020import org.jikesrvm.compilers.opt.ir.Register;
021import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand;
022import org.jikesrvm.compilers.opt.ir.operand.Operand;
023
024/**
025 * An object that returns an estimate of the relative cost of spilling a
026 * symbolic register, based on basic block frequencies.
027 */
028final class BlockCountSpillCost extends SpillCostEstimator {
029
030  BlockCountSpillCost(IR ir) {
031    calculate(ir);
032  }
033
034  @Override
035  void calculate(IR ir) {
036    final double moveFactor = ir.options.REGALLOC_SIMPLE_SPILL_COST_MOVE_FACTOR;
037    final double memoryOperandFactor = ir.options.REGALLOC_SIMPLE_SPILL_COST_MEMORY_OPERAND_FACTOR;
038    for (Enumeration<BasicBlock> blocks = ir.getBasicBlocks(); blocks.hasMoreElements();) {
039      BasicBlock bb = blocks.nextElement();
040      float freq = bb.getExecutionFrequency();
041      for (Enumeration<Instruction> e = bb.forwardInstrEnumerator(); e.hasMoreElements();) {
042        Instruction s = e.nextElement();
043        double factor = freq;
044
045        if (s.isMove()) factor *= moveFactor;
046        double baseFactor = factor;
047        if (SimpleSpillCost.hasBadSizeMemoryOperand(s)) {
048          baseFactor *= memoryOperandFactor;
049        }
050
051        // first deal with non-memory operands
052        for (Enumeration<Operand> e2 = s.getRootOperands(); e2.hasMoreElements();) {
053          Operand op = e2.nextElement();
054          if (op.isRegister()) {
055            Register r = op.asRegister().getRegister();
056            if (r.isSymbolic()) {
057              update(r, baseFactor);
058            }
059          }
060        }
061        // now handle memory operands
062        factor *= memoryOperandFactor;
063        for (Enumeration<Operand> e2 = s.getMemoryOperands(); e2.hasMoreElements();) {
064          MemoryOperand M = (MemoryOperand) e2.nextElement();
065          if (M.base != null) {
066            Register r = M.base.getRegister();
067            if (r.isSymbolic()) {
068              update(r, factor);
069            }
070          }
071          if (M.index != null) {
072            Register r = M.index.getRegister();
073            if (r.isSymbolic()) {
074              update(r, factor);
075            }
076          }
077        }
078      }
079    }
080  }
081}