Add isl operator overloads for isl::pw_aff

Piecewise affine expressions have directly corresponding mathematical
operators. Introduce these operators as overloads as this makes writing
code with isl::pw_aff expressions more directly readable.

We can now write:

  A = B + C    instead of    A = B.add(C)

git-svn-id: https://llvm.org/svn/llvm-project/polly/trunk@327216 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/polly/Support/ISLOperators.h b/include/polly/Support/ISLOperators.h
new file mode 100644
index 0000000..98ea42c
--- /dev/null
+++ b/include/polly/Support/ISLOperators.h
@@ -0,0 +1,119 @@
+//===------ IslOperators.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Operator overloads for isl C++ objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "isl/isl-noexceptions.h"
+namespace polly {
+
+inline isl::pw_aff operator+(isl::pw_aff A, isl::pw_aff B) { return A.add(B); }
+
+inline isl::pw_aff operator+(isl::val V, isl::pw_aff A) {
+  isl::pw_aff AV(A.domain(), V);
+  return A.add(AV);
+}
+
+inline isl::pw_aff operator+(isl::pw_aff A, isl::val V) { return V + A; }
+
+inline isl::pw_aff operator+(int i, isl::pw_aff A) {
+  isl::ctx ctx = A.get_ctx();
+  return A + isl::val(ctx, i);
+}
+
+inline isl::pw_aff operator+(isl::pw_aff A, int i) { return i + A; }
+
+inline isl::pw_aff operator*(isl::pw_aff A, isl::pw_aff B) { return A.mul(B); }
+
+inline isl::pw_aff operator*(isl::val V, isl::pw_aff A) {
+  isl::pw_aff AV(A.domain(), V);
+  return A.add(AV);
+}
+
+inline isl::pw_aff operator*(isl::pw_aff A, isl::val V) { return V * A; }
+
+inline isl::pw_aff operator*(int i, isl::pw_aff A) {
+  isl::ctx ctx = A.get_ctx();
+  return A * isl::val(ctx, i);
+}
+
+inline isl::pw_aff operator*(isl::pw_aff A, int i) { return i * A; }
+
+inline isl::pw_aff operator-(isl::pw_aff A, isl::pw_aff B) { return A.sub(B); }
+
+inline isl::pw_aff operator-(isl::val V, isl::pw_aff A) {
+  isl::pw_aff AV(A.domain(), V);
+  return AV - A;
+}
+
+inline isl::pw_aff operator-(isl::pw_aff A, isl::val V) {
+  isl::pw_aff AV(A.domain(), V);
+  return A - AV;
+}
+
+inline isl::pw_aff operator-(int i, isl::pw_aff A) {
+  isl::ctx ctx = A.get_ctx();
+  return isl::val(ctx, i) - A;
+}
+
+inline isl::pw_aff operator-(isl::pw_aff A, int i) {
+  isl::ctx ctx = A.get_ctx();
+  return A - isl::val(ctx, i);
+}
+
+inline isl::pw_aff operator/(isl::pw_aff A, isl::pw_aff B) {
+  return A.tdiv_q(B);
+}
+
+inline isl::pw_aff operator/(isl::val V, isl::pw_aff A) {
+  isl::pw_aff AV(A.domain(), V);
+  return AV / A;
+}
+
+inline isl::pw_aff operator/(isl::pw_aff A, isl::val V) {
+  isl::pw_aff AV(A.domain(), V);
+  return A / AV;
+}
+
+inline isl::pw_aff operator/(int i, isl::pw_aff A) {
+  isl::ctx ctx = A.get_ctx();
+  return isl::val(ctx, i) / A;
+}
+
+inline isl::pw_aff operator/(isl::pw_aff A, int i) {
+  isl::ctx ctx = A.get_ctx();
+  return A / isl::val(ctx, i);
+}
+
+inline isl::pw_aff operator%(isl::pw_aff A, isl::pw_aff B) {
+  return A.tdiv_r(B);
+}
+
+inline isl::pw_aff operator%(isl::val V, isl::pw_aff A) {
+  isl::pw_aff AV(A.domain(), V);
+  return AV % A;
+}
+
+inline isl::pw_aff operator%(isl::pw_aff A, isl::val V) {
+  isl::pw_aff AV(A.domain(), V);
+  return A % AV;
+}
+
+inline isl::pw_aff operator%(int i, isl::pw_aff A) {
+  isl::ctx ctx = A.get_ctx();
+  return isl::val(ctx, i) % A;
+}
+
+inline isl::pw_aff operator%(isl::pw_aff A, int i) {
+  isl::ctx ctx = A.get_ctx();
+  return A % isl::val(ctx, i);
+}
+
+} // namespace polly
diff --git a/lib/Support/SCEVAffinator.cpp b/lib/Support/SCEVAffinator.cpp
index 14603e1..02f13c1 100644
--- a/lib/Support/SCEVAffinator.cpp
+++ b/lib/Support/SCEVAffinator.cpp
@@ -15,6 +15,7 @@
 #include "polly/Options.h"
 #include "polly/ScopInfo.h"
 #include "polly/Support/GICHelper.h"
