[Polly][PATCH 7/8] [RTC] Build and print alias groups

Johannes Doerfert doerfert at cs.uni-saarland.de
Sun Aug 10 00:50:28 PDT 2014


  This change will build and print all alias groups (minimal/maximal
  accesses to possible aliasing base pointers) we have to check before
  we can assume an alias free environment.
---
 include/polly/ScopDetection.h                      |   3 +-
 include/polly/ScopInfo.h                           |  40 ++++++-
 include/polly/Support/GICHelper.h                  |   6 ++
 lib/Analysis/ScopDetection.cpp                     |  19 +++-
 lib/Analysis/ScopInfo.cpp                          | 115 +++++++++++++++++++++
 test/Isl/CodeGen/MemAccess/codegen_simple_float.ll |  41 ++++++++
 .../CodeGen/MemAccess/codegen_simple_md_float.ll   |  71 +++++++++++++
 .../simple___%for.cond---%for.end14.jscop          |  28 +++++
 ...mple___%for.cond---%for.end14.jscop.transformed |  28 +++++
 test/ScopDetect/aliasing_parametric_simple_1.ll    |  35 +++++++
 test/ScopDetect/aliasing_parametric_simple_2.ll    |  39 +++++++
 test/ScopDetect/aliasing_simple_1.ll               |  33 ++++++
 test/ScopDetect/aliasing_simple_2.ll               |  36 +++++++
 test/ScopInfo/Alias-0.ll                           |   6 +-
 test/ScopInfo/Alias-1.ll                           |   6 +-
 test/ScopInfo/Alias-2.ll                           |   6 +-
 test/ScopInfo/Alias-3.ll                           |   6 +-
 test/ScopInfo/Alias-4.ll                           |   6 +-
 test/ScopInfo/aliasing_multiple_alias_groups.ll    |  52 ++++++++++
 19 files changed, 562 insertions(+), 14 deletions(-)
 create mode 100644 test/Isl/CodeGen/MemAccess/codegen_simple_float.ll
 create mode 100644 test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll
 create mode 100644 test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop
 create mode 100644 test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed
 create mode 100644 test/ScopDetect/aliasing_parametric_simple_1.ll
 create mode 100644 test/ScopDetect/aliasing_parametric_simple_2.ll
 create mode 100644 test/ScopDetect/aliasing_simple_1.ll
 create mode 100644 test/ScopDetect/aliasing_simple_2.ll
 create mode 100644 test/ScopInfo/aliasing_multiple_alias_groups.ll

diff --git a/include/polly/ScopDetection.h b/include/polly/ScopDetection.h
index 96eeaef..1fd6b1d 100644
--- a/include/polly/ScopDetection.h
+++ b/include/polly/ScopDetection.h
@@ -107,6 +107,7 @@ typedef std::map<const SCEVUnknown *, const SCEV *> BaseToElSize;
 
 extern bool PollyTrackFailures;
 extern bool PollyDelinearize;
+extern bool PollyUseRuntimeAliasChecks;
 
 /// @brief A function attribute which will cause Polly to skip the function
 extern llvm::StringRef PollySkipFnAttr;
