[polly] r297466 - [DeadCodeElimination] Translate to C++ bindings

Tobias Grosser via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 10 07:05:38 PST 2017


Author: grosser
Date: Fri Mar 10 09:05:38 2017
New Revision: 297466

URL: http://llvm.org/viewvc/llvm-project?rev=297466&view=rev
Log:
[DeadCodeElimination] Translate to C++ bindings

This pass is a small and self-contained example of a piece of code that was
written with the isl C interface. The diff of this change nicely shows how the
C++ bindings can improve the readability of the code by avoiding the long C
function names and by avoiding any need for memory management.

As you will see, no calls to isl_*_copy or isl_*_free are needed anymore.
Instead the C++ interface takes care of automatically managing the objects.
This may introduce internally additional copies, but due to the isl reference
counting, such copies are expected to be cheap. For performance critical
operations, we will later exploit move semantics to eliminate unnecessary
copies that have shown to be costly.

Below we give a set of examples that shows the benefit of the C++ interface vs.
the pure C interface.

Check properties
----------------

Before:

  if (isl_aff_is_zero(aff) ||  isl_aff_is_one(aff))
    return true;

After:

  if (Aff.is_zero() || Aff.is_one())
    return true;

Type conversion
---------------

Before:

  isl_union_pw_multi_aff *UPMA = isl_union_pw_multi_aff_from_union_map(umap);

After:

  isl::union_pw_multi_aff UPMA = UMap;

Type construction
-----------------

Before:

  auto *Empty = isl_union_map_empty(space);

After:

  auto Empty = isl::union_map::empty(Space);

Operations
----------

Before:

  set = isl_union_set_intersect(set, set2);

After:

  Set = Set.intersect(Set2);

The use of isl::boolean in return types also adds an increases the robustness
of Polly, as on conversion to true or false, we verify that no isl_bool_error
has been returned and assert in case an error was returned. Before this change
we would have just ignored the error and proceeded with (some) exection path.

Tags: #polly

Reviewed By: Meinersbur

Differential Revision: https://reviews.llvm.org/D30619

Modified:
    polly/trunk/include/polly/Support/GICHelper.h
    polly/trunk/lib/Transform/DeadCodeElimination.cpp

