[llvm-commits] [polly] r167214 - in /polly/trunk: include/polly/CodeGen/Cloog.h lib/CodeGen/Cloog.cpp lib/CodeGen/CodeGeneration.cpp test/CodeGen/OpenMP/copy_in_argument.ll test/CodeGen/OpenMP/copy_in_temporary.ll test/CodeGen/OpenMP/param_referenced_in_stmt.ll

Tobias Grosser grosser at fim.uni-passau.de
Wed Oct 31 22:34:49 PDT 2012


Author: grosser
Date: Thu Nov  1 00:34:48 2012
New Revision: 167214

URL: http://llvm.org/viewvc/llvm-project?rev=167214&view=rev
Log:
CodeGen: Add scop-parameters to the OpenMP context

In addition to the arrays and clast variables a SCoP statement may also refer to
values defined before the SCoP or to function arguments. Detect these values and
add them to the set of values passed to the function generated for OpenMP
parallel execution of a clast.

Committed with additional test cases and some refactoring.

Contributed by:  Armin Groesslinger  <armin.groesslinger at uni-passau.de>

Added:
    polly/trunk/test/CodeGen/OpenMP/copy_in_argument.ll
    polly/trunk/test/CodeGen/OpenMP/copy_in_temporary.ll
    polly/trunk/test/CodeGen/OpenMP/param_referenced_in_stmt.ll
Modified:
    polly/trunk/include/polly/CodeGen/Cloog.h
    polly/trunk/lib/CodeGen/Cloog.cpp
    polly/trunk/lib/CodeGen/CodeGeneration.cpp

Modified: polly/trunk/include/polly/CodeGen/Cloog.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/CodeGen/Cloog.h?rev=167214&r1=167213&r2=167214&view=diff
==============================================================================
--- polly/trunk/include/polly/CodeGen/Cloog.h (original)
+++ polly/trunk/include/polly/CodeGen/Cloog.h Thu Nov  1 00:34:48 2012
@@ -64,6 +64,21 @@
     virtual void getAnalysisUsage(AnalysisUsage &AU) const;
     virtual void releaseMemory();
   };
+
+  // Visitor class for clasts.
+  // Only 'visitUser' has to be implemented by subclasses; the default
+  // implementations of the other methods traverse the clast recursively.
+  class ClastVisitor {
+  public:
+    virtual void visit(const clast_stmt *stmt);
+
+    virtual void visitAssignment(const clast_assignment *stmt);
+    virtual void visitBlock(const clast_block *stmt);
+    virtual void visitFor(const clast_for *stmt);
+    virtual void visitGuard(const clast_guard *stmt);
+
+    virtual void visitUser(const clast_user_stmt *stmt) = 0;
+  };
 }
 
 namespace llvm {

Modified: polly/trunk/lib/CodeGen/Cloog.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/Cloog.cpp?rev=167214&r1=167213&r2=167214&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/Cloog.cpp (original)
+++ polly/trunk/lib/CodeGen/Cloog.cpp Thu Nov  1 00:34:48 2012
@@ -217,6 +217,40 @@
   CloogInput *Input = cloog_input_alloc(Context, Statements);
   return Input;
 }
