/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt; import java.util.Enumeration; import org.jikesrvm.classloader.RVMMethod; import org.jikesrvm.compilers.opt.driver.CompilerPhase; import org.jikesrvm.compilers.opt.ir.Athrow; import org.jikesrvm.compilers.opt.ir.BasicBlock; import org.jikesrvm.compilers.opt.ir.Call; import org.jikesrvm.compilers.opt.ir.IR; import org.jikesrvm.compilers.opt.ir.IfCmp; import org.jikesrvm.compilers.opt.ir.Instruction; import org.jikesrvm.compilers.opt.ir.Trap; import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand; import org.jikesrvm.compilers.opt.ir.operand.MethodOperand; /** * This pass adjusts branch probabilities derived from static estimates * to account for blocks that are statically guessed to be infrequent. */ public class AdjustBranchProbabilities extends CompilerPhase { @Override public final String getName() { return "Adjust Branch Probabilities"; } @Override public final CompilerPhase newExecution(IR ir) { return this; } /** * Simplistic adjustment of branch probabilities. * The main target of this pass is to detect idioms like * <pre> * if (P) { infrequent block } * if (P) { } else { infrequent block } * </pre> * that are introduced by ExpandRuntimeServices. * <p> * Key idea: If a block is infrequent then make sure that * any conditional branch that targets/avoids the block * does not have 0.5 as its branch probability. * * @param ir the governing IR */ @Override public final void perform(IR ir) { for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) { BasicBlock target = e.nextElement(); if (findInfrequentInstruction(target)) { blockLoop: for (Enumeration<BasicBlock> sources = target.getIn(); sources.hasMoreElements();) { BasicBlock source = sources.nextElement(); // Found an edge to an infrequent block. // Look to see if there is a conditional branch that we need to adjust Instruction condBranch = null; for (Enumeration<Instruction> ie = source.enumerateBranchInstructions(); ie.hasMoreElements();) { Instruction s = ie.nextElement(); if (IfCmp.conforms(s) && IfCmp.getBranchProfile(s).takenProbability == 0.5f) { if (condBranch == null) { condBranch = s; } else { continue blockLoop; // branching is too complicated. } } } if (condBranch != null) { BasicBlock notTaken = source.getNotTakenNextBlock(); if (notTaken == target) { // The not taken branch is the unlikely one, make the branch be taken always. IfCmp.setBranchProfile(condBranch, BranchProfileOperand.always()); } else { // The taken branch is the unlikely one, IfCmp.setBranchProfile(condBranch, BranchProfileOperand.never()); } } } } } } private boolean findInfrequentInstruction(BasicBlock bb) { for (Enumeration<Instruction> e2 = bb.forwardRealInstrEnumerator(); e2.hasMoreElements();) { Instruction s = e2.nextElement(); if (Call.conforms(s)) { MethodOperand op = Call.getMethod(s); if (op != null) { RVMMethod target = op.getTarget(); if (target != null && target.hasNoInlinePragma()) { return true; } } } else if (Athrow.conforms(s) || Trap.conforms(s)) { return true; } } return false; } }