diff --git a/MEMO b/MEMO index 4b22218b86eb0c727d03e75ce16ef4759c02a146..6fa8a95c5c13f13dc8d0a566c4b5aa4f89d1d65b 100644 --- a/MEMO +++ b/MEMO @@ -41,9 +41,6 @@ To-do - Automatically generate testing code vs. sequential. -- If isl can prove that all operands are positive, may use '/' instead of - 'floor_div'. - - Fix all tests - Deal with equality constraints. @@ -86,6 +83,9 @@ Future ideas Dealt with ^^^^^^^^^^ +- If isl can prove that all operands are positive, may use '/' instead of + 'floor_div'. + - For forced workgroup sizes: check that at least one iname maps to them. diff --git a/loopy/isl_helpers.py b/loopy/isl_helpers.py index ba79878e976ca6f7c0966be0954397579e312a28..d48ca1331d9f75b7d48b424811b8b8728b6606ee 100644 --- a/loopy/isl_helpers.py +++ b/loopy/isl_helpers.py @@ -227,4 +227,21 @@ def duplicate_axes(isl_obj, duplicate_inames, new_inames): +def is_nonnegative(expr, over_set): + space = over_set.get_space() + from loopy.symbolic import aff_from_expr + try: + aff = aff_from_expr(space, -expr-1) + except: + return None + expr_neg_set = isl.BasicSet.universe(space).add_constraint( + isl.Constraint.inequality_from_aff(aff)) + + return over_set.intersect(expr_neg_set).is_empty() + + + + + + # vim: foldmethod=marker diff --git a/loopy/symbolic.py b/loopy/symbolic.py index f41e1b5e3d52b8800c825fae93e79d2884805bc4..b25dd296528c9ca8d816e69376cf27e36a8ae8c5 100644 --- a/loopy/symbolic.py +++ b/loopy/symbolic.py @@ -355,10 +355,16 @@ class LoopyCCodeMapper(CCodeMapper): raise RuntimeError("nothing known about variable '%s'" % expr.aggregate.name) def map_floor_div(self, expr, prec): - if isinstance(expr.denominator, int) and expr.denominator > 0: - return ("int_floor_div_pos_b(%s, %s)" - % (self.rec(expr.numerator, PREC_NONE), - expr.denominator)) + from loopy.isl_helpers import is_nonnegative + num_nonneg = is_nonnegative(expr.numerator, self.kernel.domain) + den_nonneg = is_nonnegative(expr.denominator, self.kernel.domain) + if den_nonneg: + if num_nonneg: + return CCodeMapper.map_quotient(self, expr, prec) + else: + return ("int_floor_div_pos_b(%s, %s)" + % (self.rec(expr.numerator, PREC_NONE), + expr.denominator)) else: return ("int_floor_div(%s, %s)" % (self.rec(expr.numerator, PREC_NONE),