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.lir2mir;
014
015import java.util.Enumeration;
016
017import org.jikesrvm.compilers.opt.OptimizingCompilerException;
018import org.jikesrvm.compilers.opt.driver.CompilerPhase;
019import org.jikesrvm.compilers.opt.ir.BasicBlock;
020import org.jikesrvm.compilers.opt.ir.IR;
021import org.jikesrvm.compilers.opt.ir.Instruction;
022
023/**
024 * Splits a large basic block into smaller ones with {@code size <=
025 * OptOptions.L2M_MAX_BLOCK_SIZE}
026 */
027public final class SplitBasicBlock extends CompilerPhase {
028
029  @Override
030  public String getName() {
031    return "SplitBasicBlock";
032  }
033
034  @Override
035  public CompilerPhase newExecution(IR ir) {
036    return this;
037  }
038
039  @Override
040  public void perform(IR ir) {
041    for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) {
042      BasicBlock bb = e.nextElement();
043
044      if (!bb.isEmpty()) {
045        while (bb != null) {
046          bb = splitEachBlock(bb, ir);
047        }
048      }
049    }
050  }
051
052  /**
053   * Splits a basic block.
054   *
055   * @param bb the block to process
056   * @param ir the IR that contains the block
057   *
058   * @return {@code null} if no splitting is done, returns the second block
059   *  if splitting is done.
060   */
061  BasicBlock splitEachBlock(BasicBlock bb, IR ir) {
062    if (ir.options.L2M_MAX_BLOCK_SIZE <= 0) {
063      throw new OptimizingCompilerException("Maximum block size must be a" +
064          " positive number but was " +
065          ir.options.L2M_MAX_BLOCK_SIZE + "!", true);
066    }
067
068    int remainingInstCount = ir.options.L2M_MAX_BLOCK_SIZE;
069
070    Enumeration<Instruction> instructions = bb.forwardRealInstrEnumerator();
071    while (instructions.hasMoreElements()) {
072      Instruction inst = instructions.nextElement();
073      remainingInstCount--;
074      if (remainingInstCount <= 0) {
075        // no need to split because all the rests are just branches
076        if (inst.isBranch()) {
077          return null;
078        }
079        // no need to split because the basic block does not contain any more instructions
080        if (!instructions.hasMoreElements()) {
081          return null;
082        }
083
084        return bb.splitNodeWithLinksAt(inst, ir);
085      }
086    }
087
088    return null;
089  }
090
091}