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.controlflow; 014 015 import static org.jikesrvm.compilers.opt.ir.Operators.BBEND; 016 import static org.jikesrvm.compilers.opt.ir.Operators.LABEL; 017 018 import java.util.Enumeration; 019 020 import org.jikesrvm.VM; 021 import org.jikesrvm.compilers.opt.DefUse; 022 import org.jikesrvm.compilers.opt.OptOptions; 023 import org.jikesrvm.compilers.opt.driver.CompilerPhase; 024 import org.jikesrvm.compilers.opt.ir.BasicBlock; 025 import org.jikesrvm.compilers.opt.ir.IR; 026 import org.jikesrvm.compilers.opt.ir.Instruction; 027 import org.jikesrvm.compilers.opt.ir.Trap; 028 import org.jikesrvm.compilers.opt.util.SpaceEffGraphNode; 029 030 /** 031 * IR level independent driver for 032 * simple peephole optimizations of branches. 033 */ 034 public abstract class BranchOptimizationDriver extends CompilerPhase { 035 036 /** 037 * Optimization level at which phase should be performed. 038 */ 039 private final int level; 040 041 /** 042 * Optimization level at which phase should be performed. 043 */ 044 private final boolean simplify; 045 046 /** 047 * @param level the minimum optimization level at which the branch 048 * optimizations should be performed. 049 * @param simplify perform simplification prior to optimization? 050 */ 051 BranchOptimizationDriver(int level, boolean simplify) { 052 this.level = level; 053 this.simplify = simplify; 054 } 055 056 /** 057 * @param level the minimum optimization level at which the branch 058 * optimizations should be performed. 059 */ 060 BranchOptimizationDriver(int level) { 061 this.level = level; 062 this.simplify = false; 063 } 064 065 /** Interface */ 066 @Override 067 public final boolean shouldPerform(OptOptions options) { 068 return options.getOptLevel() >= level; 069 } 070 071 @Override 072 public final String getName() { 073 return "Branch Optimizations"; 074 } 075 076 @Override 077 public final boolean printingEnabled(OptOptions options, boolean before) { 078 return false; 079 } 080 081 /** 082 * This phase contains no per-compilation instance fields. 083 */ 084 @Override 085 public final CompilerPhase newExecution(IR ir) { 086 return this; 087 } 088 089 /** 090 * Perform peephole branch optimizations. 091 * 092 * @param ir the IR to optimize 093 */ 094 @Override 095 public final void perform(IR ir) { 096 perform(ir, true); 097 } 098 099 public final void perform(IR ir, boolean renumber) { 100 if (simplify) { 101 applySimplify(ir); 102 } 103 104 maximizeBasicBlocks(ir); 105 if (VM.BuildForIA32) { 106 // spans-bb information is used for CMOV insertion 107 DefUse.recomputeSpansBasicBlock(ir); 108 } 109 boolean didSomething = false; 110 boolean didSomethingThisTime = true; 111 while (didSomethingThisTime) { 112 didSomething |= applyPeepholeBranchOpts(ir); 113 didSomethingThisTime = removeUnreachableCode(ir); 114 didSomething |= didSomethingThisTime; 115 } 116 if (didSomething) { 117 maximizeBasicBlocks(ir); 118 } 119 120 ir.cfg.compactNodeNumbering(); 121 122 if (ir.IRStage < IR.MIR) { 123 ir.pruneExceptionalOut(); 124 } 125 } 126 127 /** 128 * Perform branch simplifications. 129 * 130 * @param ir the IR to optimize 131 * @return was something reduced 132 */ 133 private static boolean applySimplify(IR ir) { 134 boolean didSomething = false; 135 for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) { 136 BasicBlock bb = e.nextElement(); 137 didSomething |= BranchSimplifier.simplify(bb, ir); 138 } 139 return didSomething; 140 } 141 142 /** 143 * This pass performs peephole branch optimizations. 144 * See Muchnick ~p.590 145 * 146 * @param ir the IR to optimize 147 */ 148 protected boolean applyPeepholeBranchOpts(IR ir) { 149 boolean didSomething = false; 150 for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) { 151 BasicBlock bb = e.nextElement(); 152 if (!bb.isEmpty()) { 153 for (Enumeration<Instruction> ie = bb.enumerateBranchInstructions(); ie.hasMoreElements();) { 154 Instruction s = ie.nextElement(); 155 if (optimizeBranchInstruction(ir, s, bb)) { 156 didSomething = true; 157 // hack: we may have modified the instructions; start over 158 ie = bb.enumerateBranchInstructions(); 159 } 160 } 161 } 162 } 163 return didSomething; 164 } 165 166 /** 167 * This method actually does the work of attempting to 168 * peephole optimize a branch instruction. 169 * @param ir the containing IR 170 * @param s the branch instruction to optimize 171 * @param bb the containing basic block 172 * @return true if an optimization was applied, false otherwise 173 */ 174 protected abstract boolean optimizeBranchInstruction(IR ir, Instruction s, BasicBlock bb); 175 176 /** 177 * Remove unreachable code 178 * 179 * @param ir the IR to optimize 180 * @return true if did something, false otherwise 181 */ 182 protected final boolean removeUnreachableCode(IR ir) { 183 boolean result = false; 184 185 // (1) All code in a basic block after an unconditional 186 // trap instruction is dead. 187 for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) { 188 if (Trap.conforms(s)) { 189 Instruction p = s.nextInstructionInCodeOrder(); 190 if (p.operator() != BBEND) { 191 BasicBlock bb = s.getBasicBlock(); 192 do { 193 Instruction q = p; 194 p = p.nextInstructionInCodeOrder(); 195 q.remove(); 196 } while (p.operator() != BBEND); 197 bb.recomputeNormalOut(ir); 198 result = true; 199 } 200 } 201 } 202 203 // (2) perform a Depth-first search of the control flow graph, 204 // and remove any nodes not reachable from entry. 205 BasicBlock entry = ir.cfg.entry(); 206 ir.cfg.clearDFS(); 207 entry.sortDFS(); 208 for (SpaceEffGraphNode node = entry; node != null;) { 209 // save it now before removeFromCFGAndCodeOrder nulls it out!!! 210 SpaceEffGraphNode nextNode = node.getNext(); 211 if (!node.dfsVisited()) { 212 BasicBlock bb = (BasicBlock) node; 213 ir.cfg.removeFromCFGAndCodeOrder(bb); 214 result = true; 215 } 216 node = nextNode; 217 } 218 return result; 219 } 220 221 /** 222 * Merge adjacent basic blocks 223 * 224 * @param ir the IR to optimize 225 */ 226 protected final void maximizeBasicBlocks(IR ir) { 227 for (BasicBlock currBB = ir.cfg.firstInCodeOrder(); currBB != null;) { 228 if (currBB.mergeFallThrough(ir)) { 229 // don't advance currBB; it may have a new trivial fallthrough to swallow 230 } else { 231 currBB = currBB.nextBasicBlockInCodeOrder(); 232 } 233 } 234 } 235 236 // Helper functions 237 238 /** 239 * Given an instruction s, return the first LABEL instruction 240 * following s. 241 */ 242 protected final Instruction firstLabelFollowing(Instruction s) { 243 for (s = s.nextInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) { 244 if (s.operator() == LABEL) { 245 return s; 246 } 247 } 248 return null; 249 } 250 251 /** 252 * Given an instruction s, return the first real (non-label) instruction 253 * following s 254 */ 255 protected final Instruction firstRealInstructionFollowing(Instruction s) { 256 for (s = s.nextInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) { 257 if (s.operator() != LABEL && s.operator() != BBEND) { 258 return s; 259 } 260 } 261 return s; 262 } 263 }