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.regalloc;
014
015 import java.util.Enumeration;
016 import org.jikesrvm.compilers.opt.ir.BasicBlock;
017 import org.jikesrvm.compilers.opt.ir.IR;
018 import org.jikesrvm.compilers.opt.ir.Instruction;
019 import org.jikesrvm.compilers.opt.ir.Register;
020 import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand;
021 import 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 */
027 class SimpleSpillCost extends SpillCostEstimator {
028
029 SimpleSpillCost(IR ir) {
030 calculate(ir);
031 }
032
033 /**
034 * Calculate the estimated cost for each register.
035 */
036 void calculate(IR ir) {
037 final double moveFactor = ir.options.REGALLOC_SIMPLE_SPILL_COST_MOVE_FACTOR;
038 final double memoryOperandFactor = ir.options.REGALLOC_SIMPLE_SPILL_COST_MEMORY_OPERAND_FACTOR;
039 for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) {
040 BasicBlock bb = e.nextElement();
041 for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements();) {
042 Instruction s = ie.nextElement();
043 double factor = (bb.getInfrequent()) ? 0.0 : 1.0;
044 if (s.isMove()) {
045 factor *= moveFactor;
046 }
047 double baseFactor = factor;
048 if (hasBadSizeMemoryOperand(s)) {
049 baseFactor *= memoryOperandFactor;
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
082 /**
083 * Does instruction s have a memory operand of an inconvenient size?
084 * NOTE: This is pretty intel-specific. Refactor to arch/ tree.
085 */
086 static boolean hasBadSizeMemoryOperand(Instruction s) {
087 for (Enumeration<Operand> e = s.getMemoryOperands(); e.hasMoreElements();) {
088 MemoryOperand M = (MemoryOperand) e.nextElement();
089 if (M.size != 4) return true;
090 }
091 return false;
092 }
093 }