+
+void ClastVisitor::visit(const clast_stmt *stmt) {
+  if      (CLAST_STMT_IS_A(stmt, stmt_root))
+    assert(false && "No second root statement expected");
+  else if (CLAST_STMT_IS_A(stmt, stmt_ass))
+    return visitAssignment((const clast_assignment *)stmt);
+  else if (CLAST_STMT_IS_A(stmt, stmt_user))
+    return visitUser((const clast_user_stmt *)stmt);
+  else if (CLAST_STMT_IS_A(stmt, stmt_block))
+    return visitBlock((const clast_block *)stmt);
+  else if (CLAST_STMT_IS_A(stmt, stmt_for))
+    return visitFor((const clast_for *)stmt);
+  else if (CLAST_STMT_IS_A(stmt, stmt_guard))
+    return visitGuard((const clast_guard *)stmt);
+
+  if (stmt->next)
+    visit(stmt->next);
+}
+
+void ClastVisitor::visitAssignment(const clast_assignment *stmt) {
+}
+
+void ClastVisitor::visitBlock(const clast_block *stmt) {
+  visit(stmt->body);
+}
+
+void ClastVisitor::visitFor(const clast_for *stmt) {
+  visit(stmt->body);
+}
+
+void ClastVisitor::visitGuard(const clast_guard *stmt) {
+  visit(stmt->then);
+}
+
 } // End namespace polly.
 
 namespace {

Modified: polly/trunk/lib/CodeGen/CodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/CodeGeneration.cpp?rev=167214&r1=167213&r2=167214&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGen/CodeGeneration.cpp Thu Nov  1 00:34:48 2012
@@ -283,7 +283,7 @@
   ///
   /// Create a list of values that has to be stored into the OpenMP subfuncition
   /// structure.
-  SetVector<Value*> getOMPValues();
+  SetVector<Value*> getOMPValues(const clast_stmt *Body);
 
   /// @brief Update ClastVars and ValueMap according to a value map.
   ///
@@ -461,7 +461,42 @@
   Builder.SetInsertPoint(AfterBB->begin());
 }
 
-SetVector<Value*> ClastStmtCodeGen::getOMPValues() {
+// Helper class to determine all scalar parameters used in the basic blocks of a
+// clast. Scalar parameters are scalar variables defined outside of the SCoP.
+class ParameterVisitor : public ClastVisitor {
+  std::set<Value *> Values;
+public:
+  ParameterVisitor() : ClastVisitor(), Values() { }
+
+  void visitUser(const clast_user_stmt *Stmt) {
+    const ScopStmt *S = static_cast<const ScopStmt *>(Stmt->statement->usr);
+    const BasicBlock *BB = S->getBasicBlock();
+
+    // Check all the operands of instructions in the basic block.
+    for (BasicBlock::const_iterator BI = BB->begin(), BE = BB->end(); BI != BE;
+         ++BI) {
+      const Instruction &Inst = *BI;
+      for (Instruction::const_op_iterator II = Inst.op_begin(),
+           IE = Inst.op_end(); II != IE; ++II) {
+        Value *SrcVal = *II;
+
+        if (Instruction *OpInst = dyn_cast<Instruction>(SrcVal))
+          if (S->getParent()->getRegion().contains(OpInst))
+            continue;
+
+        if (isa<Instruction>(SrcVal) || isa<Argument>(SrcVal))
+          Values.insert(SrcVal);
+      }
+    }
+  }
+
+  // Iterator to iterate over the values found.
+  typedef std::set<Value *>::const_iterator const_iterator;
+  inline const_iterator begin() const { return Values.begin(); }
+  inline const_iterator end()   const { return Values.end();   }
+};
+
+SetVector<Value*> ClastStmtCodeGen::getOMPValues(const clast_stmt *Body) {
   SetVector<Value*> Values;
 
   // The clast variables
@@ -479,6 +514,20 @@
     }
   }
 
+  // Find the temporaries that are referenced in the clast statements'
+  // basic blocks but are not defined by these blocks (e.g., references
+  // to function arguments or temporaries defined before the start of
+  // the SCoP).
+  ParameterVisitor Params;
+  Params.visit(Body);
+
+  for (ParameterVisitor::const_iterator PI = Params.begin(), PE = Params.end();
+       PI != PE; ++PI) {
+    Value *V = *PI;
+    Values.insert(V);
+    DEBUG(dbgs() << "Adding temporary for OMP copy-in: " << *V << "\n");
+  }
+
   return Values;
 }
 
@@ -525,7 +574,7 @@
   LB = ExpGen.codegen(For->LB, IntPtrTy);
   UB = ExpGen.codegen(For->UB, IntPtrTy);
 
-  Values = getOMPValues();
+  Values = getOMPValues(For->body);
 
   IV = OMPGen.createParallelLoop(LB, UB, Stride, Values, VMap, &LoopBody);
   BasicBlock::iterator AfterLoop = Builder.GetInsertPoint();

