[polly] r261866 - Support calls with known ModRef function behaviour

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 25 06:08:48 PST 2016


Author: jdoerfert
Date: Thu Feb 25 08:08:48 2016
New Revision: 261866

URL: http://llvm.org/viewvc/llvm-project?rev=261866&view=rev
Log:
Support calls with known ModRef function behaviour

  Check the ModRefBehaviour of functions in order to decide whether or
  not a call instruction might be acceptable.

Differential Revision: http://reviews.llvm.org/D5227

Added:
    polly/trunk/test/ScopDetect/mod_ref_read_pointer.ll
    polly/trunk/test/ScopInfo/mod_ref_access_pointee_arguments.ll
    polly/trunk/test/ScopInfo/mod_ref_read_pointee_arguments.ll
    polly/trunk/test/ScopInfo/mod_ref_read_pointer.ll
    polly/trunk/test/ScopInfo/mod_ref_read_pointers.ll
    polly/trunk/test/ScopInfo/multidim_2d_with_modref_call.ll
    polly/trunk/test/ScopInfo/multidim_2d_with_modref_call_2.ll
    polly/trunk/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll
Modified:
    polly/trunk/include/polly/ScopDetection.h
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/include/polly/Support/ScopHelper.h
    polly/trunk/lib/Analysis/ScopDetection.cpp
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/CodeGen/IRBuilder.cpp

Modified: polly/trunk/include/polly/ScopDetection.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopDetection.h?rev=261866&r1=261865&r2=261866&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopDetection.h (original)
+++ polly/trunk/include/polly/ScopDetection.h Thu Feb 25 08:08:48 2016
@@ -156,6 +156,9 @@ public:
     /// @brief The region has at least one store instruction.
     bool hasStores;
 
+    /// @brief Flag to indicate the region has at least one unknown access.
+    bool HasUnknownAccess;
+
     /// @brief The set of non-affine subregions in the region we analyze.
     NonAffineSubRegionSetTy NonAffineSubRegionSet;
 
@@ -172,7 +175,7 @@ public:
     /// @brief Initialize a DetectionContext from scratch.
     DetectionContext(Region &R, AliasAnalysis &AA, bool Verify)
         : CurRegion(R), AST(AA), Verifying(Verify), Log(&R), hasLoads(false),
-          hasStores(false) {}
+          hasStores(false), HasUnknownAccess(false) {}
 
     /// @brief Initialize a DetectionContext with the data from @p DC.
     DetectionContext(const DetectionContext &&DC)
@@ -181,7 +184,7 @@ public:
           Accesses(std::move(DC.Accesses)),
           NonAffineAccesses(std::move(DC.NonAffineAccesses)),
           ElementSize(std::move(DC.ElementSize)), hasLoads(DC.hasLoads),
-          hasStores(DC.hasStores),
+          hasStores(DC.hasStores), HasUnknownAccess(DC.HasUnknownAccess),
           NonAffineSubRegionSet(std::move(DC.NonAffineSubRegionSet)),
           BoxedLoopsSet(std::move(DC.BoxedLoopsSet)),
           RequiredILS(std::move(DC.RequiredILS)) {

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=261866&r1=261865&r2=261866&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Thu Feb 25 08:08:48 2016
@@ -327,6 +327,9 @@ public:
   /// normal scalar array modeling.
   bool isPHIKind() const { return Kind == MK_PHI; };
 
+  /// @brief Is this array info modeling an array?
+  bool isArrayKind() const { return Kind == MK_Array; };
+
   /// @brief Dump a readable representation to stderr.
   void dump() const;
 
@@ -2052,6 +2055,12 @@ class ScopInfo : public RegionPass {
   /// @brief The ScalarEvolution to help building Scop.
   ScalarEvolution *SE;
 
+  /// @brief Set of instructions that might read any memory location.
+  SmallVector<Instruction *, 16> GlobalReads;
+
+  /// @brief Set of all accessed array base pointers.
+  SmallSetVector<Value *, 16> ArrayBasePointers;
+
   // The Scop
   std::unique_ptr<Scop> scop;
 
@@ -2106,6 +2115,19 @@ class ScopInfo : public RegionPass {
                                const ScopDetection::BoxedLoopsSetTy *BoxedLoops,
                                const InvariantLoadsSetTy &ScopRIL);
 
+  /// @brief Try to build a MemoryAccess for a call instruction.
+  ///
+  /// @param Inst       The call instruction that access the memory
+  /// @param L          The parent loop of the instruction
+  /// @param R          The region on which to build the data access dictionary.
+  /// @param BoxedLoops The set of loops that are overapproximated in @p R.
+  /// @param ScopRIL    The required invariant loads equivalence classes.
+  ///
+  /// @returns True if the access could be built, False otherwise.
+  bool buildAccessCallInst(MemAccInst Inst, Loop *L, Region *R,
+                           const ScopDetection::BoxedLoopsSetTy *BoxedLoops,
+                           const InvariantLoadsSetTy &ScopRIL);
+
   /// @brief Build a single-dimensional parameteric sized MemoryAccess
   ///        from the Load/Store instruction.
   ///

Modified: polly/trunk/include/polly/Support/ScopHelper.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/ScopHelper.h?rev=261866&r1=261865&r2=261866&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/ScopHelper.h (original)
+++ polly/trunk/include/polly/Support/ScopHelper.h Thu Feb 25 08:08:48 2016
@@ -51,10 +51,10 @@ using InvariantLoadsSetTy = llvm::SetVec
 /// referenced object and should be passed by-value as it is small enough.
 ///
 /// This proxy can either represent a LoadInst instance, a StoreInst instance,
-/// a MemIntrinsic instance (memset, memmove, memcpy) or a nullptr (only
-/// creatable using the default constructor); never an Instruction that is
-/// neither of the above mentioned. When representing a nullptr, only the
-/// following methods are defined:
+/// a MemIntrinsic instance (memset, memmove, memcpy), a CallInst instance or a
+/// nullptr (only creatable using the default constructor); never an Instruction
+/// that is neither of the above mentioned. When representing a nullptr, only
+/// the following methods are defined:
 /// isNull(), isInstruction(), isLoad(), isStore(), ..., isMemTransferInst(),
 /// operator bool(), operator!()
 ///
@@ -75,16 +75,17 @@ public:
   /* implicit */ MemAccInst(llvm::StoreInst &SI) : I(&SI) {}
   /* implicit */ MemAccInst(llvm::StoreInst *SI) : I(SI) {}
   /* implicit */ MemAccInst(llvm::MemIntrinsic *MI) : I(MI) {}
+  /* implicit */ MemAccInst(llvm::CallInst *CI) : I(CI) {}
   explicit MemAccInst(llvm::Instruction &I) : I(&I) { assert(isa(I)); }
   explicit MemAccInst(llvm::Instruction *I) : I(I) { assert(isa(I)); }
 
   static bool isa(const llvm::Value &V) {
     return llvm::isa<llvm::LoadInst>(V) || llvm::isa<llvm::StoreInst>(V) ||
-           llvm::isa<llvm::MemIntrinsic>(V);
+           llvm::isa<llvm::CallInst>(V) || llvm::isa<llvm::MemIntrinsic>(V);
   }
   static bool isa(const llvm::Value *V) {
     return llvm::isa<llvm::LoadInst>(V) || llvm::isa<llvm::StoreInst>(V) ||
-           llvm::isa<llvm::MemIntrinsic>(V);
+           llvm::isa<llvm::CallInst>(V) || llvm::isa<llvm::MemIntrinsic>(V);
   }
   static MemAccInst cast(llvm::Value &V) {
     return MemAccInst(llvm::cast<llvm::Instruction>(V));
@@ -140,6 +141,14 @@ public:
     I = MI;
     return *this;
   }
+  MemAccInst &operator=(llvm::CallInst &CI) {
+    I = &CI;
+    return *this;
+  }
+  MemAccInst &operator=(llvm::CallInst *CI) {
+    I = CI;
+    return *this;
+  }
 
   operator llvm::Instruction *() const { return asInstruction(); }
   explicit operator bool() const { return isInstruction(); }
@@ -168,6 +177,8 @@ public:
       return asStore()->getValueOperand();
     if (isMemIntrinsic())
       return nullptr;
+    if (isCallInst())
+      return nullptr;
     llvm_unreachable("Operation not supported on nullptr");
   }
   llvm::Value *getPointerOperand() const {
@@ -177,6 +188,8 @@ public:
       return asStore()->getPointerOperand();
     if (isMemIntrinsic())
       return asMemIntrinsic()->getDest();
+    if (isCallInst())
+      return nullptr;
     llvm_unreachable("Operation not supported on nullptr");
   }
 
@@ -187,6 +200,8 @@ public:
       return asStore()->getAlignment();
     if (isMemIntrinsic())
       return asMemIntrinsic()->getAlignment();
+    if (isCallInst())
+      return 0;
     llvm_unreachable("Operation not supported on nullptr");
   }
   bool isVolatile() const {
@@ -196,6 +211,8 @@ public:
       return asStore()->isVolatile();
     if (isMemIntrinsic())
       return asMemIntrinsic()->isVolatile();
+    if (isCallInst())
+      return false;
     llvm_unreachable("Operation not supported on nullptr");
   }
   bool isSimple() const {
@@ -205,6 +222,8 @@ public:
       return asStore()->isSimple();
     if (isMemIntrinsic())
       return !asMemIntrinsic()->isVolatile();
+    if (isCallInst())
+      return true;
     llvm_unreachable("Operation not supported on nullptr");
   }
   llvm::AtomicOrdering getOrdering() const {
@@ -214,6 +233,8 @@ public:
       return asStore()->getOrdering();
     if (isMemIntrinsic())
       return llvm::AtomicOrdering::NotAtomic;
+    if (isCallInst())
+      return llvm::AtomicOrdering::NotAtomic;
     llvm_unreachable("Operation not supported on nullptr");
   }
   bool isUnordered() const {
@@ -224,6 +245,8 @@ public:
     // Copied from the Load/Store implementation of isUnordered:
     if (isMemIntrinsic())
       return !asMemIntrinsic()->isVolatile();
+    if (isCallInst())
+      return true;
     llvm_unreachable("Operation not supported on nullptr");
   }
 
