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;
016import org.jikesrvm.compilers.opt.ir.BasicBlock;
017import org.jikesrvm.compilers.opt.ir.IR;
018import org.jikesrvm.compilers.opt.ir.Instruction;
019import org.jikesrvm.compilers.opt.ir.Register;
020import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand;
021import org.jikesrvm.compilers.opt.ir.operand.Operand;
022
023/**
024 * An object that returns an estimate of the relative cost of spilling a
025 * symbolic register.
026 */
027final class SimpleSpillCost extends SpillCostEstimator {
028
029  SimpleSpillCost(IR ir) {
030    calculate(ir);
031  }
032
033  @Override
034  void calculate(IR ir) {
035    final double moveFactor = ir.options.REGALLOC_SIMPLE_SPILL_COST_MOVE_FACTOR;
036    final double memoryOperandFactor = ir.options.REGALLOC_SIMPLE_SPILL_COST_MEMORY_OPERAND_FACTOR;
037    for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) {
038      BasicBlock bb = e.nextElement();
039      for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements();) {
040        Instruction s = ie.nextElement();
041        double factor = (bb.getInfrequent()) ? 0.0 : 1.0;
042        if (s.isMove()) {
043          factor *= moveFactor;
044        }
045        double baseFactor = factor;
046        if (hasBadSizeMemoryOperand(s)) {
047          baseFactor *= memoryOperandFactor;
048        }
049        // first deal with non-memory operands
050        for (Enumeration<Operand> e2 = s.getRootOperands(); e2.hasMoreElements();) {
051          Operand op = e2.nextElement();
052          if (op.isRegister()) {
053            Register r = op.asRegister().getRegister();
054            if (r.isSymbolic()) {
055              update(r, baseFactor);
056            }
057          }
058        }
059        // now handle memory operands
060        factor *= memoryOperandFactor;
061        for (Enumeration<Operand> e2 = s.getMemoryOperands(); e2.hasMoreElements();) {
062          MemoryOperand M = (MemoryOperand) e2.nextElement();
063          if (M.base != null) {
064            Register r = M.base.getRegister();
065            if (r.isSymbolic()) {
066              update(r, factor);
067            }
068          }
069          if (M.index != null) {
070            Register r = M.index.getRegister();
071            if (r.isSymbolic()) {
072              update(r, factor);
073            }
074          }
075        }
076      }
077    }
078  }
079
080  /**
081   * Does instruction s have a memory operand of an inconvenient size?<p>
082   *
083   * NOTE: This is pretty intel-specific.
084   * TODO Refactor to arch/ tree.
085   *
086   * @param s the instruction to examine
087   * @return {@code true} if and only if the instruction has such a memory
088   *   operand
089   */
090  static boolean hasBadSizeMemoryOperand(Instruction s) {
091    for (Enumeration<Operand> e = s.getMemoryOperands(); e.hasMoreElements();) {
092      MemoryOperand M = (MemoryOperand) e.nextElement();
093      if (M.size != 4) return true;
094    }
095    return false;
096  }
097}