/*
* 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.controlflow;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import org.jikesrvm.compilers.opt.ir.BasicBlock;
import org.jikesrvm.compilers.opt.ir.IR;
import org.jikesrvm.util.BitVector;
/**
* This class holds data associated with a basic block as computed by the
* Lengauer-Tarjan dominator calculation.
* @see LTDominators
*/
class LTDominatorInfo {
static final boolean DEBUG = false;
private int semiDominator;
/** the immediate dominator */
private BasicBlock dominator;
private BasicBlock parent;
private final HashSet<BasicBlock> bucket;
private BasicBlock label;
private BasicBlock ancestor;
// Used to keep the trees balanced, during path compression
private int size;
private BasicBlock child;
// used to capture activation record state to avoid the use of recursion
// in Step 1 of the LT algorithm
// A null value will signal that we have not started to process this
// block, otherwise, we'll skip the (redundant)
// initialization step for the block
// See LTDominators.DFS() for details
private Enumeration<BasicBlock> bbEnum;
/**
* @param block the basic block this info is associated with
*/
LTDominatorInfo(BasicBlock block) {
semiDominator = 0;
dominator = null;
parent = null;
bucket = new HashSet<BasicBlock>();
ancestor = null;
label = block;
size = 1;
child = null;
bbEnum = null;
}
/**
* This method returns the set of blocks that dominates the passed
* block, i.e., it answers the question "Who dominates me?"
*
* @param block the block of interest
* @param ir the governing ir
* @return a BitVector containing those blocks that dominate the passed one
*/
public BitVector dominators(BasicBlock block, IR ir) {
// Currently this set is computed on demand. We may want to cache
// the result for reuse. The cost of computing is the height of the
// the dominator tree.
BitVector dominators = new BitVector(ir.getMaxBasicBlockNumber() + 1);
dominators.set(block.getNumber());
while ((block = getIdom(block, ir)) != null) {
dominators.set(block.getNumber());
}
return dominators;
}
/**
* This method determines if the 1st parameter (block) is dominated by
* the 2nd parameter (master), i.e., must control pass through "master"
* before reaching "block"
*
* @param block the block we care about
* @param master the potential dominating block
* @param ir the IR that contains the blocks
* @return whether master dominates block
*/
public static boolean isDominatedBy(BasicBlock block, BasicBlock master, IR ir) {
if (block == master) {
return true;
}
// walk up the dominator tree looking for the passed block
block = getIdom(block, ir);
while (block != null && block != master) {
block = getIdom(block, ir);
}
// If we found the master, the condition is true
return block == master;
}
/**
* Sets the semidominator for this node
* @param value the new value
*/
public void setSemiDominator(int value) {
semiDominator = value;
}
/**
* Returns the semidomintor for this node
* @return the semidomintor for this node
*/
public int getSemiDominator() {
return semiDominator;
}
/**
* Sets the immediate dominator for this node
* @param value the value to set
*/
public void setDominator(BasicBlock value) {
dominator = value;
}
/**
* Returns the immediate dominator for this node
* @return the immediate dominator for this node
*/
public BasicBlock getDominator() {
return dominator;
}
/**
* Sets the parent of this block
* @param value the value
*/
public void setParent(BasicBlock value) {
parent = value;
}
/**
* Returns the parent of this block
* @return the parent of this block
*/
public BasicBlock getParent() {
return parent;
}
/**
* Returns an iterator over this block's bucket
* @return an iterator over this block's bucket
*/
public Iterator<BasicBlock> getBucketIterator() {
return bucket.iterator();
}
/**
* Removes the passed block from the bucket for this node
* @param block the block to remove from the bucket
*/
public void removeFromBucket(BasicBlock block) {
bucket.remove(block);
}
/**
* Adds the passed block from the bucket for this node
* @param block the block to add to our bucket
*/
public void addToBucket(BasicBlock block) {
bucket.add(block);
}
/**
* Sets the ancestor for the value passed
* @param value the ancestor value
*/
public void setAncestor(BasicBlock value) {
ancestor = value;
}
/**
* Returns the ancestor for this block
* @return the ancestor for this block
*/
public BasicBlock getAncestor() {
return ancestor;
}
/**
* sets the label
* @param value the label
*/
public void setLabel(BasicBlock value) {
label = value;
}
/**
* returns the label
* @return the label
*/
public BasicBlock getLabel() {
return label;
}
/**
* sets the size
* @param value the size
*/
public void setSize(int value) {
size = value;
}
/**
* returns the size
* @return the size
*/
public int getSize() {
return size;
}
/**
* sets the child field
* @param value the child value
*/
public void setChild(BasicBlock value) {
child = value;
}
/**
* returns the child
* @return the child
*/
public BasicBlock getChild() {
return child;
}
/**
* Helper method to return the Info field associated with a block
* @return the basic block enumeration, could be null
*/
public Enumeration<BasicBlock> getEnum() {
return bbEnum;
}
/**
* set the basic block enum field
* @param bbEnum basic block enum
*/
public void setEnum(Enumeration<BasicBlock> bbEnum) {
this.bbEnum = bbEnum;
}
/**
* Helper method to return the Info field associated with a block
* @param block the block of interest
* @param ir the IR that contains the information about the dominators
* @return the LTInfo info
*/
public static LTDominatorInfo getInfo(BasicBlock block, IR ir) {
return ir.getLtDominators().getInfo(block);
}
/**
* return the immediate dominator of a basic block.
* Note: the dominator info must be pre-calculated
* @param bb the basic block in question
* @param ir the IR that contains the information about the dominators
* @return bb's immediate dominator
*/
public static BasicBlock getIdom(BasicBlock bb, IR ir) {
return getInfo(bb, ir).dominator;
}
/**
* Prints a string version of objection
*/
@Override
public String toString() {
return super.toString() + " [Parent: " + parent + " SDom: " + semiDominator + " Dom: " + dominator + "]";
}
}