Modified: polly/trunk/include/polly/Support/GICHelper.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/GICHelper.h?rev=297466&r1=297465&r2=297466&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/GICHelper.h (original)
+++ polly/trunk/include/polly/Support/GICHelper.h Fri Mar 10 09:05:38 2017
@@ -70,6 +70,36 @@ namespace polly {
 /// @return The isl_val corresponding to @p Int.
 __isl_give isl_val *isl_valFromAPInt(isl_ctx *Ctx, const llvm::APInt Int,
                                      bool IsSigned);
+
+/// Translate an llvm::APInt to an isl::val.
+///
+/// Translate the bitsequence without sign information as provided by APInt into
+/// a signed isl::val type. Depending on the value of @p IsSigned @p Int is
+/// interpreted as unsigned value or as signed value in two's complement
+/// representation.
+///
+/// Input IsSigned                 Output
+///
+///     0        0           ->    0
+///     1        0           ->    1
+///    00        0           ->    0
+///    01        0           ->    1
+///    10        0           ->    2
+///    11        0           ->    3
+///
+///     0        1           ->    0
+///     1        1           ->   -1
+///    00        1           ->    0
+///    01        1           ->    1
+///    10        1           ->   -2
+///    11        1           ->   -1
+///
+/// @param Ctx      The isl_ctx to create the isl::val in.
+/// @param Int      The integer value to translate.
+/// @param IsSigned If the APInt should be interpreted as signed or unsigned
+///                 value.
+///
+/// @return The isl::val corresponding to @p Int.
 inline isl::val valFromAPInt(isl_ctx *Ctx, const llvm::APInt Int,
                              bool IsSigned) {
   return isl::manage(isl_valFromAPInt(Ctx, Int, IsSigned));
@@ -103,6 +133,34 @@ inline isl::val valFromAPInt(isl_ctx *Ct
 ///
 /// @return The APInt value corresponding to @p Val.
 llvm::APInt APIntFromVal(__isl_take isl_val *Val);
+
+/// Translate isl::val to llvm::APInt.
+///
+/// This function can only be called on isl::val values which are integers.
+/// Calling this function with a non-integral rational, NaN or infinity value
+/// is not allowed.
+///
+/// As the input isl::val may be negative, the APInt that this function returns
+/// must always be interpreted as signed two's complement value. The bitwidth of
+/// the generated APInt is always the minimal bitwidth necessary to model the
+/// provided integer when interpreting the bitpattern as signed value.
+///
+/// Some example conversions are:
+///
+///   Input      Bits    Signed  Bitwidth
+///       0 ->      0         0         1
+///      -1 ->      1        -1         1
+///       1 ->     01         1         2
+///      -2 ->     10        -2         2
+///       2 ->    010         2         3
+///      -3 ->    101        -3         3
+///       3 ->    011         3         3
+///      -4 ->    100        -4         3
+///       4 ->   0100         4         4
+///
+/// @param Val The isl val to translate.
+///
+/// @return The APInt value corresponding to @p Val.
 inline llvm::APInt APIntFromVal(isl::val V) {
   return APIntFromVal(V.release());
 }

Modified: polly/trunk/lib/Transform/DeadCodeElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Transform/DeadCodeElimination.cpp?rev=297466&r1=297465&r2=297466&view=diff
==============================================================================
--- polly/trunk/lib/Transform/DeadCodeElimination.cpp (original)
+++ polly/trunk/lib/Transform/DeadCodeElimination.cpp Fri Mar 10 09:05:38 2017
@@ -43,6 +43,8 @@
 #include "isl/union_map.h"
 #include "isl/union_set.h"
 
+#include "isl-noexceptions.h"
+
 using namespace llvm;
 using namespace polly;
 
@@ -74,7 +76,7 @@ private:
   /// overwrite the same memory location and is consequently the only one that
   /// is visible after the execution of the SCoP.
   ///
-  isl_union_set *getLiveOut(Scop &S);
+  isl::union_set getLiveOut(Scop &S);
   bool eliminateDeadCode(Scop &S, int PreciseSteps);
 };
 } // namespace
@@ -91,21 +93,20 @@ char DeadCodeElim::ID = 0;
 // bounded write accesses can not overwrite all of the data-locations. As
 // this means may-writes are in the current situation always live, there is
 // no point in trying to remove them from the live-out set.
-__isl_give isl_union_set *DeadCodeElim::getLiveOut(Scop &S) {
-  isl_union_map *Schedule = S.getSchedule();
-  assert(Schedule &&
-         "Schedules that contain extension nodes require special handling.");
-  isl_union_map *WriteIterations = isl_union_map_reverse(S.getMustWrites());
-  isl_union_map *WriteTimes =
-      isl_union_map_apply_range(WriteIterations, isl_union_map_copy(Schedule));
-
-  isl_union_map *LastWriteTimes = isl_union_map_lexmax(WriteTimes);
-  isl_union_map *LastWriteIterations = isl_union_map_apply_range(
-      LastWriteTimes, isl_union_map_reverse(Schedule));
-
-  isl_union_set *Live = isl_union_map_range(LastWriteIterations);
-  Live = isl_union_set_union(Live, isl_union_map_domain(S.getMayWrites()));
-  return isl_union_set_coalesce(Live);
+isl::union_set DeadCodeElim::getLiveOut(Scop &S) {
+  isl::union_map Schedule = isl::manage(S.getSchedule());
+  isl::union_map MustWrites = isl::manage(S.getMustWrites());
+  isl::union_map WriteIterations = MustWrites.reverse();
+  isl::union_map WriteTimes = WriteIterations.apply_range(Schedule);
+
+  isl::union_map LastWriteTimes = WriteTimes.lexmax();
+  isl::union_map LastWriteIterations =
+      LastWriteTimes.apply_range(Schedule.reverse());
+
+  isl::union_set Live = LastWriteIterations.range();
+  isl::union_map MayWrites = isl::manage(S.getMayWrites());
+  Live = Live.unite(MayWrites.domain());
+  return Live.coalesce();
 }
 
 /// Performs polyhedral dead iteration elimination by:
@@ -123,41 +124,37 @@ bool DeadCodeElim::eliminateDeadCode(Sco
   if (!D.hasValidDependences())
     return false;
 
-  isl_union_set *Live = getLiveOut(S);
-  isl_union_map *Dep =
-      D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED);
-  Dep = isl_union_map_reverse(Dep);
+  isl::union_set Live = getLiveOut(S);
+  isl::union_map Dep = isl::manage(
+      D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED));
+  Dep = Dep.reverse();
 
   if (PreciseSteps == -1)
-    Live = isl_union_set_affine_hull(Live);
+    Live = Live.affine_hull();
 
-  isl_union_set *OriginalDomain = S.getDomains();
+  isl::union_set OriginalDomain = isl::manage(S.getDomains());
   int Steps = 0;
   while (true) {
-    isl_union_set *Extra;
     Steps++;
 
-    Extra =
-        isl_union_set_apply(isl_union_set_copy(Live), isl_union_map_copy(Dep));
+    isl::union_set Extra = Live.apply(Dep);
 
-    if (isl_union_set_is_subset(Extra, Live)) {
-      isl_union_set_free(Extra);
+    if (Extra.is_subset(Live))
       break;
-    }
 
-    Live = isl_union_set_union(Live, Extra);
+    Live = Live.unite(Extra);
 
     if (Steps > PreciseSteps) {
       Steps = 0;
-      Live = isl_union_set_affine_hull(Live);
+      Live = Live.affine_hull();
     }
 
-    Live = isl_union_set_intersect(Live, isl_union_set_copy(OriginalDomain));
+    Live = Live.intersect(OriginalDomain);
   }
-  isl_union_map_free(Dep);
-  isl_union_set_free(OriginalDomain);
 
-  bool Changed = S.restrictDomains(isl_union_set_coalesce(Live));
+  Live = Live.coalesce();
+
+  bool Changed = S.restrictDomains(Live.copy());
 
   // FIXME: We can probably avoid the recomputation of all dependences by
   // updating them explicitly.




More information about the llvm-commits mailing list