next up previous
Next: replace() Up: Use of Expressions Previous: assign()/pull()

Calculating range expressions

Here is some sample code that will determine the range of values that a single reduction array subscript may take.

// Initialization code.  Execute only once in your pass.

#include "/groups/polaris/cvdl/AIRangeDict.h"
// #include "/groups/polaris/cvdl/ControlRangeDict.h"
#include "/groups/polaris/cvdl/RangeAccessor.h"
#include "/groups/polaris/cvdl/range.h"

// Determine the set of ranges holding for each statement in the the
// program unit.

RangeDict *ranges = new AIRangeDict(pgm);

// A faster but less accurate way to compute ranges for a program.
// (Twice as fast, but only collects ranges from IF conditionals and
// loop bounds.)

// RangeDict *ranges = new ControlRangeDict(pgm);

 ...

// Code executed for each reduction statement.  This example only
// looks at the first array subscript of the reduction.  It can
// easily be extended to handle multiple array subscripts.

// Create an object to compare expressions, using the ranges
// that hold for a given statement.  Reduction_stmt is the current
// reduction statement.

RangeAccessor accessor(ranges, reduction_stmt);

// Compute the range taken by the first array subscript of the
// reduction statement.  Loop_variant_vars is a set of variables
// (i.e. RefSet<Symbol>) that are loop variant for the loop in which
// the reduction is being parallelized.  Range_expr is the 
// resulting range.

Expression *range_expr
    = accessor.eliminate_vars(reduction_stmt.lhs().subscript().arg_list()[0],
                              loop_variant_vars);

// The returned expression may be a RangeExpr object, indicating the
// range that the reduction's array subscript may take, or it
// may be some other expression, indicating a range that spans a
// single element.  So, we would need to test whether range_expr
// is type RANGE_OP or not.

Expression *lower_bound, *upper_bound;

if (range_expr->op() == RANGE_OP) {
    RangeExpr range = * (RangeExpr *) range_expr;
    lower_bound = range.grab_lb();
    upper_bound = range.grab_ub();
}
else {
    lower_bound = range_expr->clone();
    upper_bound = range_expr->clone();
}	

delete range_expr;

Now, if you wish to merge two ranges together, you can just call the routine union_ranges(), found in /groups/polaris/cvdl/range/range_util.h.

To learn more about the interfaces to the range propagation pass, read the comments in range.h, AIRangeDict.h, ControlRangeDict.h, RangeAccessor.h, RangeComparator.h, range_utils.h, and Relation.h. (Reading just range.h, RangeAccessor.h, and part of RangeComparator.h should be sufficient.)



Jay Hoeflinger
Mon Apr 21 11:52:18 CDT 1997