@@ -267,7 +268,7 @@ class ScopDetection : public FunctionPass {
 
 public:
   static char ID;
-  explicit ScopDetection() : FunctionPass(ID) {}
+  explicit ScopDetection();
 
   /// @brief Get the RegionInfo stored in this pass.
   ///
diff --git a/include/polly/ScopInfo.h b/include/polly/ScopInfo.h
index 7c7afb6..c5a9e14 100644
--- a/include/polly/ScopInfo.h
+++ b/include/polly/ScopInfo.h
@@ -47,6 +47,7 @@ struct isl_union_set;
 struct isl_union_map;
 struct isl_space;
 struct isl_constraint;
+struct isl_pw_multi_aff;
 
 namespace polly {
 
@@ -493,7 +494,17 @@ static inline raw_ostream &operator<<(raw_ostream &O, const ScopStmt &S) {
 ///   This context contains information about the values the parameters
 ///   can take and relations between different parameters.
 class Scop {
-  //===-------------------------------------------------------------------===//
+public:
+  /// @brief Type to represent a pair of minimal/maximal access to an array.
+  using MinMaxAccessTy = std::pair<isl_pw_multi_aff *, isl_pw_multi_aff *>;
+
+  /// @brief A vector of minimal/maximal accesses to different arrays.
+  using MinMaxVectorTy = SmallVector<MinMaxAccessTy, 4>;
+
+  /// @brief A set of minimal/maximal access vectors one for each alias group.
+  using MinMaxVectorSetTy = SmallPtrSet<MinMaxVectorTy *, 4>;
+
+private:
   Scop(const Scop &) LLVM_DELETED_FUNCTION;
   const Scop &operator=(const Scop &) LLVM_DELETED_FUNCTION;
 
@@ -532,6 +543,21 @@ class Scop {
   /// this scop and that need to be code generated as a run-time test.
   isl_set *AssumedContext;
 
+  /// @brief The set of minimal/maximal accesses for each alias group.
+  ///
+  /// When building runtime alias checks we look at all memory instructions and
+  /// build so called alias groups. Each group contains a set of a accesses to
+  /// different base arrays which might alias with each other. However, between
+  /// alias groups there is no aliasing possible.
+  ///
+  /// In a program with int and float pointer annotated with tbaa information we
+  /// would probably generate two alias groups, one for the int pointers and one
+  /// for the float pointers.
+  ///
+  /// During code generation we will create a runtime alias check for each alias
+  /// group to ensure the SCoP is executed in a alias free environment.
+  MinMaxVectorSetTy MinMaxAliasGroups;
+
   /// Create the static control part with a region, max loop depth of this
   /// region and parameters used in this region.
   Scop(TempScop &TempScop, LoopInfo &LI, ScalarEvolution &SE, isl_ctx *ctx);
@@ -563,9 +589,13 @@ class Scop {
                  // The scattering numbers
                  SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI);
 
-  /// Helper function for printing the Scop.
+  /// @name Helper function for printing the Scop.
+  ///
+  ///{
   void printContext(raw_ostream &OS) const;
   void printStatements(raw_ostream &OS) const;
+  void printAliasAssumptions(raw_ostream &OS) const;
+  ///}
 
   friend class ScopInfo;
 
@@ -664,6 +694,12 @@ public:
   ///            to hold.
   void addAssumption(__isl_take isl_set *Set);
 
+  /// @brief Build all alias groups for this SCoP.
+  void buildAliasGroups(AliasAnalysis &AA);
+
+  /// @brief Return all alias groups for this SCoP.
+  const MinMaxVectorSetTy &getAliasGroups() const { return MinMaxAliasGroups; }
+
   /// @brief Get an isl string representing the context.
   std::string getContextStr() const;
 
diff --git a/include/polly/Support/GICHelper.h b/include/polly/Support/GICHelper.h
index 39c2336..c5fb4a1 100755
--- a/include/polly/Support/GICHelper.h
+++ b/include/polly/Support/GICHelper.h
@@ -65,6 +65,12 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
   return OS;
 }
 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                                     __isl_keep isl_pw_multi_aff *PMA) {
+  OS << polly::stringFromIslObj(PMA);
+  return OS;
+}
+
 /// @brief Return @p Prefix + @p Val->getName() + @p Suffix but Isl compatible.
 std::string getIslCompatibleName(std::string Prefix, const llvm::Value *Val,
                                  std::string Suffix);
diff --git a/lib/Analysis/ScopDetection.cpp b/lib/Analysis/ScopDetection.cpp
index 75d6731..ed191f0 100644
--- a/lib/Analysis/ScopDetection.cpp
+++ b/lib/Analysis/ScopDetection.cpp
@@ -184,6 +184,23 @@ void DiagnosticScopFound::print(DiagnosticPrinter &DP) const {
 //===----------------------------------------------------------------------===//
 // ScopDetection.
 
+ScopDetection::ScopDetection() : FunctionPass(ID) {
+  if (!PollyUseRuntimeAliasChecks)
+    return;
+
+  if (PollyDelinearize) {
+    DEBUG(errs() << "WARNING: We disable runtime alias checks as "
+                    "delinearization is enabled.\n");
+    PollyUseRuntimeAliasChecks = false;
+  }
+
+  if (AllowNonAffine) {
+    DEBUG(errs() << "WARNING: We disable runtime alias checks as non affine "
+                    "accesses are enabled.\n");
+    PollyUseRuntimeAliasChecks = false;
+  }
+}
+
 template <class RR, typename... Args>
 inline bool ScopDetection::invalid(DetectionContext &Context, bool Assert,
                                    Args &&... Arguments) const {
@@ -464,7 +481,7 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
   if (IntToPtrInst *Inst = dyn_cast<IntToPtrInst>(BaseValue))
     return invalid<ReportIntToPtr>(Context, /*Assert=*/true, Inst);
 
-  if (IgnoreAliasing)
+  if (PollyUseRuntimeAliasChecks || IgnoreAliasing)
     return true;
 
   // Check if the base pointer of the memory access does alias with
diff --git a/lib/Analysis/ScopInfo.cpp b/lib/Analysis/ScopInfo.cpp
index 963aa80..317e8a3 100644
--- a/lib/Analysis/ScopInfo.cpp
+++ b/lib/Analysis/ScopInfo.cpp
@@ -29,6 +29,7 @@
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/RegionIterator.h"
 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
 #include "llvm/Support/Debug.h"
@@ -63,6 +64,13 @@ static cl::opt<bool> DisableMultiplicativeReductions(
     cl::desc("Disable multiplicative reductions"), cl::Hidden, cl::ZeroOrMore,
     cl::init(false), cl::cat(PollyCategory));
 
+bool polly::PollyUseRuntimeAliasChecks;
+static cl::opt<bool, true> XPollyUseRuntimeAliasChecks(
+    "polly-use-runtime-alias-checks",
+    cl::desc("Use runtime alias checks to resolve possible aliasing."),
+    cl::location(PollyUseRuntimeAliasChecks), cl::Hidden, cl::ZeroOrMore,
+    cl::init(false), cl::cat(PollyCategory));
+
 /// Translate a 'const SCEV *' expression in an isl_pw_aff.
 struct SCEVAffinator : public SCEVVisitor<SCEVAffinator, isl_pw_aff *> {
 public:
@@ -1118,6 +1126,85 @@ void Scop::simplifyAssumedContext() {
       isl_set_gist_params(AssumedContext, isl_union_set_params(getDomains()));
 }
 
+/// @brief Add the minimal/maximal access in @p Set to @p User.
+static int buildMinMaxAccess(__isl_take isl_set *Set, void *User) {
+  Scop::MinMaxVectorTy *MinMaxAccesses = (Scop::MinMaxVectorTy *)User;
+  isl_pw_multi_aff *MinPMA, *MaxPMA;
+
+  MinPMA = isl_set_lexmin_pw_multi_aff(isl_set_copy(Set));
+  MaxPMA = isl_set_lexmax_pw_multi_aff(isl_set_copy(Set));
+
+  MinMaxAccesses->push_back(std::make_pair(MinPMA, MaxPMA));
+
+  isl_set_free(Set);
+  return 0;
+}
+
+void Scop::buildAliasGroups(AliasAnalysis &AA) {
+  // To create sound alias checks we perform the following steps:
+  //   o) Use the alias analysis and an alias set tracker to build alias sets
+  //      for all memory accesses inside the SCoP.
+  //   o) For each alias set we then map the aliasing pointers back to the
+  //      memory accesses we know, thus obtain groups of memory accesses which
+  //      might alias.
+  //   o) For each group with more then one base pointer we then compute minimal
+  //      and maximal accesses to each array in this group.
+  using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
+
+  AliasSetTracker AST(AA);
+
+  DenseMap<Value *, MemoryAccess *> PtrToAcc;
+  for (ScopStmt *Stmt : *this) {
+    for (MemoryAccess *MA : *Stmt) {
+      Instruction *Acc = MA->getAccessInstruction();
+      PtrToAcc[getPointerOperand(*Acc)] = MA;
+      AST.add(Acc);
+    }
+  }
+
+  SmallVector<AliasGroupTy, 4> AliasGroups;
+  for (AliasSet &AS : AST) {
+    if (AS.isMustAlias())
+      continue;
+    AliasGroupTy AG;
+    for (auto PR : AS)
+      AG.push_back(PtrToAcc[PR.getValue()]);
+    assert(AG.size() > 1 &&
+           "Alias groups should contain at least two accesses");
+    AliasGroups.push_back(std::move(AG));
+  }
+
+  SmallPtrSet<const Value *, 4> BaseValues;
+  for (auto I = AliasGroups.begin(); I != AliasGroups.end();) {
+    BaseValues.clear();
+    for (MemoryAccess *MA : *I)
+      BaseValues.insert(MA->getBaseAddr());
+    if (BaseValues.size() > 1)
+      I++;
+    else
+      I = AliasGroups.erase(I);
+  }
+
+  for (AliasGroupTy &AG : AliasGroups) {
+    MinMaxVectorTy *MinMaxAccesses = new MinMaxVectorTy();
+    MinMaxAccesses->reserve(AG.size());
+
+    isl_union_map *Accesses = isl_union_map_empty(getParamSpace());
+    for (MemoryAccess *MA : AG)
+      Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation());
+    Accesses = isl_union_map_intersect_domain(Accesses, getDomains());
+
+    isl_union_set *Locations = isl_union_map_range(Accesses);
+    Locations = isl_union_set_intersect_params(Locations, getAssumedContext());
+    Locations = isl_union_set_coalesce(Locations);
+    Locations = isl_union_set_detect_equalities(Locations);
+    isl_union_set_foreach_set(Locations, buildMinMaxAccess, MinMaxAccesses);
+    isl_union_set_free(Locations);
+
+    MinMaxAliasGroups.insert(MinMaxAccesses);
+  }
+}
+
 Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution,
            isl_ctx *Context)
     : SE(&ScalarEvolution), R(tempScop.getMaxRegion()),
@@ -1148,6 +1235,13 @@ Scop::~Scop() {
   // Free the statements;
   for (ScopStmt *Stmt : *this)
     delete Stmt;
+
+  // Free the alias groups
+  for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
+    for (MinMaxAccessTy &MMA : *MinMaxAccesses)
+      isl_pw_multi_aff_free(MMA.first) || isl_pw_multi_aff_free(MMA.second);
+    delete MinMaxAccesses;
+  }
 }
 
 std::string Scop::getContextStr() const { return stringFromIslObj(Context); }
@@ -1209,6 +1303,20 @@ void Scop::printContext(raw_ostream &OS) const {
   }
 }
 
+void Scop::printAliasAssumptions(raw_ostream &OS) const {
+  OS.indent(4) << "Alias Groups (" << MinMaxAliasGroups.size() << "):\n";
+  if (MinMaxAliasGroups.empty()) {
+    OS.indent(8) << "n/a\n";
+    return;
+  }
+  for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
+    OS.indent(8) << "[[";
+    for (MinMaxAccessTy &MinMacAccess : *MinMaxAccesses)
+      OS << " <" << MinMacAccess.first << ", " << MinMacAccess.second << ">";
+    OS << " ]]\n";
+  }
+}
+
 void Scop::printStatements(raw_ostream &OS) const {
   OS << "Statements {\n";
 
@@ -1223,6 +1331,7 @@ void Scop::print(raw_ostream &OS) const {
                << "\n";
   OS.indent(4) << "Region: " << getNameStr() << "\n";
   printContext(OS.indent(4));
+  printAliasAssumptions(OS);
   printStatements(OS.indent(4));
 }
 
@@ -1409,11 +1518,13 @@ void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.addRequired<RegionInfoPass>();
   AU.addRequired<ScalarEvolution>();
   AU.addRequired<TempScopInfo>();
+  AU.addRequired<AliasAnalysis>();
   AU.setPreservesAll();
 }
 
 bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
   LoopInfo &LI = getAnalysis<LoopInfo>();
+  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
   ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
 
   TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R);
