[Refactor] Remove containsLoop to find innermost loops

Use the fact that if we visit a for node first in pre and next in post order
  we know we did not visit any children, thus we found an innermost loop.

  + Test case for an innermost loop with a conditional inside

llvm-svn: 213870
This commit is contained in:
Johannes Doerfert 2014-07-24 15:59:06 +00:00
parent fb3d5d1750
commit af9b1e2d80
2 changed files with 28 additions and 54 deletions

View File

@ -84,13 +84,20 @@ IslAstInfo::IslAstUserPayload::~IslAstUserPayload() {
isl_ast_build_free(Build);
}
// Temporary information used when building the ast.
/// @brief Temporary information used when building the ast.
struct AstBuildUserInfo {
// The dependence information.
/// @brief Construct and initialize the helper struct for AST creation.
AstBuildUserInfo()
: Deps(nullptr), InParallelFor(false), LastForNodeId(nullptr) {}
/// @brief The dependence information used for the parallelism check.
Dependences *Deps;
// We are inside a parallel for node.
int InParallelFor;
/// @brief Flag to indicate that we are inside a parallel for node.
bool InParallelFor;
/// @brief The last iterator id created for the current SCoP.
isl_id *LastForNodeId;
};
// Print a loop annotated with OpenMP or vector pragmas.
@ -237,52 +244,13 @@ static __isl_give isl_id *astBuildBeforeFor(__isl_keep isl_ast_build *Build,
IslAstUserPayload *NodeInfo = new IslAstUserPayload();
isl_id *Id = isl_id_alloc(isl_ast_build_get_ctx(Build), "", NodeInfo);
Id = isl_id_set_free_user(Id, freeIslAstUserPayload);
BuildInfo->LastForNodeId = Id;
markOpenmpParallel(Build, BuildInfo, NodeInfo);
return Id;
}
// Returns 0 when Node contains loops, otherwise returns -1. This search
// function uses ISL's way to iterate over lists of isl_ast_nodes with
// isl_ast_node_list_foreach. Please use the single argument wrapper function
// that returns a bool instead of using this function directly.
static int containsLoops(__isl_take isl_ast_node *Node, void *User) {
if (!Node)
return -1;
switch (isl_ast_node_get_type(Node)) {
case isl_ast_node_for:
isl_ast_node_free(Node);
return 0;
case isl_ast_node_block: {
isl_ast_node_list *List = isl_ast_node_block_get_children(Node);
int Res = isl_ast_node_list_foreach(List, &containsLoops, nullptr);
isl_ast_node_list_free(List);
isl_ast_node_free(Node);
return Res;
}
case isl_ast_node_if: {
int Res = -1;
if (0 == containsLoops(isl_ast_node_if_get_then(Node), nullptr) ||
(isl_ast_node_if_has_else(Node) &&
0 == containsLoops(isl_ast_node_if_get_else(Node), nullptr)))
Res = 0;
isl_ast_node_free(Node);
return Res;
}
case isl_ast_node_user:
default:
isl_ast_node_free(Node);
return -1;
}
}
// Returns true when Node contains loops.
static bool containsLoops(__isl_take isl_ast_node *Node) {
return 0 == containsLoops(Node, nullptr);
}
// This method is executed after the construction of a for node.
//
// It performs the following actions:
@ -299,10 +267,12 @@ astBuildAfterFor(__isl_take isl_ast_node *Node, __isl_keep isl_ast_build *Build,
IslAstUserPayload *Info = (IslAstUserPayload *)isl_id_get_user(Id);
AstBuildUserInfo *BuildInfo = (AstBuildUserInfo *)User;
bool IsInnermost = (Id == BuildInfo->LastForNodeId);
if (Info) {
if (Info->IsOutermostParallel)
BuildInfo->InParallelFor = 0;
if (!containsLoops(isl_ast_node_for_get_body(Node)))
if (IsInnermost)
if (astScheduleDimIsParallel(Build, BuildInfo->Deps,
Info->IsReductionParallel))
Info->IsInnermostParallel = 1;

View File

@ -1,4 +1,16 @@
; RUN: opt %loadPolly %defaultOpts -polly-ast -analyze < %s | FileCheck %s
; RUN: opt %loadPolly %defaultOpts -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
; Verify that we actually detect this loop as the innermost loop even though
; there is a conditional inside.
; CHECK: #pragma simd
; CHECK: for (int c1 = 0; c1 <= 1023; c1 += 1) {
; CHECK: if (c1 >= m + 1025) {
; CHECK: Stmt_if_else(c1);
; CHECK: } else
; CHECK: Stmt_if_then(c1);
; CHECK: Stmt_if_end(c1);
; CHECK: }
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"
target triple = "x86_64-unknown-linux-gnu"
@ -127,11 +139,3 @@ return: ; preds = %for.end35, %if.then
}
declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
; CHECK: for (int c1 = 0; c1 <= 1023; c1 += 1) {
; CHECK: if (c1 >= m + 1025) {
; CHECK: Stmt_if_else(c1);
; CHECK: } else
; CHECK: Stmt_if_then(c1);
; CHECK: Stmt_if_end(c1);
; CHECK: }