[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