diff options
4 files changed, 67 insertions, 14 deletions
diff --git a/polly/lib/CodeGen/IslAst.cpp b/polly/lib/CodeGen/IslAst.cpp index 4f79ea89cbd..5d16fda1612 100644 --- a/polly/lib/CodeGen/IslAst.cpp +++ b/polly/lib/CodeGen/IslAst.cpp @@ -81,6 +81,9 @@ static void IslAstUserFree(void *User) struct AstNodeUserInfo { // The node is the outermost parallel loop. int IsOutermostParallel; + + // The node is the innermost parallel loop. + int IsInnermostParallel; }; // Temporary information used when building the ast. @@ -92,16 +95,22 @@ struct AstBuildUserInfo { int InParallelFor; }; -// Print a loop annotated with OpenMP pragmas. +// Print a loop annotated with OpenMP or vector pragmas. static __isl_give isl_printer * printParallelFor(__isl_keep isl_ast_node *Node, __isl_take isl_printer *Printer, __isl_take isl_ast_print_options *PrintOptions, AstNodeUserInfo *Info) { - if (Info && Info->IsOutermostParallel) { - Printer = isl_printer_start_line(Printer); - if (Info->IsOutermostParallel) + if (Info) { + if (Info->IsInnermostParallel) { + Printer = isl_printer_start_line(Printer); + Printer = isl_printer_print_str(Printer, "#pragma simd"); + Printer = isl_printer_end_line(Printer); + } + if (Info->IsOutermostParallel) { + Printer = isl_printer_start_line(Printer); Printer = isl_printer_print_str(Printer, "#pragma omp parallel for"); - Printer = isl_printer_end_line(Printer); + Printer = isl_printer_end_line(Printer); + } } return isl_ast_node_for_print(Node, Printer, PrintOptions); } @@ -126,6 +135,7 @@ static struct AstNodeUserInfo *allocateAstNodeUserInfo() { struct AstNodeUserInfo *NodeInfo; NodeInfo = (struct AstNodeUserInfo *) malloc(sizeof(struct AstNodeUserInfo)); NodeInfo->IsOutermostParallel = 0; + NodeInfo->IsInnermostParallel = 0; return NodeInfo; } @@ -223,6 +233,46 @@ static __isl_give isl_id *astBuildBeforeFor(__isl_keep isl_ast_build *Build, 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, NULL); + 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), NULL) || + (isl_ast_node_if_has_else(Node) && + 0 == containsLoops(isl_ast_node_if_get_else(Node), NULL))) + 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, NULL); +} + // This method is executed after the construction of a for node. // // It performs the following actions: @@ -233,17 +283,17 @@ static __isl_give isl_id *astBuildBeforeFor(__isl_keep isl_ast_build *Build, static __isl_give isl_ast_node * astBuildAfterFor(__isl_take isl_ast_node *Node, __isl_keep isl_ast_build *Build, void *User) { - isl_id *Id; - struct AstBuildUserInfo *BuildInfo; - struct AstNodeUserInfo *Info; - - Id = isl_ast_node_get_annotation(Node); + isl_id *Id = isl_ast_node_get_annotation(Node); if (!Id) return Node; - Info = (struct AstNodeUserInfo *) isl_id_get_user(Id); - if (Info && Info->IsOutermostParallel) { - BuildInfo = (struct AstBuildUserInfo *) User; - BuildInfo->InParallelFor = 0; + struct AstNodeUserInfo *Info = (struct AstNodeUserInfo *) isl_id_get_user(Id); + struct AstBuildUserInfo *BuildInfo = (struct AstBuildUserInfo *) User; + if (Info) { + if (Info->IsOutermostParallel) + BuildInfo->InParallelFor = 0; + if (!containsLoops(isl_ast_node_for_get_body(Node))) + if (astScheduleDimIsParallel(Build, BuildInfo->Deps)) + Info->IsInnermostParallel = 1; } isl_id_free(Id); diff --git a/polly/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll b/polly/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll index b87610a8b26..1864937f382 100644 --- a/polly/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll +++ b/polly/test/Isl/Ast/OpenMP/nested_loop_both_parallel_parametric.ll @@ -50,6 +50,7 @@ ret: ; memory accesses, that would happen if n >= 1024. ; ; CHECK: for (int c1 = 0; c1 < n; c1 += 1) +; CHECK: #pragma simd ; CHECK: #pragma omp parallel for ; CHECK: for (int c3 = 0; c3 < n; c3 += 1) ; CHECK: Stmt_loop_body(c1, c3); diff --git a/polly/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll b/polly/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll index c530aaf6533..c92fb1d9743 100644 --- a/polly/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll +++ b/polly/test/Isl/Ast/OpenMP/nested_loop_inner_parallel.ll @@ -41,6 +41,7 @@ ret: } ; CHECK: for (int c1 = 0; c1 < n; c1 += 1) +; CHECK: #pragma simd ; CHECK: #pragma omp parallel for ; CHECK: for (int c3 = 0; c3 < n; c3 += 1) ; CHECK: Stmt_loop_body(c1, c3); diff --git a/polly/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll b/polly/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll index 499cfa7d27a..cbe48d8eefd 100644 --- a/polly/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll +++ b/polly/test/Isl/Ast/OpenMP/single_loop_param_parallel.ll @@ -30,6 +30,7 @@ ret: ret void } +; CHECK: #pragma simd ; CHECK: #pragma omp parallel for ; CHECK: for (int c1 = 0; c1 < n; c1 += 1) ; CHECK: Stmt_loop_body(c1) |