@@ -1431,6 +1542,9 @@ bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
 
   scop = new Scop(*tempScop, LI, SE, ctx);
 
+  if (PollyUseRuntimeAliasChecks)
+    scop->buildAliasGroups(AA);
+
   return false;
 }
 
@@ -1441,6 +1555,7 @@ Pass *polly::createScopInfoPass() { return new ScopInfo(); }
 INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops",
                       "Polly - Create polyhedral description of Scops", false,
                       false);
+INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
 INITIALIZE_PASS_DEPENDENCY(LoopInfo);
 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
 INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
diff --git a/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll b/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll
new file mode 100644
index 0000000..01b1b55
--- /dev/null
+++ b/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll
@@ -0,0 +1,41 @@
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed -polly-codegen-isl -instnamer < %s -S | FileCheck %s
+;
+;float A[100];
+;
+;int codegen_simple () {
+;  for (int i = 0; i < 12; i++)
+;    A[13] = A[i] + A[i-1];
+;
+;  return 0;
+;}
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+
+ at A = common global [100 x float] zeroinitializer, align 4
+
+define i32 @codegen_simple() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %tmp1 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %tmp = add i32 %tmp1, -1
+  %arrayidx4 = getelementptr [100 x float]* @A, i32 0, i32 %tmp
+  %arrayidx = getelementptr [100 x float]* @A, i32 0, i32 %tmp1
+  %exitcond = icmp ne i32 %tmp1, 12
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp2 = load float* %arrayidx, align 4
+  %tmp5 = load float* %arrayidx4, align 4
+  %add = fadd float %tmp2, %tmp5
+  store float %add, float* getelementptr inbounds ([100 x float]* @A, i32 0, i32 13), align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %tmp1, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret i32 0
+}
+; CHECK: load float* getelementptr inbounds ([100 x float]* @A, i64 0, i64 0)
diff --git a/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll b/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll
new file mode 100644
index 0000000..01bd46d
--- /dev/null
+++ b/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll
@@ -0,0 +1,71 @@
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen-isl < %s -S | FileCheck -check-prefix=WITHOUTCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withconst -polly-codegen-isl -polly-codegen-scev < %s -S | FileCheck -check-prefix=WITHCONST %s
+;RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-dir=%S -polly-import-jscop-postfix=transformed+withoutconst -polly-codegen-isl -polly-codegen-scev < %s -S | FileCheck -check-prefix=WITHOUTCONST %s
+;
+;float A[1040];
+;
+;int codegen_simple_md() {
+;  for (int i = 0; i < 32; ++i)
+;    for (int j = 0; j < 32; ++j)
+;      A[32*i+j] = 100;
+;}
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+
+ at A = common global [1040 x float] zeroinitializer, align 4
+
+define void @codegen_simple_md() nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %exitcond1 = icmp ne i32 %i.0, 32
+  br i1 %exitcond1, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, 32
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  %mul = shl nsw i32 %i.0, 5
+  %add = add nsw i32 %mul, %j.0
+  %arrayidx = getelementptr inbounds [1040 x float]* @A, i32 0, i32 %add
+  store float 100.0, float* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret void
+}
+
+; WITHCONST:  %[[IVOut:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHCONST:  %[[IVIn:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHCONST:  %[[MUL1:[._a-zA-Z0-9]+]] = mul nsw i64 16, %[[IVOut]]
+; WITHCONST:  %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
+; WITHCONST:  %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
+; WITHCONST:  %[[SUM2:[._a-zA-Z0-9]+]] = add nsw i64 %[[SUM1]], 5
+; WITHCONST:  %[[ACC:[._a-zA-Z0-9]*]] = getelementptr [1040 x float]* @A, i64 0, i64 %[[SUM2]]
+; WITHCONST:  store float 1.000000e+02, float* %[[ACC]]
+
+; WITHOUTCONST:  %[[IVOut:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHOUTCONST:  %[[IVIn:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
+; WITHOUTCONST:  %[[MUL1:[._a-zA-Z0-9]+]] = mul nsw i64 16, %[[IVOut]]
+; WITHOUTCONST:  %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
+; WITHOUTCONST:  %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
+; WITHOUTCONST:  %[[ACC:[._a-zA-Z0-9]*]] = getelementptr [1040 x float]* @A, i64 0, i64 %[[SUM1]]
+; WITHOUTCONST:  store float 1.000000e+02, float* %[[ACC]]
diff --git a/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop b/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop
new file mode 100644
index 0000000..88fafec
--- /dev/null
+++ b/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop
@@ -0,0 +1,28 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end14",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body7[i0] -> MemRef_B[i0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body7[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body7",
+         "schedule" : "{ Stmt_for_body7[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed b/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed
new file mode 100644
index 0000000..b1808f1
--- /dev/null
+++ b/test/Isl/CodeGen/MemAccess/simple___%for.cond---%for.end14.jscop.transformed
@@ -0,0 +1,28 @@
+{
+   "context" : "{  :  }",
+   "name" : "for.cond => for.end14",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body[i0] -> MemRef_A[0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body",
+         "schedule" : "{ Stmt_for_body[i0] -> scattering[0, i0, 0] }"
+      },
+      {
+         "accesses" : [
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_for_body7[i0] -> MemRef_B[0] }"
+            }
+         ],
+         "domain" : "{ Stmt_for_body7[i0] : i0 >= 0 and i0 <= 11 }",
+         "name" : "Stmt_for_body7",
+         "schedule" : "{ Stmt_for_body7[i0] -> scattering[0, i0, 0] }"
+      }
+   ]
+}
diff --git a/test/ScopDetect/aliasing_parametric_simple_1.ll b/test/ScopDetect/aliasing_parametric_simple_1.ll
new file mode 100644
index 0000000..a5fdfdb
--- /dev/null
+++ b/test/ScopDetect/aliasing_parametric_simple_1.ll
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-use-runtime-alias-checks=true -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop:
+;
+;    void jd(int *A, int *B, int c) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[c];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32 %c) {
+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
+  %idxprom = sext i32 %c to i64
+  %arrayidx = getelementptr inbounds i32* %B, i64 %idxprom
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, 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
+}
diff --git a/test/ScopDetect/aliasing_parametric_simple_2.ll b/test/ScopDetect/aliasing_parametric_simple_2.ll
new file mode 100644
index 0000000..f518d68
--- /dev/null
+++ b/test/ScopDetect/aliasing_parametric_simple_2.ll
@@ -0,0 +1,39 @@
+; RUN: opt %loadPolly -polly-use-runtime-alias-checks=true -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop:
+;
+;    void jd(int *A, int *B, int c) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[c - 10] + B[5];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %B, i32 %c) {
+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
+  %sub = add nsw i32 %c, -10
+  %idxprom = sext i32 %sub to i64
+  %arrayidx = getelementptr inbounds i32* %B, i64 %idxprom
+  %tmp = load i32* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds i32* %B, i64 5
+  %tmp1 = load i32* %arrayidx1, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  %arrayidx3 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  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
+}
diff --git a/test/ScopDetect/aliasing_simple_1.ll b/test/ScopDetect/aliasing_simple_1.ll
new file mode 100644
index 0000000..9009111
--- /dev/null
+++ b/test/ScopDetect/aliasing_simple_1.ll
@@ -0,0 +1,33 @@
+; RUN: opt %loadPolly -polly-use-runtime-alias-checks=true -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop:
+;
+;    void jd(int *A, int *B) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[0];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %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
+  %tmp = load i32* %B, align 4
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, 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
+}
diff --git a/test/ScopDetect/aliasing_simple_2.ll b/test/ScopDetect/aliasing_simple_2.ll
new file mode 100644
index 0000000..5db8e6f
--- /dev/null
+++ b/test/ScopDetect/aliasing_simple_2.ll
@@ -0,0 +1,36 @@
+; RUN: opt %loadPolly -polly-use-runtime-alias-checks=true -polly-detect -analyze < %s | FileCheck %s
+;
+; CHECK: Valid Region for Scop:
+;
+;    void jd(int *A, int *B) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i] = B[0] + B[1023];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* %A, i32* %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
+  %tmp = load i32* %B, align 4
+  %arrayidx1 = getelementptr inbounds i32* %B, i64 1023
+  %tmp1 = load i32* %arrayidx1, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  %arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %add, i32* %arrayidx2, 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
+}
diff --git a/test/ScopInfo/Alias-0.ll b/test/ScopInfo/Alias-0.ll
index 8474131..3d64e8d 100755
--- a/test/ScopInfo/Alias-0.ll
+++ b/test/ScopInfo/Alias-0.ll
@@ -1,4 +1,5 @@
-; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=true -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
 ; REQUIRES: asserts
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
@@ -32,4 +33,5 @@ return:                                           ; preds = %bb3
 declare i32 @rnd(...)
 
 
