def get_scalar_cvars(pattern): cvars = {} def maybe_add(access): if access.is_scalar() and access.var not in cvars: cvars[access.var] = Int(access.var) for access in get_accesses(pattern): maybe_add(access) for decl in pattern.decls: for size in decl.sizes: if size is not None: for access in get_accesses(size): maybe_add(access) return cvars
def start(self, args): decls = [] body = [] # consts = [] for arg in args: if type(arg) == Declaration: decls.append(arg) elif type(arg) in [AbstractLoop, Assignment]: body.append(arg) else: raise RuntimeError('Unsupported syntax in main program') # Add implicit constants that are created when the bounds and steps # of loop vars are not explicitly stated non_consts = set() for decl in decls: non_consts.add(decl.name) for stmt in body: for loop in get_loops(stmt): for shape in loop.loop_shapes: non_consts.add(shape.loop_var.var) consts_set = set() for stmt in body: for access in get_accesses(stmt): if access.var not in non_consts: consts_set.add(access.var) consts = [Const(name) for name in sorted(list(consts_set))] return Program(decls, body, consts)
def get_int_cvars(pattern, types): cvars = {} def maybe_add(access): name = access.pprint() if types.can_be(access.var, 'int') and name not in cvars: cvars[name] = Int(name) for access in get_accesses(pattern): maybe_add(access) for decl in pattern.decls: for size in decl.sizes: if size is not None: for access in get_accesses(size): maybe_add(access) return cvars
def iterate_unique_reference_pairs(program): refs = list(get_accesses(program)) n_refs = len(refs) for i in range(0, n_refs): for j in range(i, n_refs): ref1 = refs[i] ref2 = refs[j] if ref1.var != ref2.var: continue if not ref1.is_write and not ref2.is_write: continue yield (ref1, ref2)
def try_once(): random_pattern = replace_constant_variables_blindly(pattern, var_map) cvars = get_scalar_cvars(random_pattern) accesses = get_accesses(random_pattern) cloned_var_map = var_map.clone() # Set array sizes in var map for decl in random_pattern.decls: for dimension in range(decl.n_dimensions): size = decl.sizes[dimension] if size is not None: dim_var = dimension_var(decl.name, dimension) # TODO: we don't really need min cloned_var_map.set_min(dim_var, 0) # TODO: maybe allow more room for the max cloned_var_map.set_max(dim_var, size) index_constraints = generate_index_constraints(accesses, cvars, cloned_var_map) loop_shape_constraints = [] for loop in get_loops(random_pattern): loop_shape_constraints += generate_loop_shape_constraints(loop.loop_shapes, cvars, cloned_var_map) bound_constraints = generate_bound_constraints(random_pattern.decls, cvars, cloned_var_map) l.debug('Index constraints:\n' + '\n'.join(map(str, index_constraints))) l.debug('Loop shape constraints:\n' + '\n'.join(map(str, loop_shape_constraints))) l.debug('Bound constraints:\n' + '\n'.join(map(str, bound_constraints))) assert(len(index_constraints) > 0) invert_index_constraints = Not(And(index_constraints)) constraints = [invert_index_constraints] + loop_shape_constraints + bound_constraints solver = Solver() solver.set('timeout', 10000) solver.add(constraints) status = solver.check() if status != unsat: l.debug(f'Constraints are not unsatisfiable ({status}). ' 'May result in index out of bound') l.debug('Constraints:\n' + '\n'.join(map(str, constraints))) if status == sat: l.debug(f'Model:\n{solver.model()}') return None constraints = index_constraints + loop_shape_constraints + bound_constraints solver = Solver() solver.set('timeout', 10000) solver.add(constraints) status = solver.check() if status != sat: l.debug(f'Constraints are not satisfiable ({status}). ' 'May result in no iterations') l.debug('\n'.join(map(str, constraints))) return None bounds = determine_array_access_bounds(random_pattern.decls, accesses, cvars, constraints, cloned_var_map, l) if bounds is None: return None # assign types once we're sure it's a valid program nonlocal types if types is None: types = TypeAssignment() assign_types(random_pattern, types) return Instance(random_pattern, bounds)