public class RangeAnalysis extends AnalysisPass
The goal of Range Analysis is to collect, at each program statement, a map from integer-typed scalar variables to their symbolic value ranges, represented by a symbolic lower bound and an upper bound. In other words, a symbolic value range expresses the relationship between the variables that appear in the range. We use a similar approach as in Symbolic Range Propagation in the Polaris parallelizing compiler, with necessary adjustment for the C language, to compute the set of value ranges before each statement. The set of value ranges at each statement can be used in several ways. Pass writers can directly query the symbolic bound of a variable or can compare two symbolic expressions using the constraints given by the set of value ranges.
The high-level algorithm performs fix-point iteration in two phases when propagating the value ranges throughout the program. The first phase applies widening operations at nodes that have incoming back edges to guarantee the termination of the algorithm. The second phase compensates the loss of information due to the widening operations by applying narrowing operation to the node at which widening has occurred. During the fix-point iteration, the value ranges are merged at nodes that have multiple predecessors, and outgoing value ranges are computed by symbolically executing the statement. Two typical types of program semantics that cause such changes of value ranges are constraints from conditional expressions and assignments to variables.
Range analysis returns a map from each statement to its corresponding
RangeDomain
that contains the set of valid value ranges before
each statement. The result of this analysis was verified with the
C benchmarks in the SPEC CPU2006 suite. Range analysis does not handle
integer overflow as it does not model the overflow but such cases are rare
in normal correct programs. Following example shows how to invoke a range
analyzer in a compiler pass:
Map<Statement, RangeDomain> range_map = RangeAnalysis.getRanges(procedure); RangeDomain range_domain = range_map.get(statement); // range_domain now contains the set of value ranges for the statement.Following example shows a function and its range map created after the range analysis.
int foo(int k) { [] int i, j; [] double a; [] for ( i=0; i<10; ++i ) { [0<=i<=9] a=(0.5*i); } [i=10] j=(i+k); [i=10, j=(i+k)] return j; }
Modifier and Type | Field and Description |
---|---|
static int |
RANGE_EMPTY
Option for disabling range computation
|
static int |
RANGE_INTER
Option for enforcing inter-procedural analysis
|
static int |
RANGE_INTRA
Option for enforcing intra-procedural analysis
|
static int |
RANGE_PRAGMA
Option for enforcing use of range pragma and constraint
|
Constructor and Description |
---|
RangeAnalysis(Program program)
Constructs a range analyzer for the program.
|
Modifier and Type | Method and Description |
---|---|
static RangeDomain |
extractRanges(Expression e) |
java.lang.String |
getPassName()
Returns the pass name.
|
static RangeDomain |
getRangeDomain(Statement stmt)
Returns a range domain for the given statement.
|
java.util.Map<Statement,RangeDomain> |
getRangeMap(Procedure proc)
Performs range analysis for the procedure and returns the result.
|
static java.util.Map<Statement,RangeDomain> |
getRanges(SymbolTable symtab)
Returns a range map created for the symbol table object.
|
static java.util.Map<Statement,RangeDomain> |
getRanges(SymbolTable symtab,
int temporal_option)
Enforces use of the specified option for computing the ranges
|
static void |
invalidate()
Invalidates range domains stored in the static spaces.
|
static RangeDomain |
query(Statement stmt)
Returns a range domain associated with the specified statement.
|
static void |
registerSafeFunction(java.lang.String name,
java.lang.String... names)
Register the specified function names in the safe list of function calls.
|
void |
start()
Starts range analysis for the whole program.
|
static java.lang.String |
toPrettyRanges(Traversable t,
java.util.Map<Statement,RangeDomain> ranges,
java.lang.Integer indent)
Returns the range map in a pretty format.
|
run
public static final int RANGE_EMPTY
public static final int RANGE_INTRA
public static final int RANGE_INTER
public static final int RANGE_PRAGMA
public RangeAnalysis(Program program)
program
- the input program.public java.lang.String getPassName()
getPassName
in class AnalysisPass
public void start()
start
in class AnalysisPass
public java.util.Map<Statement,RangeDomain> getRangeMap(Procedure proc)
proc
- the input procedure.public static java.lang.String toPrettyRanges(Traversable t, java.util.Map<Statement,RangeDomain> ranges, java.lang.Integer indent)
t
- the traversable object.ranges
- the range map.indent
- the indent for pretty printing.public static java.util.Map<Statement,RangeDomain> getRanges(SymbolTable symtab, int temporal_option)
public static java.util.Map<Statement,RangeDomain> getRanges(SymbolTable symtab)
symtab
- the symbol table object whose range map is collected.public static RangeDomain getRangeDomain(Statement stmt)
stmt
- the input statement.public static RangeDomain extractRanges(Expression e)
public static RangeDomain query(Statement stmt)
stmt
are recomputed
, and then the associated range domain is returned.stmt
- the statement of interest.public static void invalidate()
public static void registerSafeFunction(java.lang.String name, java.lang.String... names)