-; CHECK: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/test/ScopInfo/Alias-1.ll b/test/ScopInfo/Alias-1.ll
index c8f0093..c33f73d 100755
--- a/test/ScopInfo/Alias-1.ll
+++ b/test/ScopInfo/Alias-1.ll
@@ -1,4 +1,5 @@
-; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=true -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
 ; REQUIRES: asserts
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
@@ -33,4 +34,5 @@ return:                                           ; preds = %bb3
 declare i32 @rnd(...)
 
 
-; CHECK: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/test/ScopInfo/Alias-2.ll b/test/ScopInfo/Alias-2.ll
index 3a70bf4..0be3e73 100755
--- a/test/ScopInfo/Alias-2.ll
+++ b/test/ScopInfo/Alias-2.ll
@@ -1,4 +1,5 @@
-; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=true -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
 ; REQUIRES: asserts
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
@@ -31,4 +32,5 @@ return:                                           ; preds = %bb
   ret void
 }
 
-; CHECK: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/test/ScopInfo/Alias-3.ll b/test/ScopInfo/Alias-3.ll
index 7ad9ad6..89d0140 100755
--- a/test/ScopInfo/Alias-3.ll
+++ b/test/ScopInfo/Alias-3.ll
@@ -1,4 +1,5 @@
-; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=true -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
 ; REQUIRES: asserts
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
@@ -24,4 +25,5 @@ return:                                           ; preds = %bb
 }
 
 
