/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* 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/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt;
import java.util.HashSet;
import java.util.Iterator;
import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock;
import org.jikesrvm.compilers.opt.ir.OPT_BasicBlockEnumeration;
import org.jikesrvm.compilers.opt.ir.OPT_IR;
/**
* This class holds data associated with a basic block as computed by the
* Lengauer-Tarjan dominator calculation.
* @see OPT_LTDominators
*/
class OPT_LTDominatorInfo {
static final boolean DEBUG = false;
private int semiDominator;
private OPT_BasicBlock dominator; // the imediate dominator
private OPT_BasicBlock parent;
private final HashSet<OPT_BasicBlock> bucket;
private OPT_BasicBlock label;
private OPT_BasicBlock ancestor;
// Used to keep the trees balanced, during path compression
private int size;
private OPT_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 OPT_LTDominators.DFS() for details
private OPT_BasicBlockEnumeration bbEnum;
/**
* @param block the basic block this info is associated with
*/
OPT_LTDominatorInfo(OPT_BasicBlock block) {
semiDominator = 0;
dominator = null;
parent = null;
bucket = new HashSet<OPT_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 OPT_BitVector dominators(OPT_BasicBlock block, OPT_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.
OPT_BitVector dominators = new OPT_BitVector(ir.getMaxBasicBlockNumber() + 1);
dominators.set(block.getNumber());
while ((block = getIdom(block)) != 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
* @return whether master dominates block
*/
public static boolean isDominatedBy(OPT_BasicBlock block, OPT_BasicBlock master) {
if (block == master) {
return true;
}
// walk up the dominator tree looking for the passed block
block = getIdom(block);
while (block != null && block != master) {
block = getIdom(block);
}
// 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(OPT_BasicBlock value) {
dominator = value;
}
/**
* Returns the immediate dominator for this node
* @return the immediate dominator for this node
*/
public OPT_BasicBlock getDominator() {
return dominator;
}
/**
* Sets the parent of this block
* @param value the value
*/
public void setParent(OPT_BasicBlock value) {
parent = value;
}
/**
* Returns the parent of this block
* @return the parent of this block
*/
public OPT_BasicBlock getParent() {
return parent;
}
/**
* Returns an iterator over this block's bucket
* @return an iterator over this block's bucket
*/
public Iterator<OPT_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(OPT_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(OPT_BasicBlock block) {
bucket.add(block);
}
/**
* Sets the ancestor for the value passed
* @param value the ancestor value
*/
public void setAncestor(OPT_BasicBlock value) {
ancestor = value;
}
/**
* Returns the ancestor for this block
* @return the ancestor for this block
*/
public OPT_BasicBlock getAncestor() {
return ancestor;
}
/**
* sets the label
* @param value the label
*/
public void setLabel(OPT_BasicBlock value) {
label = value;
}
/**
* returns the label
* @return the label
*/
public OPT_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(OPT_BasicBlock value) {
child = value;
}
/**
* returns the child
* @return the child
*/
public OPT_BasicBlock getChild() {
return child;
}
/**
* Helper method to return the Info field associated with a block
* @return the basic block enumeration, could be null
*/
public OPT_BasicBlockEnumeration getEnum() {
return bbEnum;
}
/**
* set the basic block enum field
* @param bbEnum basic block enum
*/
public void setEnum(OPT_BasicBlockEnumeration bbEnum) {
this.bbEnum = bbEnum;
}
/**
* Helper method to return the Info field associated with a block
* @param block the block of interest
* @return the LTInfo info
*/
public static OPT_LTDominatorInfo getInfo(OPT_BasicBlock block) {
return (OPT_LTDominatorInfo) block.scratchObject;
}
/**
* return the immediate dominator of a basic block.
* Note: the dominator info must be pre-calculated
* @param bb the basic block in question
* @return bb's immediate dominator
*/
public static OPT_BasicBlock getIdom(OPT_BasicBlock bb) {
return getInfo(bb).dominator;
}
/**
* Prints a string version of objection
*/
public String toString() {
return super.toString() + " [Parent: " + parent + " SDom: " + semiDominator + " Dom: " + dominator + "]";
}
}