From 43cc6dbdab76a85ca72d943a125ce90fdf7ccac4 Mon Sep 17 00:00:00 2001
From: Andreas Kloeckner <inform@tiker.net>
Date: Mon, 31 Oct 2011 16:24:19 -0400
Subject: [PATCH] Use straight integer division if isl can show the operands
 are nonnegative.

---
 MEMO                 |  6 +++---
 loopy/isl_helpers.py | 17 +++++++++++++++++
 loopy/symbolic.py    | 14 ++++++++++----
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/MEMO b/MEMO
index 4b22218b8..6fa8a95c5 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 ba79878e9..d48ca1331 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 f41e1b5e3..b25dd2965 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),
-- 
GitLab