Added: polly/trunk/test/CodeGen/OpenMP/copy_in_argument.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/CodeGen/OpenMP/copy_in_argument.ll?rev=167214&view=auto
==============================================================================
--- polly/trunk/test/CodeGen/OpenMP/copy_in_argument.ll (added)
+++ polly/trunk/test/CodeGen/OpenMP/copy_in_argument.ll Thu Nov  1 00:34:48 2012
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-codegen -enable-polly-openmp -S %s | FileCheck %s
+;
+; 'arg' has the same type as A[i], i.e., the function argument has to be
+; copied to the function generated for the loop.
+;
+; float A[100];
+; void copy_in_test(float arg) {
+;     long i;
+;     for (i=0; i<100; ++i)
+;         A[i] = arg;
+; }
+
+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-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at A = common global [100 x float] zeroinitializer, align 16
+
+define void @copy_in_test(float %arg) nounwind uwtable {
+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 [100 x float]* @A, i64 0, i64 %indvars.iv
+  store float %arg, float* %arrayidx
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 100
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+; CHECK: %omp.userContext = alloca { [100 x float]*, float }

Added: polly/trunk/test/CodeGen/OpenMP/copy_in_temporary.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/CodeGen/OpenMP/copy_in_temporary.ll?rev=167214&view=auto
==============================================================================
--- polly/trunk/test/CodeGen/OpenMP/copy_in_temporary.ll (added)
+++ polly/trunk/test/CodeGen/OpenMP/copy_in_temporary.ll Thu Nov  1 00:34:48 2012
@@ -0,0 +1,35 @@
+; RUN: opt %loadPolly -polly-codegen -enable-polly-openmp -S %s | FileCheck %s
+;
+; 'arg' is converted to float before the loop, so the corresponding temporary
+; has to be copied to the function generated for the loop.
+;
+; float A[100];
+; void copy_in_test(long arg) {
+;   long i;
+;   for (i=0; i<100; ++i)
+;     A[i] = arg;
+; }
+
+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-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at A = common global [100 x float] zeroinitializer, align 16
+
+define void @copy_in_test(i64 %arg) nounwind uwtable {
+entry:
+  %conv = sitofp i64 %arg to float
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+  %arrayidx = getelementptr inbounds [100 x float]* @A, i64 0, i64 %indvars.iv
+  store float %conv, float* %arrayidx
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 100
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+; CHECK: %omp.userContext = alloca { [100 x float]*, float }

Added: polly/trunk/test/CodeGen/OpenMP/param_referenced_in_stmt.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/CodeGen/OpenMP/param_referenced_in_stmt.ll?rev=167214&view=auto
==============================================================================
--- polly/trunk/test/CodeGen/OpenMP/param_referenced_in_stmt.ll (added)
+++ polly/trunk/test/CodeGen/OpenMP/param_referenced_in_stmt.ll Thu Nov  1 00:34:48 2012
@@ -0,0 +1,38 @@
+; RUN: opt %loadPolly -polly-codegen %s -enable-polly-openmp -S | FileCheck %s
+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-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+
+; This test case implements the following code:
+;
+; for (i = 0; i < 1024; i++)
+;   A[i] = A[i] * param
+;
+; The problem is that 'param' is not references in any subscript of loop
+; bound, but it must still be forwarded to the OpenMP subfunction.
+
+define void @foo(double %param, [1024 x double]* %A) {
+entry:
+  br label %for.preheader
+
+for.preheader:
+  br label %for.body
+
+for.body:
+  %indvar = phi i64 [ 0, %for.preheader ], [ %indvar.next, %for.inc ]
+  %arrayidx = getelementptr [1024 x double]* %A, i64 0, i64 %indvar
+  %val = load double* %arrayidx
+  %mul = fmul double %param, %val
+  store double %mul, double* %arrayidx, align 8
+  br label %for.inc
+
+for.inc:
+  %indvar.next = add i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, 1024
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:
+  ret void
+}
+
+; CHECK: omp_subfn





More information about the llvm-commits mailing list