-; CHECK: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/test/ScopInfo/Alias-4.ll b/test/ScopInfo/Alias-4.ll
index a47f799..92fd76e 100755
--- a/test/ScopInfo/Alias-4.ll
+++ b/test/ScopInfo/Alias-4.ll
@@ -1,4 +1,5 @@
-; RUN: opt %loadPolly -basicaa -polly-analyze-ir -analyze < %s -stats 2>&1 | not FileCheck %s
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=true -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
+; RUN: opt %loadPolly -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
 ; REQUIRES: asserts
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
@@ -24,4 +25,5 @@ return:                                           ; preds = %bb
 }
 
 
-; CHECK:  Found base address alias
+; RTA:   1 polly-detect     - Number of regions that a valid part of Scop
+; NORTA: 1 polly-detect     - Number of bad regions for Scop: Found base address alias
diff --git a/test/ScopInfo/aliasing_multiple_alias_groups.ll b/test/ScopInfo/aliasing_multiple_alias_groups.ll
new file mode 100644
index 0000000..24d7f86
--- /dev/null
+++ b/test/ScopInfo/aliasing_multiple_alias_groups.ll
@@ -0,0 +1,52 @@
+; RUN: opt %loadPolly -polly-use-runtime-alias-checks=true -polly-scops -analyze          < %s | FileCheck %s --check-prefix=NOAA
+; RUN: opt %loadPolly -polly-use-runtime-alias-checks=true -polly-scops -analyze -tbaa    < %s | FileCheck %s --check-prefix=TBAA
+;
+;    void jd(int *Int0, int *Int1, float *Float0, float *Float1) {
+;      for (int i = 0; i < 1024; i++) {
+;        Int0[i] = Int1[i];
+;        Float0[i] = Float1[i];
+;      }
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @jd(i32* nocapture %Int0, i32* nocapture readonly %Int1, float* nocapture %Float0, float* nocapture readonly %Float1) {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+  %arrayidx = getelementptr inbounds i32* %Int1, i64 %indvars.iv
+  %tmp = load i32* %arrayidx, align 4, !tbaa !0
+  %arrayidx2 = getelementptr inbounds i32* %Int0, i64 %indvars.iv
+  store i32 %tmp, i32* %arrayidx2, align 4, !tbaa !0
+  %arrayidx4 = getelementptr inbounds float* %Float1, i64 %indvars.iv
+  %tmp1 = load float* %arrayidx4, align 4, !tbaa !4
+  %arrayidx6 = getelementptr inbounds float* %Float0, i64 %indvars.iv
+  store float %tmp1, float* %arrayidx6, align 4, !tbaa !4
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 1024
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+!0 = metadata !{metadata !1, metadata !1, i64 0}
+!1 = metadata !{metadata !"int", metadata !2, i64 0}
+!2 = metadata !{metadata !"omnipotent char", metadata !3, i64 0}
+!3 = metadata !{metadata !"Simple C/C++ TBAA"}
+!4 = metadata !{metadata !5, metadata !5, i64 0}
+!5 = metadata !{metadata !"float", metadata !2, i64 0}
+
+; NOAA: Alias Groups (1):
+; NOAA-DAG:      <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1023)] }>
+; NOAA-DAG:      <{ MemRef_Int1[(0)] }, { MemRef_Int1[(1023)] }>
+; NOAA-DAG:      <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1023)] }>
+; NOAA-DAG:      <{ MemRef_Float1[(0)] }, { MemRef_Float1[(1023)] }>
+
+; TBAA-DAG: Alias Groups (2):
+; TBAA-DAG:      <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1023)] }>
+; TBAA-DAG:      <{ MemRef_Int1[(0)] }, { MemRef_Int1[(1023)] }>
+; TBAA-DAG:      <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1023)] }>
+; TBAA-DAG:      <{ MemRef_Float1[(0)] }, { MemRef_Float1[(1023)] }>
-- 
2.0.4




More information about the llvm-commits mailing list