[polly] r247893 - Extract function that derives the index expressions of a GEP instruction [NFC]

Tobias Grosser via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 17 08:47:52 PDT 2015


Author: grosser
Date: Thu Sep 17 10:47:52 2015
New Revision: 247893

URL: http://llvm.org/viewvc/llvm-project?rev=247893&view=rev
Log:
Extract function that derives the index expressions of a GEP instruction [NFC]

We currently use this functionality to add run-time assumptions that check its
in-bound property.

Modified:
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/lib/Analysis/ScopInfo.cpp

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=247893&r1=247892&r2=247893&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Thu Sep 17 10:47:52 2015
@@ -679,6 +679,21 @@ private:
                                 llvm::SmallVectorImpl<MemoryAccess *> &Loads);
   //@}
 
+  /// @brief Derive the individual index expressions from a GEP instruction
+  ///
+  /// This function optimistically assumes the GEP references into a fixed size
+  /// array. If this is actually true, this function returns a list of array
+  /// subscript expressions as SCEV as well as a list of integers describing
+  /// the size of the individual array dimensions. Both lists have either equal
+  /// length of the size list is one element shorter in case there is no known
+  /// size available for the outermost array dimension.
+  ///
+  /// @param GEP The GetElementPtr instruction to analyze.
+  ///
+  /// @return A tuple with the subscript expressions and the dimension sizes.
+  std::tuple<std::vector<const SCEV *>, std::vector<int>>
+  getIndexExpressionsFromGEP(GetElementPtrInst *GEP);
+
   /// @brief Derive assumptions about parameter values from GetElementPtrInst
   ///
   /// In case a GEP instruction references into a fixed size array e.g., an

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=247893&r1=247892&r2=247893&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Thu Sep 17 10:47:52 2015
@@ -921,6 +921,51 @@ void ScopStmt::buildDomain() {
   Domain = isl_set_set_tuple_id(Domain, Id);
 }
 
+std::tuple<std::vector<const SCEV *>, std::vector<int>>
+ScopStmt::getIndexExpressionsFromGEP(GetElementPtrInst *GEP) {
+  ScalarEvolution &SE = *Parent.getSE();
+  std::vector<const SCEV *> Subscripts;
+  std::vector<int> Sizes;
+
+  Type *Ty = GEP->getPointerOperandType();
+
+  for (long i = 1; i < GEP->getNumOperands(); i++) {
+
+    const SCEV *Expr = SE.getSCEV(GEP->getOperand(i));
+
+    if (i == 1) {
+      if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
+        Ty = PtrTy->getElementType();
+      } else if (auto ArrayTy = dyn_cast<ArrayType>(Ty)) {
+        Ty = ArrayTy->getElementType();
+      } else {
+        Subscripts.clear();
+        Sizes.clear();
+        break;
+      }
+      if (auto Const = dyn_cast<SCEVConstant>(Expr))
+        if (Const->getValue()->isZero())
+          continue;
+      Subscripts.push_back(Expr);
+      continue;
+    }
+
+    auto ArrayTy = dyn_cast<ArrayType>(Ty);
+    if (!ArrayTy) {
+      Subscripts.clear();
+      Sizes.clear();
+      break;
+    }
+
+    Subscripts.push_back(Expr);
+    Sizes.push_back(ArrayTy->getNumElements());
+
+    Ty = ArrayTy->getElementType();
+  }
+
+  return std::make_tuple(Subscripts, Sizes);
+}
+
 void ScopStmt::deriveAssumptionsFromGEP(GetElementPtrInst *GEP) {
   int Dimension = 0;
   isl_ctx *Ctx = Parent.getIslCtx();
@@ -928,43 +973,45 @@ void ScopStmt::deriveAssumptionsFromGEP(
   Type *Ty = GEP->getPointerOperandType();
   ScalarEvolution &SE = *Parent.getSE();
 
+  std::vector<const SCEV *> Subscripts;
+  std::vector<int> Sizes;
+
+  std::tie(Subscripts, Sizes) = getIndexExpressionsFromGEP(GEP);
+
   if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
     Dimension = 1;
     Ty = PtrTy->getElementType();
   }
 
-  while (auto ArrayTy = dyn_cast<ArrayType>(Ty)) {
-    unsigned int Operand = 1 + Dimension;
+  int IndexOffset = Subscripts.size() - Sizes.size();
 
-    if (GEP->getNumOperands() <= Operand)
-      break;
+  assert(IndexOffset <= 1 && "Unexpected large index offset");
 
-    const SCEV *Expr = SE.getSCEV(GEP->getOperand(Operand));
+  for (size_t i = 0; i < Sizes.size(); i++) {
+    auto Expr = Subscripts[i + IndexOffset];
+    auto Size = Sizes[i];
 
-    if (isAffineExpr(&Parent.getRegion(), Expr, SE)) {
-      isl_pw_aff *AccessOffset = getPwAff(Expr);
-      AccessOffset =
-          isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId());
-
-      isl_pw_aff *DimSize = isl_pw_aff_from_aff(isl_aff_val_on_domain(
-          isl_local_space_copy(LSpace),
-          isl_val_int_from_si(Ctx, ArrayTy->getNumElements())));
-
-      isl_set *OutOfBound = isl_pw_aff_ge_set(AccessOffset, DimSize);
-      OutOfBound = isl_set_intersect(getDomain(), OutOfBound);
-      OutOfBound = isl_set_params(OutOfBound);
-      isl_set *InBound = isl_set_complement(OutOfBound);
-      isl_set *Executed = isl_set_params(getDomain());
-
-      // A => B == !A or B
-      isl_set *InBoundIfExecuted =
-          isl_set_union(isl_set_complement(Executed), InBound);
+    if (!isAffineExpr(&Parent.getRegion(), Expr, SE))
+      continue;
 
-      Parent.addAssumption(InBoundIfExecuted);
-    }
+    isl_pw_aff *AccessOffset = getPwAff(Expr);
+    AccessOffset =
+        isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId());
 
-    Dimension += 1;
-    Ty = ArrayTy->getElementType();
+    isl_pw_aff *DimSize = isl_pw_aff_from_aff(isl_aff_val_on_domain(
+        isl_local_space_copy(LSpace), isl_val_int_from_si(Ctx, Size)));
+
+    isl_set *OutOfBound = isl_pw_aff_ge_set(AccessOffset, DimSize);
+    OutOfBound = isl_set_intersect(getDomain(), OutOfBound);
+    OutOfBound = isl_set_params(OutOfBound);
+    isl_set *InBound = isl_set_complement(OutOfBound);
+    isl_set *Executed = isl_set_params(getDomain());
+
+    // A => B == !A or B
+    isl_set *InBoundIfExecuted =
+        isl_set_union(isl_set_complement(Executed), InBound);
+
+    Parent.addAssumption(InBoundIfExecuted);
   }
 
   isl_local_space_free(LSpace);




More information about the llvm-commits mailing list