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}