[polly] r270412 - [FIX] Require base pointers of loads that might alias to be hoisted

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Mon May 23 02:26:49 PDT 2016


Author: jdoerfert
Date: Mon May 23 04:26:46 2016
New Revision: 270412

URL: http://llvm.org/viewvc/llvm-project?rev=270412&view=rev
Log:
[FIX] Require base pointers of loads that might alias to be hoisted

  Since the base pointer of a possibly aliasing pointer might not alias
  with any other pointer it (the base pointer) might not be tagged as
  "required invariant". However, we need it do be in order to compare
  the accessed addresses of the derived (possibly aliasing) pointer.

  This patch also tries to clean up the load hoisting a little bit.


Added:
    polly/trunk/test/Isl/CodeGen/non-hoisted-load-needed-as-base-ptr.ll
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=270412&r1=270411&r2=270412&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Mon May 23 04:26:46 2016
@@ -1606,6 +1606,13 @@ private:
   /// @brief Simplify the SCoP representation
   void simplifySCoP(bool AfterHoisting, DominatorTree &DT, LoopInfo &LI);
 
+  /// @brief Return the access for the base ptr of @p MA if any.
+  MemoryAccess *lookupBasePtrAccess(MemoryAccess *MA);
+
+  /// @brief Check if the base ptr of @p MA is in the SCoP but not hoistable.
+  bool hasNonHoistableBasePtrInScop(MemoryAccess *MA,
+                                    __isl_keep isl_union_map *Writes);
+
   /// @brief Create equivalence classes for required invariant accesses.
   ///
   /// These classes will consolidate multiple required invariant loads from the
@@ -2036,10 +2043,16 @@ public:
   const InvariantLoadsSetTy &getRequiredInvariantLoads() const {
     return DC.RequiredILS;
   }
+
+  /// @brief Add @p LI to the set of required invariant loads.
+  void addRequiredInvariantLoad(LoadInst *LI) { DC.RequiredILS.insert(LI); }
+
   const BoxedLoopsSetTy &getBoxedLoops() const { return DC.BoxedLoopsSet; }
+
   bool isNonAffineSubRegion(const Region *R) {
     return DC.NonAffineSubRegionSet.count(R);
   }
+
   const MapInsnToMemAcc &getInsnToMemAccMap() const { return DC.InsnToMemAcc; }
 
   /// @brief Return the (possibly new) ScopArrayInfo object for @p Access.

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=270412&r1=270411&r2=270412&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Mon May 23 04:26:46 2016
@@ -2836,6 +2836,37 @@ bool Scop::addLoopBoundsToHeaderDomain(L
   return true;
 }
 
+MemoryAccess *Scop::lookupBasePtrAccess(MemoryAccess *MA) {
+  auto *BaseAddr = SE->getSCEV(MA->getBaseAddr());
+  auto *PointerBase = dyn_cast<SCEVUnknown>(SE->getPointerBase(BaseAddr));
+  if (!PointerBase)
+    return nullptr;
+
+  auto *PointerBaseInst = dyn_cast<Instruction>(PointerBase->getValue());
+  if (!PointerBaseInst)
+    return nullptr;
+
+  auto *BasePtrStmt = getStmtFor(PointerBaseInst);
+  if (!BasePtrStmt)
+    return nullptr;
+
+  return BasePtrStmt->getArrayAccessOrNULLFor(PointerBaseInst);
+}
+
+bool Scop::hasNonHoistableBasePtrInScop(MemoryAccess *MA,
+                                        __isl_keep isl_union_map *Writes) {
+  if (auto *BasePtrMA = lookupBasePtrAccess(MA))
+    return !isHoistableAccess(BasePtrMA, Writes);
+
+  auto *BaseAddr = SE->getSCEV(MA->getBaseAddr());
+  auto *PointerBase = dyn_cast<SCEVUnknown>(SE->getPointerBase(BaseAddr));
+  if (auto *BasePtrInst = dyn_cast<Instruction>(PointerBase->getValue()))
+    if (!isa<LoadInst>(BasePtrInst))
+      return R.contains(BasePtrInst);
+
+  return false;
+}
+
 void Scop::buildAliasChecks(AliasAnalysis &AA) {
   if (!PollyUseRuntimeAliasChecks)
     return;
@@ -2978,17 +3009,25 @@ bool Scop::buildAliasGroups(AliasAnalysi
 
     // Check if we have non-affine accesses left, if so bail out as we cannot
     // generate a good access range yet.
-    for (auto *MA : AG)
+    for (auto *MA : AG) {
       if (!MA->isAffine()) {
         invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc());
         return false;
       }
+      if (auto *BasePtrMA = lookupBasePtrAccess(MA))
+        addRequiredInvariantLoad(
+            cast<LoadInst>(BasePtrMA->getAccessInstruction()));
+    }
     for (auto &ReadOnlyPair : ReadOnlyPairs)
-      for (auto *MA : ReadOnlyPair.second)
+      for (auto *MA : ReadOnlyPair.second) {
         if (!MA->isAffine()) {
           invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc());
           return false;
         }
+        if (auto *BasePtrMA = lookupBasePtrAccess(MA))
+          addRequiredInvariantLoad(
+              cast<LoadInst>(BasePtrMA->getAccessInstruction()));
+      }
 
     // Calculate minimal and maximal accesses for non read only accesses.
     MinMaxAliasGroups.emplace_back();
