001/* 002 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.lir; 024 025import java.util.*; 026 027import jdk.internal.jvmci.code.*; 028 029import com.oracle.graal.compiler.common.cfg.*; 030import com.oracle.graal.lir.StandardOp.MoveOp; 031import com.oracle.graal.lir.gen.*; 032import com.oracle.graal.lir.phases.*; 033 034/** 035 * This class optimizes moves, particularly those that result from eliminating SSA form. 036 * <p> 037 * When a block has more than one predecessor, and all predecessors end with the 038 * {@linkplain Optimizer#same(LIRInstruction, LIRInstruction) same} sequence of {@linkplain MoveOp 039 * move} instructions, then these sequences can be replaced with a single copy of the sequence at 040 * the beginning of the block. 041 * <p> 042 * Similarly, when a block has more than one successor, then same sequences of moves at the 043 * beginning of the successors can be placed once at the end of the block. But because the moves 044 * must be inserted before all branch instructions, this works only when there is exactly one 045 * conditional branch at the end of the block (because the moves must be inserted before all 046 * branches, but after all compares). 047 * <p> 048 * This optimization affects all kind of moves (reg->reg, reg->stack and stack->reg). 049 * Because this optimization works best when a block contains only a few moves, it has a huge impact 050 * on the number of blocks that are totally empty. 051 */ 052public final class EdgeMoveOptimizer extends PostAllocationOptimizationPhase { 053 054 @Override 055 protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, 056 BenchmarkCounterFactory counterFactory) { 057 LIR ir = lirGenRes.getLIR(); 058 Optimizer optimizer = new Optimizer(ir); 059 060 List<? extends AbstractBlockBase<?>> blockList = ir.linearScanOrder(); 061 // ignore the first block in the list (index 0 is not processed) 062 for (int i = blockList.size() - 1; i >= 1; i--) { 063 AbstractBlockBase<?> block = blockList.get(i); 064 065 if (block.getPredecessorCount() > 1) { 066 optimizer.optimizeMovesAtBlockEnd(block); 067 } 068 if (block.getSuccessorCount() == 2) { 069 optimizer.optimizeMovesAtBlockBegin(block); 070 } 071 } 072 } 073 074 private static final class Optimizer { 075 private final List<List<LIRInstruction>> edgeInstructionSeqences; 076 private LIR ir; 077 078 public Optimizer(LIR ir) { 079 this.ir = ir; 080 edgeInstructionSeqences = new ArrayList<>(4); 081 } 082 083 /** 084 * Determines if two operations are both {@linkplain MoveOp moves} that have the same 085 * {@linkplain MoveOp#getInput() source} and {@linkplain MoveOp#getResult() destination} 086 * operands. 087 * 088 * @param op1 the first instruction to compare 089 * @param op2 the second instruction to compare 090 * @return {@code true} if {@code op1} and {@code op2} are the same by the above algorithm 091 */ 092 private static boolean same(LIRInstruction op1, LIRInstruction op2) { 093 assert op1 != null; 094 assert op2 != null; 095 096 if (op1 instanceof MoveOp && op2 instanceof MoveOp) { 097 MoveOp move1 = (MoveOp) op1; 098 MoveOp move2 = (MoveOp) op2; 099 if (move1.getInput().equals(move2.getInput()) && move1.getResult().equals(move2.getResult())) { 100 // these moves are exactly equal and can be optimized 101 return true; 102 } 103 } 104 return false; 105 } 106 107 /** 108 * Moves the longest {@linkplain #same common} subsequence at the end all predecessors of 109 * {@code block} to the start of {@code block}. 110 */ 111 private void optimizeMovesAtBlockEnd(AbstractBlockBase<?> block) { 112 for (AbstractBlockBase<?> pred : block.getPredecessors()) { 113 if (pred == block) { 114 // currently we can't handle this correctly. 115 return; 116 } 117 } 118 119 // clear all internal data structures 120 edgeInstructionSeqences.clear(); 121 122 int numPreds = block.getPredecessorCount(); 123 assert numPreds > 1 : "do not call otherwise"; 124 125 // setup a list with the LIR instructions of all predecessors 126 for (AbstractBlockBase<?> pred : block.getPredecessors()) { 127 assert pred != null; 128 assert ir.getLIRforBlock(pred) != null; 129 List<LIRInstruction> predInstructions = ir.getLIRforBlock(pred); 130 131 if (pred.getSuccessorCount() != 1) { 132 // this can happen with switch-statements where multiple edges are between 133 // the same blocks. 134 return; 135 } 136 137 assert pred.getSuccessors().iterator().next() == block : "invalid control flow"; 138 assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; 139 140 if (predInstructions.get(predInstructions.size() - 1).hasState()) { 141 // can not optimize instructions that have debug info 142 return; 143 } 144 145 // ignore the unconditional branch at the end of the block 146 List<LIRInstruction> seq = predInstructions.subList(0, predInstructions.size() - 1); 147 edgeInstructionSeqences.add(seq); 148 } 149 150 // process lir-instructions while all predecessors end with the same instruction 151 while (true) { 152 List<LIRInstruction> seq = edgeInstructionSeqences.get(0); 153 if (seq.isEmpty()) { 154 return; 155 } 156 157 LIRInstruction op = last(seq); 158 for (int i = 1; i < numPreds; ++i) { 159 List<LIRInstruction> otherSeq = edgeInstructionSeqences.get(i); 160 if (otherSeq.isEmpty() || !same(op, last(otherSeq))) { 161 return; 162 } 163 } 164 165 // insert the instruction at the beginning of the current block 166 ir.getLIRforBlock(block).add(1, op); 167 168 // delete the instruction at the end of all predecessors 169 for (int i = 0; i < numPreds; i++) { 170 seq = edgeInstructionSeqences.get(i); 171 removeLast(seq); 172 } 173 } 174 } 175 176 /** 177 * Moves the longest {@linkplain #same common} subsequence at the start of all successors of 178 * {@code block} to the end of {@code block} just prior to the branch instruction ending 179 * {@code block}. 180 */ 181 private void optimizeMovesAtBlockBegin(AbstractBlockBase<?> block) { 182 183 edgeInstructionSeqences.clear(); 184 int numSux = block.getSuccessorCount(); 185 186 List<LIRInstruction> instructions = ir.getLIRforBlock(block); 187 188 assert numSux == 2 : "method should not be called otherwise"; 189 190 LIRInstruction lastInstruction = instructions.get(instructions.size() - 1); 191 if (lastInstruction.hasState()) { 192 // cannot optimize instructions when debug info is needed 193 return; 194 } 195 196 LIRInstruction branch = lastInstruction; 197 if (!(branch instanceof StandardOp.BranchOp) || branch.hasOperands()) { 198 // Only blocks that end with a conditional branch are optimized. 199 // In addition, a conditional branch with operands (including state) cannot 200 // be optimized. Moving a successor instruction before such a branch may 201 // interfere with the operands of the branch. For example, a successive move 202 // instruction may redefine an input operand of the branch. 203 return; 204 } 205 206 // Now it is guaranteed that the block ends with a conditional branch. 207 // The instructions are inserted at the end of the block before the branch. 208 int insertIdx = instructions.size() - 1; 209 210 // setup a list with the lir-instructions of all successors 211 for (AbstractBlockBase<?> sux : block.getSuccessors()) { 212 List<LIRInstruction> suxInstructions = ir.getLIRforBlock(sux); 213 214 assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; 215 216 if (sux.getPredecessorCount() != 1) { 217 // this can happen with switch-statements where multiple edges are between 218 // the same blocks. 219 return; 220 } 221 assert sux.getPredecessors().iterator().next() == block : "invalid control flow"; 222 223 // ignore the label at the beginning of the block 224 List<LIRInstruction> seq = suxInstructions.subList(1, suxInstructions.size()); 225 edgeInstructionSeqences.add(seq); 226 } 227 228 // process LIR instructions while all successors begin with the same instruction 229 while (true) { 230 List<LIRInstruction> seq = edgeInstructionSeqences.get(0); 231 if (seq.isEmpty()) { 232 return; 233 } 234 235 LIRInstruction op = first(seq); 236 for (int i = 1; i < numSux; i++) { 237 List<LIRInstruction> otherSeq = edgeInstructionSeqences.get(i); 238 if (otherSeq.isEmpty() || !same(op, first(otherSeq))) { 239 // these instructions are different and cannot be optimized . 240 // no further optimization possible 241 return; 242 } 243 } 244 245 // insert instruction at end of current block 246 ir.getLIRforBlock(block).add(insertIdx, op); 247 insertIdx++; 248 249 // delete the instructions at the beginning of all successors 250 for (int i = 0; i < numSux; i++) { 251 seq = edgeInstructionSeqences.get(i); 252 removeFirst(seq); 253 } 254 } 255 } 256 257 /** 258 * Gets the first element from a LIR instruction sequence. 259 */ 260 private static LIRInstruction first(List<LIRInstruction> seq) { 261 return seq.get(0); 262 } 263 264 /** 265 * Gets the last element from a LIR instruction sequence. 266 */ 267 private static LIRInstruction last(List<LIRInstruction> seq) { 268 return seq.get(seq.size() - 1); 269 } 270 271 /** 272 * Removes the first element from a LIR instruction sequence. 273 */ 274 private static void removeFirst(List<LIRInstruction> seq) { 275 seq.remove(0); 276 } 277 278 /** 279 * Removes the last element from a LIR instruction sequence. 280 */ 281 private static void removeLast(List<LIRInstruction> seq) { 282 seq.remove(seq.size() - 1); 283 } 284 285 } 286}