@@ -231,6 +254,7 @@ public:
   bool isInstruction() const { return I; }
   bool isLoad() const { return I && llvm::isa<llvm::LoadInst>(I); }
   bool isStore() const { return I && llvm::isa<llvm::StoreInst>(I); }
+  bool isCallInst() const { return I && llvm::isa<llvm::CallInst>(I); }
   bool isMemIntrinsic() const { return I && llvm::isa<llvm::MemIntrinsic>(I); }
   bool isMemSetInst() const { return I && llvm::isa<llvm::MemSetInst>(I); }
   bool isMemTransferInst() const {
@@ -240,6 +264,7 @@ public:
   llvm::Instruction *asInstruction() const { return I; }
   llvm::LoadInst *asLoad() const { return llvm::cast<llvm::LoadInst>(I); }
   llvm::StoreInst *asStore() const { return llvm::cast<llvm::StoreInst>(I); }
+  llvm::CallInst *asCallInst() const { return llvm::cast<llvm::CallInst>(I); }
   llvm::MemIntrinsic *asMemIntrinsic() const {
     return llvm::cast<llvm::MemIntrinsic>(I);
   }

Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=261866&r1=261865&r2=261866&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Thu Feb 25 08:08:48 2016
@@ -451,7 +451,8 @@ bool ScopDetection::isValidCallInst(Call
     return true;
 
   if (auto *II = dyn_cast<IntrinsicInst>(&CI))
-    return isValidIntrinsicInst(*II, Context);
+    if (isValidIntrinsicInst(*II, Context))
+      return true;
 
   Function *CalledFunction = CI.getCalledFunction();
 
@@ -459,6 +460,41 @@ bool ScopDetection::isValidCallInst(Call
   if (CalledFunction == 0)
     return false;
 
+  switch (AA->getModRefBehavior(CalledFunction)) {
+  case llvm::FMRB_UnknownModRefBehavior:
+    return false;
+  case llvm::FMRB_DoesNotAccessMemory:
+  case llvm::FMRB_OnlyReadsMemory:
+    // Implicitly disable delinearization since we have an unknown
+    // accesses with an unknown access function.
+    Context.HasUnknownAccess = true;
+    Context.AST.add(&CI);
+    return true;
+  case llvm::FMRB_OnlyReadsArgumentPointees:
+  case llvm::FMRB_OnlyAccessesArgumentPointees:
+    for (const auto &Arg : CI.arg_operands()) {
+      if (!Arg->getType()->isPointerTy())
+        continue;
+
+      // Bail if a pointer argument has a base address not known to
+      // ScalarEvolution. Note that a zero pointer is acceptable.
+      auto *ArgSCEV = SE->getSCEVAtScope(Arg, LI->getLoopFor(CI.getParent()));
+      if (ArgSCEV->isZero())
+        continue;
+
+      auto *BP = dyn_cast<SCEVUnknown>(SE->getPointerBase(ArgSCEV));
+      if (!BP)
+        return false;
+
+      // Implicitly disable delinearization since we have an unknown
+      // accesses with an unknown access function.
+      Context.HasUnknownAccess = true;
+    }
+
+    Context.AST.add(&CI);
+    return true;
+  }
+
   return false;
 }
 
@@ -784,6 +820,11 @@ bool ScopDetection::hasBaseAffineAccesse
 }
 
 bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
+  // TODO: If we have an unknown access and other non-affine accesses we do
+  //       not try to delinearize them for now.
+  if (Context.HasUnknownAccess && !Context.NonAffineAccesses.empty())
+    return AllowNonAffine;
+
   for (const SCEVUnknown *BasePointer : Context.NonAffineAccesses)
     if (!hasBaseAffineAccesses(Context, BasePointer)) {
       if (KeepGoing)

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=261866&r1=261865&r2=261866&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Thu Feb 25 08:08:48 2016
@@ -202,7 +202,7 @@ void ScopArrayInfo::updateElementType(Ty
   auto OldElementSize = DL.getTypeAllocSizeInBits(ElementType);
   auto NewElementSize = DL.getTypeAllocSizeInBits(NewElementType);
 
-  if (NewElementSize == OldElementSize)
+  if (NewElementSize == OldElementSize || NewElementSize == 0)
     return;
 
   if (NewElementSize % OldElementSize == 0 && NewElementSize < OldElementSize) {
@@ -620,16 +620,22 @@ void MemoryAccess::buildMemIntrinsicAcce
   assert(MAI.isMemIntrinsic());
   assert(Subscripts.size() == 2 && Sizes.size() == 0);
 
-  auto *LengthPWA = Statement->getPwAff(Subscripts[1]);
-  auto *LengthMap = isl_map_from_pw_aff(LengthPWA);
-  auto *RangeSpace = isl_space_range(isl_map_get_space(LengthMap));
-  LengthMap = isl_map_apply_range(LengthMap, isl_map_lex_gt(RangeSpace));
-  LengthMap = isl_map_lower_bound_si(LengthMap, isl_dim_out, 0, 0);
   auto *SubscriptPWA = Statement->getPwAff(Subscripts[0]);
   auto *SubscriptMap = isl_map_from_pw_aff(SubscriptPWA);
+
+  isl_map *LengthMap;
+  if (Subscripts[1] == nullptr) {
+    LengthMap = isl_map_universe(isl_map_get_space(SubscriptMap));
+  } else {
+    auto *LengthPWA = Statement->getPwAff(Subscripts[1]);
+    LengthMap = isl_map_from_pw_aff(LengthPWA);
+    auto *RangeSpace = isl_space_range(isl_map_get_space(LengthMap));
+    LengthMap = isl_map_apply_range(LengthMap, isl_map_lex_gt(RangeSpace));
+  }
+  LengthMap = isl_map_lower_bound_si(LengthMap, isl_dim_out, 0, 0);
+  LengthMap = isl_map_align_params(LengthMap, isl_map_get_space(SubscriptMap));
   SubscriptMap =
       isl_map_align_params(SubscriptMap, isl_map_get_space(LengthMap));
-  LengthMap = isl_map_align_params(LengthMap, isl_map_get_space(SubscriptMap));
   LengthMap = isl_map_sum(LengthMap, SubscriptMap);
   AccessRelation = isl_map_set_tuple_id(LengthMap, isl_dim_in,
                                         getStatement()->getDomainId());
@@ -725,6 +731,7 @@ __isl_give isl_map *MemoryAccess::foldAc
 
 /// @brief Check if @p Expr is divisible by @p Size.
 static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE) {
+  assert(Size != 0);
   if (Size == 1)
     return true;
 
@@ -3937,6 +3944,15 @@ bool ScopInfo::buildAccessMemIntrinsic(
   auto *LengthVal = SE->getSCEVAtScope(Inst.asMemIntrinsic()->getLength(), L);
   assert(LengthVal);
 
+  // Check if the length val is actually affine or if we overapproximate it
+  InvariantLoadsSetTy AccessILS;
+  bool LengthIsAffine = isAffineExpr(R, LengthVal, *SE, nullptr, &AccessILS);
+  for (LoadInst *LInst : AccessILS)
+    if (!ScopRIL.count(LInst))
+      LengthIsAffine = false;
+  if (!LengthIsAffine)
+    LengthVal = nullptr;
+
   auto *DestPtrVal = Inst.asMemIntrinsic()->getDest();
   assert(DestPtrVal);
   auto *DestAccFunc = SE->getSCEVAtScope(DestPtrVal, L);
@@ -3965,6 +3981,51 @@ bool ScopInfo::buildAccessMemIntrinsic(
   return true;
 }
 
+bool ScopInfo::buildAccessCallInst(
+    MemAccInst Inst, Loop *L, Region *R,
+    const ScopDetection::BoxedLoopsSetTy *BoxedLoops,
+    const InvariantLoadsSetTy &ScopRIL) {
+  if (!Inst.isCallInst())
+    return false;
+
+  auto &CI = *Inst.asCallInst();
+  if (CI.doesNotAccessMemory() || isIgnoredIntrinsic(&CI))
+    return true;
+
+  bool ReadOnly = false;
+  auto *AF = SE->getConstant(IntegerType::getInt64Ty(CI.getContext()), 0);
+  auto *CalledFunction = CI.getCalledFunction();
+  switch (AA->getModRefBehavior(CalledFunction)) {
+  case llvm::FMRB_UnknownModRefBehavior:
+    llvm_unreachable("Unknown mod ref behaviour cannot be represented.");
+  case llvm::FMRB_DoesNotAccessMemory:
+    return true;
+  case llvm::FMRB_OnlyReadsMemory:
+    GlobalReads.push_back(&CI);
+    return true;
+  case llvm::FMRB_OnlyReadsArgumentPointees:
+    ReadOnly = true;
+  // Fall through
+  case llvm::FMRB_OnlyAccessesArgumentPointees:
+    auto AccType = ReadOnly ? MemoryAccess::READ : MemoryAccess::MAY_WRITE;
+    for (const auto &Arg : CI.arg_operands()) {
+      if (!Arg->getType()->isPointerTy())
+        continue;
+
+      auto *ArgSCEV = SE->getSCEVAtScope(Arg, L);
+      if (ArgSCEV->isZero())
+        continue;
+
+      auto *ArgBasePtr = cast<SCEVUnknown>(SE->getPointerBase(ArgSCEV));
+      addArrayAccess(Inst, AccType, ArgBasePtr->getValue(),
+                     ArgBasePtr->getType(), false, {AF}, {}, &CI);
+    }
+    return true;
+  }
+
+  return true;
+}
+
 void ScopInfo::buildAccessSingleDim(
     MemAccInst Inst, Loop *L, Region *R,
     const ScopDetection::BoxedLoopsSetTy *BoxedLoops,
@@ -4016,6 +4077,9 @@ void ScopInfo::buildMemoryAccess(
   if (buildAccessMemIntrinsic(Inst, L, R, BoxedLoops, ScopRIL))
     return;
 
+  if (buildAccessCallInst(Inst, L, R, BoxedLoops, ScopRIL))
+    return;
+
   if (buildAccessMultiDimFixed(Inst, L, R, BoxedLoops, ScopRIL))
     return;
 
@@ -4152,6 +4216,7 @@ void ScopInfo::addArrayAccess(MemAccInst
                               bool IsAffine, ArrayRef<const SCEV *> Subscripts,
                               ArrayRef<const SCEV *> Sizes,
                               Value *AccessValue) {
+  ArrayBasePointers.insert(BaseAddress);
   addMemoryAccess(MemAccInst.getParent(), MemAccInst, AccType, BaseAddress,
                   ElementType, IsAffine, AccessValue, Subscripts, Sizes,
                   ScopArrayInfo::MK_Array);
@@ -4277,6 +4342,13 @@ void ScopInfo::buildScop(Region &R, Assu
     buildAccessFunctions(R, *R.getExit(), *SD->getInsnToMemAccMap(&R), nullptr,
                          /* IsExitBlock */ true);
 
+  // Create memory accesses for global reads since all arrays are now known.
+  auto *AF = SE->getConstant(IntegerType::getInt64Ty(SE->getContext()), 0);
+  for (auto *GlobalRead : GlobalReads)
+    for (auto *BP : ArrayBasePointers)
+      addArrayAccess(MemAccInst(GlobalRead), MemoryAccess::READ, BP,
+                     BP->getType(), false, {AF}, {}, GlobalRead);
+
   scop->init(*AA, AC, *SD, *DT, *LI);
 }
 

Modified: polly/trunk/lib/CodeGen/IRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/IRBuilder.cpp?rev=261866&r1=261865&r2=261866&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/IRBuilder.cpp (original)
+++ polly/trunk/lib/CodeGen/IRBuilder.cpp Thu Feb 25 08:08:48 2016
@@ -135,7 +135,11 @@ void ScopAnnotator::annotate(Instruction
   if (!MemInst)
     return;
 
-  auto *PtrSCEV = SE->getSCEV(MemInst.getPointerOperand());
+  auto *Ptr = MemInst.getPointerOperand();
+  if (!Ptr)
+    return;
+
+  auto *PtrSCEV = SE->getSCEV(Ptr);
   auto *BaseSCEV = SE->getPointerBase(PtrSCEV);
   auto *SU = dyn_cast<SCEVUnknown>(BaseSCEV);
 

Added: polly/trunk/test/ScopDetect/mod_ref_read_pointer.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopDetect/mod_ref_read_pointer.ll?rev=261866&view=auto
==============================================================================
--- polly/trunk/test/ScopDetect/mod_ref_read_pointer.ll (added)
+++ polly/trunk/test/ScopDetect/mod_ref_read_pointer.ll Thu Feb 25 08:08:48 2016
@@ -0,0 +1,41 @@
+; RUN: opt %loadPolly -basicaa -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop: for.cond => for.end
+;
+;    #pragma readonly
+;    int func(int *A);
+;
+;    void jd(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i + 2] = func(A);
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare i32 @func(i32* %A) #1
+
+define void @jd(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %call = call i32 @func(i32* %A)
+  %tmp = add nsw i64 %indvars.iv, 2
+  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %tmp
+  store i32 %call, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+attributes #1 = { nounwind readonly }

Added: polly/trunk/test/ScopInfo/mod_ref_access_pointee_arguments.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/mod_ref_access_pointee_arguments.ll?rev=261866&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/mod_ref_access_pointee_arguments.ll (added)
+++ polly/trunk/test/ScopInfo/mod_ref_access_pointee_arguments.ll Thu Feb 25 08:08:48 2016
@@ -0,0 +1,56 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-codegen -disable-output < %s
+;
+; Verify that we model the may-write access of the prefetch intrinsic
+; correctly, thus that A is accessed by it but B is not.
+;
+; CHECK:      Stmt_for_body
+; CHECK-NEXT:   Domain :=
+; CHECK-NEXT:       { Stmt_for_body[i0] : 0 <= i0 <= 1023 };
+; CHECK-NEXT:   Schedule :=
+; CHECK-NEXT:       { Stmt_for_body[i0] -> [i0] };
+; CHECK-NEXT:   MayWriteAccess := [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_A[o0] };
+; CHECK-NEXT:   ReadAccess := [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_B[i0] };
+; CHECK-NEXT:   MustWriteAccess :=  [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_A[i0] };
+;
+;    void jd(int *restirct A, int *restrict B) {
+;      for (int i = 0; i < 1024; i++) {
+;        @llvm.prefetch(A);
+;        A[i] = B[i];
+;      }
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* noalias %A, i32* noalias %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+  %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
+  %bc = bitcast i32* %arrayidx to i8*
+  call void @f(i8* %bc, i32 1, i32 1, i32 1)
+  %tmp = load i32, i32* %arrayidx2
+  store i32 %tmp, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+declare void @f(i8*, i32, i32, i32) #0
+
+attributes #0 = { argmemonly nounwind }

Added: polly/trunk/test/ScopInfo/mod_ref_read_pointee_arguments.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/mod_ref_read_pointee_arguments.ll?rev=261866&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/mod_ref_read_pointee_arguments.ll (added)
+++ polly/trunk/test/ScopInfo/mod_ref_read_pointee_arguments.ll Thu Feb 25 08:08:48 2016
@@ -0,0 +1,65 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-codegen -disable-output < %s
+;
+; Verify that we model the read access of the gcread intrinsic
+; correctly, thus that A is read by it but B is not.
+;
+; CHECK:      Stmt_for_body
+; CHECK-NEXT:   Domain :=
+; CHECK-NEXT:       { Stmt_for_body[i0] : 0 <= i0 <= 1023 };
+; CHECK-NEXT:   Schedule :=
+; CHECK-NEXT:       { Stmt_for_body[i0] -> [i0] };
+; CHECK-NEXT:   ReadAccess := [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_A[o0] };
+; CHECK-NEXT:   MustWriteAccess :=  [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_dummyloc[0] };
+; CHECK-NEXT:   ReadAccess := [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_B[i0] };
+; CHECK-NEXT:   MustWriteAccess :=  [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_A[i0] };
+;
+;    void jd(int *restirct A, int *restrict B) {
+;      char **dummyloc;
+;      for (int i = 0; i < 1024; i++) {
+;        char *dummy = @llvm.gcread(A, nullptr);
+;        *dummyloc = dummy;
+;        A[i] = B[i];
+;      }
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* noalias %A, i32* noalias %B) gc "dummy" {
+entry:
+  %dummyloc = alloca i8*
+  br label %entry.split
+
+entry.split:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry.split
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry.split ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+  %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
+  %bc = bitcast i32* %arrayidx to i8*
+  %dummy = call i8* @f(i8* %bc, i8** null)
+  store i8* %dummy, i8** %dummyloc, align 4
+  %tmp = load i32, i32* %arrayidx2
+  store i32 %tmp, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+declare i8* @f(i8*, i8**) #0
+
+attributes #0 = { argmemonly readonly nounwind }

Added: polly/trunk/test/ScopInfo/mod_ref_read_pointer.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/mod_ref_read_pointer.ll?rev=261866&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/mod_ref_read_pointer.ll (added)
+++ polly/trunk/test/ScopInfo/mod_ref_read_pointer.ll Thu Feb 25 08:08:48 2016
@@ -0,0 +1,52 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-codegen -disable-output < %s
+;
+; Check that we assume the call to func has a read on the whole A array.
+;
+; CHECK:      Stmt_for_body
+; CHECK-NEXT:   Domain :=
+; CHECK-NEXT:       { Stmt_for_body[i0] : 0 <= i0 <= 1023 };
+; CHECK-NEXT:   Schedule :=
+; CHECK-NEXT:       { Stmt_for_body[i0] -> [i0] };
+; CHECK-NEXT:   MustWriteAccess :=  [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_A[2 + i0] };
+; CHECK-NEXT:   ReadAccess :=  [Reduction Type: NONE]
+; CHECK-NEXT:       { Stmt_for_body[i0] -> MemRef_A[o0] };
+;
+;    #pragma readonly
+;    int func(int *A);
+;
+;    void jd(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i + 2] = func(A);
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %call = call i32 @func(i32* %A) #2
+  %tmp = add nsw i64 %indvars.iv, 2
+  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %tmp
+  store i32 %call, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+declare i32 @func(i32*) #1
+
+attributes #1 = { nounwind readonly }

Added: polly/trunk/test/ScopInfo/mod_ref_read_pointers.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/mod_ref_read_pointers.ll?rev=261866&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/mod_ref_read_pointers.ll (added)
+++ polly/trunk/test/ScopInfo/mod_ref_read_pointers.ll Thu Feb 25 08:08:48 2016
@@ -0,0 +1,60 @@
+; RUN: opt %loadPolly -basicaa -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -basicaa -polly-codegen -disable-output < %s
+;
+; Check that the call to func will "read" not only the A array but also the
+; B array. The reason is the readonly annotation of func.
+;
+; CHECK:      Stmt_for_body
+; CHECK-NEXT:  Domain :=
+; CHECK-NEXT:      { Stmt_for_body[i0] : 0 <= i0 <= 1023 };
+; CHECK-NEXT:  Schedule :=
+; CHECK-NEXT:      { Stmt_for_body[i0] -> [i0] };
+; CHECK-NEXT:  ReadAccess :=  [Reduction Type: NONE]
+; CHECK-NEXT:      { Stmt_for_body[i0] -> MemRef_B[i0] };
+; CHECK-NEXT:  MustWriteAccess :=  [Reduction Type: NONE]
+; CHECK-NEXT:      { Stmt_for_body[i0] -> MemRef_A[2 + i0] };
+; CHECK-DAG:   ReadAccess :=  [Reduction Type: NONE]
+; CHECK-DAG:       { Stmt_for_body[i0] -> MemRef_B[o0] };
+; CHECK-DAG:   ReadAccess :=  [Reduction Type: NONE]
+; CHECK-DAG:       { Stmt_for_body[i0] -> MemRef_A[o0] };
+;
+;    #pragma readonly
+;    int func(int *A);
+;
+;    void jd(int *restrict A, int *restrict B) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i + 2] = func(A) + B[i];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* noalias %A, i32* noalias %B) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %call = call i32 @func(i32* %A)
+  %arrayidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv
+  %tmp = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %call, %tmp
+  %tmp2 = add nsw i64 %indvars.iv, 2
+  %arrayidx3 = getelementptr inbounds i32, i32* %A, i64 %tmp2
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+declare i32 @func(i32*) #1
+
+attributes #1 = { nounwind readonly }

Added: polly/trunk/test/ScopInfo/multidim_2d_with_modref_call.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/multidim_2d_with_modref_call.ll?rev=261866&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/multidim_2d_with_modref_call.ll (added)
+++ polly/trunk/test/ScopInfo/multidim_2d_with_modref_call.ll Thu Feb 25 08:08:48 2016
@@ -0,0 +1,179 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine -analyze < %s | FileCheck %s --check-prefix=NONAFFINE
+
+;  TODO: We should delinearize the accesses despite the use in a call to a
+;        readonly function. For now we verify we do not delinearize them though.
+
+; CHECK:         Function: ham
+; CHECK-NEXT:    Region: %bb12---%bb28
+; CHECK-NEXT:    Max Loop Depth:  1
+; CHECK-NEXT:    Invariant Accesses: {
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> MemRef_arg1[0] };
+; CHECK-NEXT:            Execution Context: [tmp14, p_1] -> {  :  }
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  : -9223372036854775808 <= tmp14 <= 9223372036854775807 and -9223372036854775808 <= p_1 <= 9223372036854775807 }
+; CHECK-NEXT:    Assumed Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  :  }
+; CHECK-NEXT:    Boundary Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  : tmp14 <= 1152921504606846976 and (tmp14 <= 0 or (tmp14 > 0 and -1152921504606846976 <= p_1 <= 1152921504606846976 - tmp14)) }
+; CHECK-NEXT:    p0: %tmp14
+; CHECK-NEXT:    p1: {0,+,(0 smax %tmp)}<%bb12>
+; CHECK-NEXT:    Arrays {
+; CHECK-NEXT:        i64 MemRef_tmp13; // Element size 8
+; CHECK-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; CHECK-NEXT:        double MemRef_arg4[*]; // Element size 8
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Arrays (Bounds as pw_affs) {
+; CHECK-NEXT:        i64 MemRef_tmp13; // Element size 8
+; CHECK-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; CHECK-NEXT:        double MemRef_arg4[*]; // Element size 8
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Alias Groups (0):
+; CHECK-NEXT:        n/a
+; CHECK-NEXT:    Statements {
+; CHECK-NEXT:    	Stmt_bb12
+; CHECK-NEXT:            Domain :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] };
+; CHECK-NEXT:            Schedule :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> [0, 0] };
+; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> MemRef_tmp13[] };
+; CHECK-NEXT:    	Stmt_bb17
+; CHECK-NEXT:            Domain :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] : 0 <= i0 < tmp14 };
+; CHECK-NEXT:            Schedule :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> [1, i0] };
+; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> MemRef_arg4[p_1 + i0] };
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> MemRef_arg1[o0] };
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> MemRef_arg4[o0] };
+; CHECK-NEXT:    }
+
+
+; NONAFFINE:         Function: ham
+; NONAFFINE-NEXT:    Region: %bb5---%bb32
+; NONAFFINE-NEXT:    Max Loop Depth:  2
+; NONAFFINE-NEXT:    Invariant Accesses: {
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_arg[0] };
+; NONAFFINE-NEXT:            Execution Context: [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb12[i0] -> MemRef_arg1[0] };
+; NONAFFINE-NEXT:            Execution Context: [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  : -9223372036854775808 <= tmp9 <= 9223372036854775807 and -9223372036854775808 <= tmp14 <= 9223372036854775807 }
+; NONAFFINE-NEXT:    Assumed Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    Boundary Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    p0: %tmp9
+; NONAFFINE-NEXT:    p1: %tmp14
+; NONAFFINE-NEXT:    Arrays {
+; NONAFFINE-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_arg[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp7; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp8; // Element size 8
+; NONAFFINE-NEXT:        double MemRef_arg4[*]; // Element size 8
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Arrays (Bounds as pw_affs) {
+; NONAFFINE-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_arg[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp7; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp8; // Element size 8
+; NONAFFINE-NEXT:        double MemRef_arg4[*]; // Element size 8
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Alias Groups (0):
+; NONAFFINE-NEXT:        n/a
+; NONAFFINE-NEXT:    Statements {
+; NONAFFINE-NEXT:    	Stmt_bb5
+; NONAFFINE-NEXT:            Domain :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] };
+; NONAFFINE-NEXT:            Schedule :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> [0, 0, 0] };
+; NONAFFINE-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_tmp7[] };
+; NONAFFINE-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_tmp8[] };
+; NONAFFINE-NEXT:    	Stmt_bb17
+; NONAFFINE-NEXT:            Domain :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] : 0 <= i0 < tmp9 and 0 <= i1 < tmp14 };
+; NONAFFINE-NEXT:            Schedule :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> [1, i0, i1] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_tmp7[] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_tmp8[] };
+; NONAFFINE-NEXT:            MayWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg4[o0] : -1152921504606846976 <= o0 <= 1152921504606846975 };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg1[o0] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg[o0] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg4[o0] };
+
+target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+define void @ham(i64* noalias %arg, i64* noalias %arg1, i64* noalias %arg2, i64* noalias %arg3, [1000 x double]* noalias %arg4) unnamed_addr {
+bb:
+  br label %bb5
+
+bb5:                                              ; preds = %bb
+  %tmp = load i64, i64* %arg1, align 8
+  %tmp6 = icmp slt i64 %tmp, 0
+  %tmp7 = select i1 %tmp6, i64 0, i64 %tmp
+  %tmp8 = xor i64 %tmp7, -1
+  %tmp9 = load i64, i64* %arg, align 8
+  %tmp10 = icmp sgt i64 %tmp9, 0
+  br i1 %tmp10, label %bb11, label %bb32
+
+bb11:                                             ; preds = %bb5
+  br label %bb12
+
+bb12:                                             ; preds = %bb28, %bb11
+  %tmp13 = phi i64 [ %tmp30, %bb28 ], [ 1, %bb11 ]
+  %tmp14 = load i64, i64* %arg1, align 8
+  %tmp15 = icmp sgt i64 %tmp14, 0
+  br i1 %tmp15, label %bb16, label %bb28
+
+bb16:                                             ; preds = %bb12
+  br label %bb17
+
+bb17:                                             ; preds = %bb17, %bb16
+  %tmp18 = phi i64 [ %tmp26, %bb17 ], [ 1, %bb16 ]
+  %tmp19 = mul i64 %tmp13, %tmp7
+  %tmp20 = add i64 %tmp19, %tmp8
+  %tmp21 = add i64 %tmp20, %tmp18
+  %tmp22 = add i64 %tmp18, %tmp13
+  %tmp23 = sitofp i64 %tmp22 to double
+  %tmp24 = getelementptr [1000 x double], [1000 x double]* %arg4, i64 0, i64 %tmp21
+  %call = call double @func(double* %tmp24) #2
+  %sum = fadd double %call, %tmp23
+  store double %sum, double* %tmp24, align 8
+  %tmp25 = icmp eq i64 %tmp18, %tmp14
+  %tmp26 = add i64 %tmp18, 1
+  br i1 %tmp25, label %bb27, label %bb17
+
+bb27:                                             ; preds = %bb17
+  br label %bb28
+
+bb28:                                             ; preds = %bb27, %bb12
+  %tmp29 = icmp eq i64 %tmp13, %tmp9
+  %tmp30 = add i64 %tmp13, 1
+  br i1 %tmp29, label %bb31, label %bb12
+
+bb31:                                             ; preds = %bb28
+  br label %bb32
+
+bb32:                                             ; preds = %bb31, %bb5
+  ret void
+}
+
+declare double @func(double*) #1
+
+attributes #1 = { nounwind readonly }