@@ -3402,23 +3441,13 @@ bool Scop::isHoistableAccess(MemoryAcces
   // that it is invariant, thus it will be hoisted too. However, if there is
   // no base pointer origin we check that the base pointer is defined
   // outside the region.
-  const ScopArrayInfo *SAI = Access->getScopArrayInfo();
-  auto *BasePtrInst = dyn_cast<Instruction>(SAI->getBasePtr());
-  if (SAI->getBasePtrOriginSAI()) {
-    assert(BasePtrInst && R.contains(BasePtrInst));
-    if (!isa<LoadInst>(BasePtrInst))
-      return false;
-    auto *BasePtrStmt = getStmtFor(BasePtrInst);
-    assert(BasePtrStmt);
-    auto *BasePtrMA = BasePtrStmt->getArrayAccessOrNULLFor(BasePtrInst);
-    if (BasePtrMA && !isHoistableAccess(BasePtrMA, Writes))
-      return false;
-  } else if (BasePtrInst && R.contains(BasePtrInst))
+  if (hasNonHoistableBasePtrInScop(Access, Writes))
     return false;
 
   // Skip accesses in non-affine subregions as they might not be executed
   // under the same condition as the entry of the non-affine subregion.
-  if (BB != Access->getAccessInstruction()->getParent())
+  auto *LI = cast<LoadInst>(Access->getAccessInstruction());
+  if (BB != LI->getParent())
     return false;
 
   isl_map *AccessRelation = Access->getAccessRelation();
@@ -3438,10 +3467,7 @@ bool Scop::isHoistableAccess(MemoryAcces
   bool IsWritten = !isl_union_map_is_empty(Written);
   isl_union_map_free(Written);
 
-  if (IsWritten)
-    return false;
-
-  return true;
+  return !IsWritten;
 }
 
 void Scop::verifyInvariantLoads() {

Added: polly/trunk/test/Isl/CodeGen/non-hoisted-load-needed-as-base-ptr.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/non-hoisted-load-needed-as-base-ptr.ll?rev=270412&view=auto
==============================================================================
--- polly/trunk/test/Isl/CodeGen/non-hoisted-load-needed-as-base-ptr.ll (added)
+++ polly/trunk/test/Isl/CodeGen/non-hoisted-load-needed-as-base-ptr.ll Mon May 23 04:26:46 2016
@@ -0,0 +1,48 @@
+; RUN: opt %loadPolly -tbaa -polly-codegen -disable-output %s
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.1 = type { %struct.2*, %struct.2*, %struct.3*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i32, [38 x i8], [128 x i8], [38 x i32], [256 x i8], [256 x i8], [256 x i8], %struct.4, [25 x [16 x %struct.4]], [128 x [64 x i16]] }
+%struct.2 = type { i16, i16, i32, i32 }
+%struct.3 = type { i8, i8, i16, i16 }
+%struct.4 = type { i16, i8, i8 }
+
+define void @AllocUnitsRare(%struct.1* %p, i32 %indx) {
+entry:
+  br label %do.body
+
+do.body:                                          ; preds = %do.body, %entry
+  %i.0 = phi i32 [ %inc, %do.body ], [ %indx, %entry ]
+  %inc = add i32 %i.0, 1
+  br i1 undef, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.body
+  %Base.i = getelementptr inbounds %struct.1, %struct.1* %p, i32 0, i32 12
+  %tmp.i = load i8*, i8** %Base.i, align 8, !tbaa !0
+  %idxprom.i = zext i32 %inc to i64
+  %FreeList.i = getelementptr inbounds %struct.1, %struct.1* %p, i32 0, i32 20
+  %arrayidx.i = getelementptr inbounds [38 x i32], [38 x i32]* %FreeList.i, i64 0, i64 %idxprom.i
+  %tmp1.i = bitcast i8* %tmp.i to i32*
+  %tmp2.i = load i32, i32* %tmp1.i, align 4, !tbaa !8
+  store i32 %tmp2.i, i32* %arrayidx.i, align 4, !tbaa !8
+  %Indx2Units.i = getelementptr inbounds %struct.1, %struct.1* %p, i32 0, i32 18
+  %arrayidx.i1 = getelementptr inbounds [38 x i8], [38 x i8]* %Indx2Units.i, i64 0, i64 0
+  %cmp.i = icmp ne i32 0, 3
+  br i1 %cmp.i, label %if.then.i, label %SplitBlock.exit
+
+if.then.i:                                        ; preds = %do.end
+  br label %SplitBlock.exit
+
+SplitBlock.exit:                                  ; preds = %if.then.i, %do.end
+  ret void
+}
+
+!0 = !{!1, !2, i64 64}
+!1 = !{!"", !2, i64 0, !2, i64 8, !2, i64 16, !5, i64 24, !5, i64 28, !5, i64 32, !5, i64 36, !5, i64 40, !5, i64 44, !5, i64 48, !5, i64 52, !5, i64 56, !2, i64 64, !2, i64 72, !2, i64 80, !2, i64 88, !2, i64 96, !5, i64 104, !3, i64 108, !3, i64 146, !3, i64 276, !3, i64 428, !3, i64 684, !3, i64 940, !6, i64 1196, !3, i64 1200, !3, i64 2800}
+!2 = !{!"any pointer", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!"int", !3, i64 0}
+!6 = !{!"", !7, i64 0, !3, i64 2, !3, i64 3}
+!7 = !{!"short", !3, i64 0}
+!8 = !{!5, !5, i64 0}




More information about the llvm-commits mailing list