[polly] r271898 - Refactor division generation code

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 6 07:56:18 PDT 2016


Author: jdoerfert
Date: Mon Jun  6 09:56:17 2016
New Revision: 271898

URL: http://llvm.org/viewvc/llvm-project?rev=271898&view=rev
Log:
Refactor division generation code

  This patch refactors the code generation for divisions. This allows to
  always generate a shift for a power-of-two division and to utilize
  information about constant divisors in order to truncate the result
  type.


Modified:
    polly/trunk/include/polly/CodeGen/IslExprBuilder.h
    polly/trunk/lib/CodeGen/IslExprBuilder.cpp
    polly/trunk/test/Isl/CodeGen/exprModDiv.ll
    polly/trunk/test/Isl/CodeGen/invariant_load_escaping_second_scop.ll

Modified: polly/trunk/include/polly/CodeGen/IslExprBuilder.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/CodeGen/IslExprBuilder.h?rev=271898&r1=271897&r2=271898&view=diff
==============================================================================
--- polly/trunk/include/polly/CodeGen/IslExprBuilder.h (original)
+++ polly/trunk/include/polly/CodeGen/IslExprBuilder.h Mon Jun  6 09:56:17 2016
@@ -204,6 +204,9 @@ private:
   llvm::Value *createOpAddressOf(__isl_take isl_ast_expr *Expr);
   llvm::Value *createAccessAddress(__isl_take isl_ast_expr *Expr);
 
+  /// @brief Supported kinds of division.
+  enum DivisionMode { DM_SIGNED, DM_UNSIGNED, DM_FLOORED };
+
   /// @brief Create a binary operation @p Opc and track overflows if requested.
   ///
   /// @param OpC  The binary operation that should be performed [Add/Sub/Mul].
@@ -216,6 +219,15 @@ private:
                            llvm::Value *LHS, llvm::Value *RHS,
                            const llvm::Twine &Name);
 
+  /// @brief Create a division and adjust the result type if possible.
+  ///
+  /// @param LHS The left operand.
+  /// @param RHS The right operand.
+  /// @param DM  The requested division mode.
+  ///
+  /// @return A value that represents the result of the division.
+  llvm::Value *createDiv(llvm::Value *LHS, llvm::Value *RHS, DivisionMode DM);
+
   /// @brief Create an addition and track overflows if requested.
   ///
   /// @param LHS  The left operand.

Modified: polly/trunk/lib/CodeGen/IslExprBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/IslExprBuilder.cpp?rev=271898&r1=271897&r2=271898&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/IslExprBuilder.cpp (original)
+++ polly/trunk/lib/CodeGen/IslExprBuilder.cpp Mon Jun  6 09:56:17 2016
@@ -318,6 +318,48 @@ Value *IslExprBuilder::createOpAccess(is
   return Builder.CreateLoad(Addr, Addr->getName() + ".load");
 }
 
