def test_multiple_eqs(self, exprs, expected, ti0, ti1, ti3, fa): """ Tests data dependences across ordered sequences of equations representing a scope. ``expected`` is a list of comma-separated words, each word representing a dependence in the scope and consisting of three pieces of information: * the name of the function inducing a dependence * if it's a flow, anti, or output dependence * the dimension causing the dependence """ exprs = [ LoweredEq(i) for i in EVAL(exprs, ti0.base, ti1.base, ti3.base, fa) ] expected = [tuple(i.split(',')) for i in expected] # Force innatural flow, only to stress the compiler to see if it was # capable of detecting anti-dependences for i in exprs: i.ispace._directions = {i: Forward for i in i.ispace.directions} scope = Scope(exprs) assert len(scope.d_all) == len(expected) for i in ['flow', 'anti', 'output']: for dep in getattr(scope, 'd_%s' % i): item = (dep.function.name, i, str(dep.cause)) assert item in expected expected.remove(item) # Sanity check: we did find all of the expected dependences assert len(expected) == 0
def test_dependences_scope(exprs, expected, ti0, ti1, ti3, fa): """ Tests data dependences across ordered sequences of equations representing a scope. ``expected`` is a list of comma-separated words, each word representing a dependence in the scope and consisting of three pieces of information: * the name of the function inducing a dependence * if it's a flow, anti, or output dependence * the dimension causing the dependence """ exprs = EVAL(exprs, ti0.base, ti1.base, ti3.base, fa) expected = [tuple(i.split(',')) for i in expected] scope = Scope(exprs) assert len(scope.d_all) == len(expected) for i in ['flow', 'anti', 'output']: for dep in getattr(scope, 'd_%s' % i): item = (dep.function.name, i, str(dep.cause)) assert item in expected expected.remove(item) # Sanity check: we did find all of the expected dependences assert len(expected) == 0
def group_expressions(exprs): """``{exprs} -> ({exprs'}, {exprs''}, ...)`` where: :: * There are data dependences within exprs' and within exprs''; * There are *no* data dependencies across exprs' and exprs''. """ # Partion based on data dependences mapper = OrderedDict() ngroups = 0 for i, e1 in enumerate(exprs): if e1 in mapper: continue found = False for e2 in exprs[i + 1:]: if Scope([e1, e2]).has_dep: v = mapper.get(e1, mapper.get(e2)) if v is None: ngroups += 1 v = ngroups mapper[e1] = mapper[e2] = v found = True if not found: ngroups += 1 mapper[e1] = ngroups # Reorder to match input ordering groups = [] data = sorted(mapper, key=lambda i: mapper[i]) for k, g in groupby(data, key=lambda i: mapper[i]): groups.append(tuple(sorted(g, key=lambda i: exprs.index(i)))) # Sanity check assert max(mapper.values()) == len(groups) return tuple(groups)
def test_single_eq(self, expr, expected, ti0, ti1, fa): """ Tests data dependences within a single equation consisting of only two Indexeds. ``expected`` is a comma-separated word consisting of four pieces of information: * if it's a flow, anti, or output dependence * if it's loop-carried or loop-independent * the dimension causing the dependence * whether it's direct or indirect (i.e., through A[B[i]]) """ expr = LoweredEq(EVAL(expr, ti0.base, ti1.base, fa)) # Force innatural flow, only to stress the compiler to see if it was # capable of detecting anti-dependences expr.ispace._directions = {i: Forward for i in expr.ispace.directions} scope = Scope(expr) deps = scope.d_all if expected is None: assert len(deps) == 0 return else: type, mode, exp_cause, regular = expected.split(',') if type == 'all': assert len(deps) == 2 else: assert len(deps) == 1 dep = deps[0] # Check type types = ['flow', 'anti'] if type != 'all': types.remove(type) assert len(getattr(scope, 'd_%s' % type)) == 1 assert all(len(getattr(scope, 'd_%s' % i)) == 0 for i in types) else: assert all(len(getattr(scope, 'd_%s' % i)) == 1 for i in types) # Check mode assert getattr(dep, 'is_%s' % mode)() # Check cause if exp_cause == 'None': assert not dep.cause return else: assert len(dep.cause) == 1 cause = dep.cause.pop() assert cause.name == exp_cause # Check mode restricted to the cause assert getattr(dep, 'is_%s' % mode)(cause) non_causes = [i for i in [x, y, z] if i is not cause] assert all(not getattr(dep, 'is_%s' % mode)(i) for i in non_causes) # Check if it's regular or irregular assert getattr(dep.source, 'is_%s' % regular) or\ getattr(dep.sink, 'is_%s' % regular)
def test_dependences_eq(expr, expected, ti0, ti1, fa): """ Tests data dependences within a single equation consisting of only two Indexeds. ``expected`` is a comma-separated word consisting of four pieces of information: * if it's a flow, anti, or output dependence * if it's loop-carried or loop-independent * the dimension causing the dependence * whether it's direct or indirect (i.e., through A[B[i]]) """ expr = EVAL(expr, ti0.base, ti1.base, fa) scope = Scope(expr) deps = scope.d_all if expected is None: assert len(deps) == 0 return else: type, mode, cause, direct = expected.split(',') if type == 'all': assert len(deps) == 2 else: assert len(deps) == 1 dep = deps[0] # Check type types = ['flow', 'anti'] if type != 'all': types.remove(type) assert len(getattr(scope, 'd_%s' % type)) == 1 assert all(len(getattr(scope, 'd_%s' % i)) == 0 for i in types) else: assert all(len(getattr(scope, 'd_%s' % i)) == 1 for i in types) # Check mode assert getattr(dep, 'is_%s' % mode)() # Check cause if cause == 'None': assert dep.cause is None return else: assert dep.cause.name == cause # Check mode restricted to the cause assert getattr(dep, 'is_%s' % mode)(dep.cause) non_causes = [i for i in [x, y, z] if i is not dep.cause] assert all(not getattr(dep, 'is_%s' % mode)(i) for i in non_causes) # Check if it's direct or indirect assert getattr(dep, 'is_%s' % direct)