Added: polly/trunk/test/ScopInfo/multidim_2d_with_modref_call_2.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/multidim_2d_with_modref_call_2.ll?rev=261866&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/multidim_2d_with_modref_call_2.ll (added)
+++ polly/trunk/test/ScopInfo/multidim_2d_with_modref_call_2.ll Thu Feb 25 08:08:48 2016
@@ -0,0 +1,172 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine -analyze < %s | FileCheck %s --check-prefix=NONAFFINE
+
+;  TODO: We should delinearize the accesses despite the use in a call to a
+;        readonly function. For now we verify we do not delinearize them though.
+
+; CHECK:         Function: ham
+; CHECK-NEXT:    Region: %bb12---%bb28
+; CHECK-NEXT:    Max Loop Depth:  1
+; CHECK-NEXT:    Invariant Accesses: {
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> MemRef_arg1[0] };
+; CHECK-NEXT:            Execution Context: [tmp14, p_1] -> {  :  }
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  : -9223372036854775808 <= tmp14 <= 9223372036854775807 and -9223372036854775808 <= p_1 <= 9223372036854775807 }
+; CHECK-NEXT:    Assumed Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  :  }
+; CHECK-NEXT:    Boundary Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  : tmp14 <= 1152921504606846976 and (tmp14 <= 0 or (tmp14 > 0 and -1152921504606846976 <= p_1 <= 1152921504606846976 - tmp14)) }
+; CHECK-NEXT:    p0: %tmp14
+; CHECK-NEXT:    p1: {0,+,(0 smax %tmp)}<%bb12>
+; CHECK-NEXT:    Arrays {
+; CHECK-NEXT:        i64 MemRef_tmp13; // Element size 8
+; CHECK-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; CHECK-NEXT:        [1000 x double]* MemRef_arg4[*]; // Element size 8
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Arrays (Bounds as pw_affs) {
+; CHECK-NEXT:        i64 MemRef_tmp13; // Element size 8
+; CHECK-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; CHECK-NEXT:        [1000 x double]* MemRef_arg4[*]; // Element size 8
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Alias Groups (0):
+; CHECK-NEXT:        n/a
+; CHECK-NEXT:    Statements {
+; CHECK-NEXT:    	Stmt_bb12
+; CHECK-NEXT:            Domain :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] };
+; CHECK-NEXT:            Schedule :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> [0, 0] };
+; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> MemRef_tmp13[] };
+; CHECK-NEXT:    	Stmt_bb17
+; CHECK-NEXT:            Domain :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] : 0 <= i0 < tmp14 };
+; CHECK-NEXT:            Schedule :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> [1, i0] };
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> MemRef_arg4[o0] };
+; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> MemRef_arg4[p_1 + i0] };
+; CHECK-NEXT:    }
+
+
+; NONAFFINE:         Function: ham
+; NONAFFINE-NEXT:    Region: %bb5---%bb32
+; NONAFFINE-NEXT:    Max Loop Depth:  2
+; NONAFFINE-NEXT:    Invariant Accesses: {
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_arg[0] };
+; NONAFFINE-NEXT:            Execution Context: [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb12[i0] -> MemRef_arg1[0] };
+; NONAFFINE-NEXT:            Execution Context: [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  : -9223372036854775808 <= tmp9 <= 9223372036854775807 and -9223372036854775808 <= tmp14 <= 9223372036854775807 }
+; NONAFFINE-NEXT:    Assumed Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    Boundary Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    p0: %tmp9
+; NONAFFINE-NEXT:    p1: %tmp14
+; NONAFFINE-NEXT:    Arrays {
+; NONAFFINE-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_arg[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp7; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp8; // Element size 8
+; NONAFFINE-NEXT:        [1000 x double]* MemRef_arg4[*]; // Element size 8
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Arrays (Bounds as pw_affs) {
+; NONAFFINE-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_arg[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp7; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp8; // Element size 8
+; NONAFFINE-NEXT:        [1000 x double]* MemRef_arg4[*]; // Element size 8
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Alias Groups (0):
+; NONAFFINE-NEXT:        n/a
+; NONAFFINE-NEXT:    Statements {
+; NONAFFINE-NEXT:    	Stmt_bb5
+; NONAFFINE-NEXT:            Domain :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] };
+; NONAFFINE-NEXT:            Schedule :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> [0, 0, 0] };
+; NONAFFINE-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_tmp7[] };
+; NONAFFINE-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_tmp8[] };
+; NONAFFINE-NEXT:    	Stmt_bb17
+; NONAFFINE-NEXT:            Domain :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] : 0 <= i0 < tmp9 and 0 <= i1 < tmp14 };
+; NONAFFINE-NEXT:            Schedule :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> [1, i0, i1] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_tmp7[] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_tmp8[] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg4[o0] };
+; NONAFFINE-NEXT:            MayWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg4[o0] : -1152921504606846976 <= o0 <= 1152921504606846975 };
+; NONAFFINE-NEXT:    }
+
+target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+define void @ham(i64* noalias %arg, i64* noalias %arg1, i64* noalias %arg2, i64* noalias %arg3, [1000 x double]* noalias %arg4) gc "dummy" {
+bb:
+  br label %bb5
+
+bb5:                                              ; preds = %bb
+  %tmp = load i64, i64* %arg1, align 8
+  %tmp6 = icmp slt i64 %tmp, 0
+  %tmp7 = select i1 %tmp6, i64 0, i64 %tmp
+  %tmp8 = xor i64 %tmp7, -1
+  %tmp9 = load i64, i64* %arg, align 8
+  %tmp10 = icmp sgt i64 %tmp9, 0
+  br i1 %tmp10, label %bb11, label %bb32
+
+bb11:                                             ; preds = %bb5
+  br label %bb12
+
+bb12:                                             ; preds = %bb28, %bb11
+  %tmp13 = phi i64 [ %tmp30, %bb28 ], [ 1, %bb11 ]
+  %tmp14 = load i64, i64* %arg1, align 8
+  %tmp15 = icmp sgt i64 %tmp14, 0
+  br i1 %tmp15, label %bb16, label %bb28
+
+bb16:                                             ; preds = %bb12
+  br label %bb17
+
+bb17:                                             ; preds = %bb17, %bb16
+  %tmp18 = phi i64 [ %tmp26, %bb17 ], [ 1, %bb16 ]
+  %tmp19 = mul i64 %tmp13, %tmp7
+  %tmp20 = add i64 %tmp19, %tmp8
+  %tmp21 = add i64 %tmp20, %tmp18
+  %tmp22 = add i64 %tmp18, %tmp13
+  %tmp23 = sitofp i64 %tmp22 to double
+  %tmp24 = getelementptr [1000 x double], [1000 x double]* %arg4, i64 0, i64 %tmp21
+  %bc = bitcast double* %tmp24 to i8*
+  %dummy = call i8* @llvm.gcread(i8* %bc, i8** null)
+  store double %tmp23, double* %tmp24, align 8
+  %tmp25 = icmp eq i64 %tmp18, %tmp14
+  %tmp26 = add i64 %tmp18, 1
+  br i1 %tmp25, label %bb27, label %bb17
+
+bb27:                                             ; preds = %bb17
+  br label %bb28
+
+bb28:                                             ; preds = %bb27, %bb12
+  %tmp29 = icmp eq i64 %tmp13, %tmp9
+  %tmp30 = add i64 %tmp13, 1
+  br i1 %tmp29, label %bb31, label %bb12
+
+bb31:                                             ; preds = %bb28
+  br label %bb32
+
+bb32:                                             ; preds = %bb31, %bb5
+  ret void
+}
+
+declare i8* @llvm.gcread(i8*, i8**)