+Value *IslExprBuilder::createDiv(Value *LHS, Value *RHS, DivisionMode DM) {
+  auto *ConstRHS = dyn_cast<ConstantInt>(RHS);
+  unsigned UnusedBits = 0;
+  Value *Res = nullptr;
+
+  if (ConstRHS)
+    UnusedBits = ConstRHS->getValue().logBase2();
+
+  if (ConstRHS && ConstRHS->getValue().isPowerOf2() &&
+      ConstRHS->getValue().isNonNegative())
+    Res = Builder.CreateAShr(LHS, UnusedBits, "polly.div.shr");
+  else if (DM == DM_SIGNED)
+    Res = Builder.CreateSDiv(LHS, RHS, "pexp.div", true);
+  else if (DM == DM_UNSIGNED)
+    Res = Builder.CreateUDiv(LHS, RHS, "pexp.p_div_q");
+  else {
+    assert(DM == DM_FLOORED);
+    // TODO: Review code and check that this calculation does not yield
+    //       incorrect overflow in some bordercases.
+    //
+    // floord(n,d) ((n < 0) ? (n - d + 1) : n) / d
+    Value *Sum1 = createSub(LHS, RHS, "pexp.fdiv_q.0");
+    Value *One = ConstantInt::get(Sum1->getType(), 1);
+    Value *Sum2 = createAdd(Sum1, One, "pexp.fdiv_q.1");
+    Value *Zero = ConstantInt::get(LHS->getType(), 0);
+    Value *isNegative = Builder.CreateICmpSLT(LHS, Zero, "pexp.fdiv_q.2");
+    unifyTypes(LHS, Sum2);
+    Value *Dividend =
+        Builder.CreateSelect(isNegative, Sum2, LHS, "pexp.fdiv_q.3");
+    unifyTypes(Dividend, RHS);
+    Res = Builder.CreateSDiv(Dividend, RHS, "pexp.fdiv_q.4");
+  }
+
+  if (UnusedBits) {
+    auto RequiredBits = Res->getType()->getPrimitiveSizeInBits() - UnusedBits;
+    Res = Builder.CreateTrunc(Res, Builder.getIntNTy(RequiredBits),
+                              "polly.div.trunc");
+  }
+
+  return Res;
+}
+
 Value *IslExprBuilder::createOpBin(__isl_take isl_ast_expr *Expr) {
   Value *LHS, *RHS, *Res;
   isl_ast_op_type OpType;
@@ -364,39 +406,17 @@ Value *IslExprBuilder::createOpBin(__isl
     Res = createMul(LHS, RHS);
     break;
   case isl_ast_op_div:
-    Res = Builder.CreateSDiv(LHS, RHS, "pexp.div", true);
+    Res = createDiv(LHS, RHS, DM_SIGNED);
     break;
   case isl_ast_op_pdiv_q: // Dividend is non-negative
-    Res = Builder.CreateUDiv(LHS, RHS, "pexp.p_div_q");
+    Res = createDiv(LHS, RHS, DM_UNSIGNED);
     break;
-  case isl_ast_op_fdiv_q: { // Round towards -infty
-    if (auto *Const = dyn_cast<ConstantInt>(RHS)) {
-      auto &Val = Const->getValue();
-      if (Val.isPowerOf2() && Val.isNonNegative()) {
-        Res = Builder.CreateAShr(LHS, Val.ceilLogBase2(), "polly.fdiv_q.shr");
-        break;
-      }
-    }
-    // TODO: Review code and check that this calculation does not yield
-    //       incorrect overflow in some bordercases.
-    //
-    // floord(n,d) ((n < 0) ? (n - d + 1) : n) / d
-    Value *Sum1 = createSub(LHS, RHS, "pexp.fdiv_q.0");
-    Value *One = ConstantInt::get(Sum1->getType(), 1);
-    Value *Sum2 = createAdd(Sum1, One, "pexp.fdiv_q.1");
-    Value *Zero = ConstantInt::get(LHS->getType(), 0);
-    Value *isNegative = Builder.CreateICmpSLT(LHS, Zero, "pexp.fdiv_q.2");
-    unifyTypes(LHS, Sum2);
-    Value *Dividend =
-        Builder.CreateSelect(isNegative, Sum2, LHS, "pexp.fdiv_q.3");
-    unifyTypes(Dividend, RHS);
-    Res = Builder.CreateSDiv(Dividend, RHS, "pexp.fdiv_q.4");
+  case isl_ast_op_fdiv_q: // Round towards -infty
+    Res = createDiv(LHS, RHS, DM_FLOORED);
     break;
-  }
   case isl_ast_op_pdiv_r: // Dividend is non-negative
     Res = Builder.CreateURem(LHS, RHS, "pexp.pdiv_r");
     break;
-
   case isl_ast_op_zdiv_r: // Result only compared against zero
     Res = Builder.CreateSRem(LHS, RHS, "pexp.zdiv_r");
     break;

Modified: polly/trunk/test/Isl/CodeGen/exprModDiv.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/exprModDiv.ll?rev=271898&r1=271897&r2=271898&view=diff
==============================================================================
--- polly/trunk/test/Isl/CodeGen/exprModDiv.ll (original)
+++ polly/trunk/test/Isl/CodeGen/exprModDiv.ll Mon Jun  6 09:56:17 2016
@@ -28,7 +28,8 @@
 ;       each value of i to indeed be mapped to a value.
 ;
 ; CHECK:  %pexp.p_div_q = udiv i64 %polly.indvar, 127
-; CHECK:  %polly.access.B{{[0-9]*}} = getelementptr float, float* %B, i64 %pexp.p_div_q
+; CHECK:  %polly.div.trunc = trunc i64 %pexp.p_div_q to i58
+; CHECK:  %polly.access.B{{[0-9]*}} = getelementptr float, float* %B, i58 %polly.div.trunc
 
 ; #define floord(n,d) ((n < 0) ? (n - d + 1) : n) / d
 ; A[p + 127 * floord(-p - 1, 127) + 127]
@@ -37,32 +38,39 @@
 ; CHECK:  %pexp.fdiv_q.2 = icmp slt i64 %p, 0
 ; CHECK:  %pexp.fdiv_q.3 = select i1 %pexp.fdiv_q.2, i64 %pexp.fdiv_q.1, i64 %p
 ; CHECK:  %pexp.fdiv_q.4 = sdiv i64 %pexp.fdiv_q.3, 127
-; CHECK:  %[[r1:[0-9]*]] = mul nsw i64 127, %pexp.fdiv_q.4
+; CHECK:  %polly.div.trunc1 = trunc i64 %pexp.fdiv_q.4 to i58
+; CHECK:  %[[r0:[0-9]*]] = sext i58 %polly.div.trunc1 to i64
+; CHECK:  %[[r1:[0-9]*]] = mul nsw i64 127, %[[r0]]
 ; CHECK:  %[[r2:[0-9]*]] = sub nsw i64 %p, %[[r1]]
 ; CHECK:  %polly.access.A{{[0-9]*}} = getelementptr float, float* %A, i64 %[[r2]]
 
 ; A[p / 127]
 ; CHECK:  %pexp.div = sdiv exact i64 %p, 127
-; CHECK:  %polly.access.B{{[0-9]*}} = getelementptr float, float* %B, i64 %pexp.div
+; CHECK:  %polly.div.trunc3 = trunc i64 %pexp.div to i58
+; CHECK:  %polly.access.B{{[0-9]*}} = getelementptr float, float* %B, i58 %polly.div.trunc3
 
 ; A[i % 128]
 ; POW2:  %pexp.pdiv_r = urem i64 %polly.indvar, 128
 ; POW2:  %polly.access.A{{[0-9]*}} = getelementptr float, float* %A, i64 %pexp.pdiv_r
 
 ; A[floor(i / 128)]
-; POW2:  %pexp.p_div_q = udiv i64 %polly.indvar, 128
-; POW2:  %polly.access.B{{[0-9]*}} = getelementptr float, float* %B, i64 %pexp.p_div_q
+; POW2:  %polly.div.shr = ashr i64 %polly.indvar, 7
+; POW2:  %polly.div.trunc = trunc i64 %polly.div.shr to i57
+; POW2:  %polly.access.B{{[0-9]*}} = getelementptr float, float* %B, i57 %polly.div.trunc
 
 ; #define floord(n,d) ((n < 0) ? (n - d + 1) : n) / d
 ; A[p + 128 * floord(-p - 1, 128) + 128]
-; POW2:  %polly.fdiv_q.shr = ashr i64 %p, 7
-; POW2:  %[[r1:[0-9]*]] = mul nsw i64 128, %polly.fdiv_q.shr
+; POW2:  %polly.div.shr1 = ashr i64 %p, 7
+; POW2:  %polly.div.trunc2 = trunc i64 %polly.div.shr1 to i57
+; POW2:  %[[r0:[0-9]*]] = sext i57 %polly.div.trunc2 to i64
+; POW2:  %[[r1:[0-9]*]] = mul nsw i64 128, %[[r0]]
 ; POW2:  %[[r2:[0-9]*]] = sub nsw i64 %p, %[[r1]]
 ; POW2:  %polly.access.A{{[0-9]*}} = getelementptr float, float* %A, i64 %[[r2]]
 
 ; A[p / 128]
-; POW2:  %pexp.div = sdiv exact i64 %p, 128
-; POW2:  %polly.access.B{{[0-9]*}} = getelementptr float, float* %B, i64 %pexp.div
+; POW2:  %polly.div.shr4 = ashr i64 %p, 7
+; POW2:  %polly.div.trunc5 = trunc i64 %polly.div.shr4 to i57
+; POW2:  %polly.access.B{{[0-9]*}} = getelementptr float, float* %B, i57 %polly.div.trunc5
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 

Modified: polly/trunk/test/Isl/CodeGen/invariant_load_escaping_second_scop.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/invariant_load_escaping_second_scop.ll?rev=271898&r1=271897&r2=271898&view=diff
==============================================================================
--- polly/trunk/test/Isl/CodeGen/invariant_load_escaping_second_scop.ll (original)
+++ polly/trunk/test/Isl/CodeGen/invariant_load_escaping_second_scop.ll Mon Jun  6 09:56:17 2016
@@ -19,8 +19,9 @@
 ;    }
 ;
 ; CHECK: polly.stmt.stmt.P:
-; CHECK:   %polly.fdiv_q.shr = ashr i32 %tmp.merge, 1
-; CHECL:   sext i32 %polly.fdiv_q.shr to i33
+; CHECK:   %polly.div.shr = ashr i32 %tmp.merge, 1
+; CHECK:   %polly.div.trunc = trunc i32 %polly.div.shr to i31
+; CHECK:   sext i31 %polly.div.trunc to i32
 ;
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 




More information about the llvm-commits mailing list