+#include "polly/Support/ISLOperators.h"
 #include "polly/Support/SCEVValidator.h"
 #include "polly/Support/ScopHelper.h"
 #include "isl/aff.h"
@@ -162,7 +163,8 @@
   isl::set Domain = PWA.domain();
   isl::pw_aff AddPW =
       isl::manage(getWidthExpValOnDomain(Width - 1, Domain.take()));
-  return PWA.add(AddPW).mod(ModVal).sub(AddPW);
+
+  return ((PWA + AddPW) % ModVal) - AddPW;
 }
 
 bool SCEVAffinator::hasNSWAddRecForLoop(Loop *L) const {
diff --git a/unittests/Isl/IslTest.cpp b/unittests/Isl/IslTest.cpp
index b1e6fc8..acafe35 100644
--- a/unittests/Isl/IslTest.cpp
+++ b/unittests/Isl/IslTest.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "polly/Support/GICHelper.h"
+#include "polly/Support/ISLOperators.h"
 #include "polly/Support/ISLTools.h"
 #include "gtest/gtest.h"
 #include "isl/stream.h"
@@ -74,6 +75,10 @@
 static bool operator==(const isl::val &LHS, const isl::val &RHS) {
   return bool(LHS.eq(RHS));
 }
+
+static bool operator==(const isl::pw_aff &LHS, const isl::pw_aff &RHS) {
+  return bool(LHS.is_equal(RHS));
+}
 } // namespace noexceptions
 } // namespace isl
 
@@ -281,6 +286,70 @@
   isl_ctx_free(IslCtx);
 }
 
+TEST(Isl, Operators) {
+  isl_ctx *IslCtx = isl_ctx_alloc();
+
+  isl::val ValOne = isl::val(IslCtx, 1);
+  isl::val ValTwo = isl::val(IslCtx, 2);
+  isl::val ValThree = isl::val(IslCtx, 3);
+  isl::val ValFour = isl::val(IslCtx, 4);
+
+  isl::space Space = isl::space(IslCtx, 0, 0);
+  isl::local_space LS = isl::local_space(Space);
+
+  isl::pw_aff AffOne = isl::aff(LS, ValOne);
+  isl::pw_aff AffTwo = isl::aff(LS, ValTwo);
+  isl::pw_aff AffThree = isl::aff(LS, ValThree);
+  isl::pw_aff AffFour = isl::aff(LS, ValFour);
+
+  // Addition
+  {
+    EXPECT_EQ(AffOne + AffOne, AffTwo);
+    EXPECT_EQ(AffOne + 1, AffTwo);
+    EXPECT_EQ(1 + AffOne, AffTwo);
+    EXPECT_EQ(AffOne + ValOne, AffTwo);
+    EXPECT_EQ(ValOne + AffOne, AffTwo);
+  }
+
+  // Multiplication
+  {
+    EXPECT_EQ(AffTwo * AffTwo, AffFour);
+    EXPECT_EQ(AffTwo * 2, AffFour);
+    EXPECT_EQ(2 * AffTwo, AffFour);
+    EXPECT_EQ(AffTwo * ValTwo, AffFour);
+    EXPECT_EQ(ValTwo * AffTwo, AffFour);
+  }
+
+  // Subtraction
+  {
+    EXPECT_EQ(AffTwo - AffOne, AffOne);
+    EXPECT_EQ(AffTwo - 1, AffOne);
+    EXPECT_EQ(2 - AffOne, AffOne);
+    EXPECT_EQ(AffTwo - ValOne, AffOne);
+    EXPECT_EQ(ValTwo - AffOne, AffOne);
+  }
+
+  // Division
+  {
+    EXPECT_EQ(AffFour - AffTwo, AffTwo);
+    EXPECT_EQ(AffFour - 2, AffTwo);
+    EXPECT_EQ(4 - AffTwo, AffTwo);
+    EXPECT_EQ(AffFour / ValTwo, AffTwo);
+    EXPECT_EQ(AffFour / 2, AffTwo);
+  }
+
+  // Remainder
+  {
+    EXPECT_EQ(AffThree % AffTwo, AffOne);
+    EXPECT_EQ(AffThree % 2, AffOne);
+    EXPECT_EQ(3 % AffTwo, AffOne);
+    EXPECT_EQ(AffThree % ValTwo, AffOne);
+    EXPECT_EQ(ValThree % AffTwo, AffOne);
+  }
+
+  isl_ctx_free(IslCtx);
+}
+
 TEST(Isl, Foreach) {
   std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
                                                         &isl_ctx_free);