Added: polly/trunk/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll?rev=261866&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll (added)
+++ polly/trunk/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll Thu Feb 25 08:08:48 2016
@@ -0,0 +1,180 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine -analyze < %s | FileCheck %s --check-prefix=NONAFFINE
+
+;  TODO: We should delinearize the accesses despite the use in a call to a
+;        readonly function. For now we verify we do not delinearize them though.
+
+; CHECK:         Function: ham
+; CHECK-NEXT:    Region: %bb12---%bb28
+; CHECK-NEXT:    Max Loop Depth:  1
+; CHECK-NEXT:    Invariant Accesses: {
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> MemRef_arg1[0] };
+; CHECK-NEXT:            Execution Context: [tmp14, p_1] -> {  :  }
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  : -9223372036854775808 <= tmp14 <= 9223372036854775807 and -9223372036854775808 <= p_1 <= 9223372036854775807 }
+; CHECK-NEXT:    Assumed Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  :  }
+; CHECK-NEXT:    Boundary Context:
+; CHECK-NEXT:    [tmp14, p_1] -> {  : tmp14 <= 1152921504606846976 and (tmp14 <= 0 or (tmp14 > 0 and -1152921504606846976 <= p_1 <= 1152921504606846976 - tmp14)) }
+; CHECK-NEXT:    p0: %tmp14
+; CHECK-NEXT:    p1: {0,+,(0 smax %tmp)}<%bb12>
+; CHECK-NEXT:    Arrays {
+; CHECK-NEXT:        i64 MemRef_tmp13; // Element size 8
+; CHECK-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; CHECK-NEXT:        double MemRef_arg4[*]; // Element size 8
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Arrays (Bounds as pw_affs) {
+; CHECK-NEXT:        i64 MemRef_tmp13; // Element size 8
+; CHECK-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; CHECK-NEXT:        double MemRef_arg4[*]; // Element size 8
+; CHECK-NEXT:    }
+; CHECK-NEXT:    Alias Groups (0):
+; CHECK-NEXT:        n/a
+; CHECK-NEXT:    Statements {
+; CHECK-NEXT:    	Stmt_bb12
+; CHECK-NEXT:            Domain :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] };
+; CHECK-NEXT:            Schedule :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> [0, 0] };
+; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb12[] -> MemRef_tmp13[] };
+; CHECK-NEXT:    	Stmt_bb17
+; CHECK-NEXT:            Domain :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] : 0 <= i0 < tmp14 };
+; CHECK-NEXT:            Schedule :=
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> [1, i0] };
+; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> MemRef_arg4[p_1 + i0] };
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> MemRef_arg1[o0] };
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [tmp14, p_1] -> { Stmt_bb17[i0] -> MemRef_arg4[o0] };
+; CHECK-NEXT:    }
+
+; NONAFFINE:         Function: ham
+; NONAFFINE-NEXT:    Region: %bb5---%bb32
+; NONAFFINE-NEXT:    Max Loop Depth:  2
+; NONAFFINE-NEXT:    Invariant Accesses: {
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_arg[0] };
+; NONAFFINE-NEXT:            Execution Context: [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb12[i0] -> MemRef_arg1[0] };
+; NONAFFINE-NEXT:            Execution Context: [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  : -9223372036854775808 <= tmp9 <= 9223372036854775807 and -9223372036854775808 <= tmp14 <= 9223372036854775807 }
+; NONAFFINE-NEXT:    Assumed Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    Boundary Context:
+; NONAFFINE-NEXT:    [tmp9, tmp14] -> {  :  }
+; NONAFFINE-NEXT:    p0: %tmp9
+; NONAFFINE-NEXT:    p1: %tmp14
+; NONAFFINE-NEXT:    Arrays {
+; NONAFFINE-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_arg[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp7; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp8; // Element size 8
+; NONAFFINE-NEXT:        double MemRef_arg4[*]; // Element size 8
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Arrays (Bounds as pw_affs) {
+; NONAFFINE-NEXT:        i64 MemRef_arg1[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_arg[*]; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp7; // Element size 8
+; NONAFFINE-NEXT:        i64 MemRef_tmp8; // Element size 8
+; NONAFFINE-NEXT:        double MemRef_arg4[*]; // Element size 8
+; NONAFFINE-NEXT:    }
+; NONAFFINE-NEXT:    Alias Groups (0):
+; NONAFFINE-NEXT:        n/a
+; NONAFFINE-NEXT:    Statements {
+; NONAFFINE-NEXT:    	Stmt_bb5
+; NONAFFINE-NEXT:            Domain :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] };
+; NONAFFINE-NEXT:            Schedule :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> [0, 0, 0] };
+; NONAFFINE-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_tmp7[] };
+; NONAFFINE-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb5[] -> MemRef_tmp8[] };
+; NONAFFINE-NEXT:    	Stmt_bb17
+; NONAFFINE-NEXT:            Domain :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] : 0 <= i0 < tmp9 and 0 <= i1 < tmp14 };
+; NONAFFINE-NEXT:            Schedule :=
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> [1, i0, i1] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_tmp7[] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 1]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_tmp8[] };
+; NONAFFINE-NEXT:            MayWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg4[o0] : -1152921504606846976 <= o0 <= 1152921504606846975 };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg1[o0] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg[o0] };
+; NONAFFINE-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; NONAFFINE-NEXT:                [tmp9, tmp14] -> { Stmt_bb17[i0, i1] -> MemRef_arg4[o0] };
+; NONAFFINE-NEXT:    }
+
+
+target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+define void @ham(i64* noalias %arg, i64* noalias %arg1, i64* noalias %arg2, i64* noalias %arg3, [0 x double]* noalias %arg4) unnamed_addr {
+bb:
+  br label %bb5
+
+bb5:                                              ; preds = %bb
+  %tmp = load i64, i64* %arg1, align 8
+  %tmp6 = icmp slt i64 %tmp, 0
+  %tmp7 = select i1 %tmp6, i64 0, i64 %tmp
+  %tmp8 = xor i64 %tmp7, -1
+  %tmp9 = load i64, i64* %arg, align 8
+  %tmp10 = icmp sgt i64 %tmp9, 0
+  br i1 %tmp10, label %bb11, label %bb32
+
+bb11:                                             ; preds = %bb5
+  br label %bb12
+
+bb12:                                             ; preds = %bb28, %bb11
+  %tmp13 = phi i64 [ %tmp30, %bb28 ], [ 1, %bb11 ]
+  %tmp14 = load i64, i64* %arg1, align 8
+  %tmp15 = icmp sgt i64 %tmp14, 0
+  br i1 %tmp15, label %bb16, label %bb28
+
+bb16:                                             ; preds = %bb12
+  br label %bb17
+
+bb17:                                             ; preds = %bb17, %bb16
+  %tmp18 = phi i64 [ %tmp26, %bb17 ], [ 1, %bb16 ]
+  %tmp19 = mul i64 %tmp13, %tmp7
+  %tmp20 = add i64 %tmp19, %tmp8
+  %tmp21 = add i64 %tmp20, %tmp18
+  %tmp22 = add i64 %tmp18, %tmp13
+  %tmp23 = sitofp i64 %tmp22 to double
+  %tmp24 = getelementptr [0 x double], [0 x double]* %arg4, i64 0, i64 %tmp21
+  %call = call double @func(double* %tmp24) #2
+  %sum = fadd double %call, %tmp23
+  store double %sum, double* %tmp24, align 8
+  %tmp25 = icmp eq i64 %tmp18, %tmp14
+  %tmp26 = add i64 %tmp18, 1
+  br i1 %tmp25, label %bb27, label %bb17
+
+bb27:                                             ; preds = %bb17
+  br label %bb28
+
+bb28:                                             ; preds = %bb27, %bb12
+  %tmp29 = icmp eq i64 %tmp13, %tmp9
+  %tmp30 = add i64 %tmp13, 1
+  br i1 %tmp29, label %bb31, label %bb12
+
+bb31:                                             ; preds = %bb28
+  br label %bb32
+
+bb32:                                             ; preds = %bb31, %bb5
+  ret void
+}
+
+declare double @func(double*) #1
+
+attributes #1 = { nounwind readonly }




More information about the llvm-commits mailing list