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.)