diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2015-10-02 09:18:34 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2015-10-02 09:18:34 +0000 |
commit | 1ddde8dca28e6e8d35db1782938d33e5320145e2 (patch) | |
tree | 0c86523efe143f65b5f0ec98fe758a0d5d63d52a /gcc/ada/gcc-interface/trans.c | |
parent | 7262aee97867264a6cd283ea8a7739c5dfcf13f7 (diff) | |
download | gcc-1ddde8dca28e6e8d35db1782938d33e5320145e2.zip gcc-1ddde8dca28e6e8d35db1782938d33e5320145e2.tar.gz gcc-1ddde8dca28e6e8d35db1782938d33e5320145e2.tar.bz2 |
ada-tree.h (DECL_RESTRICTED_ALIASING_P): New flag.
* gcc-interface/ada-tree.h (DECL_RESTRICTED_ALIASING_P): New flag.
* gcc-interface/decl.c (gnat_to_gnu_param): For parameters passed by
reference but whose type isn't by-ref and whose mechanism hasn't been
forced to by-ref, set the DECL_RESTRICTED_ALIASING_P flag directly on
them instead of changing their type.
* gcc-interface/trans.c (scan_rhs_r): New helper function.
(independent_iterations_p): New predicate.
(Loop_Statement_to_gnu): For a loop with an iteration scheme, set an
ivdep pragma if the iterations are independent.
From-SVN: r228377
Diffstat (limited to 'gcc/ada/gcc-interface/trans.c')
-rw-r--r-- | gcc/ada/gcc-interface/trans.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 58e3d32..1da381b 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -2714,6 +2714,89 @@ can_be_lower_p (tree val1, tree val2) return tree_int_cst_lt (val1, val2); } +/* Helper function for walk_tree, used by independent_iterations_p below. */ + +static tree +scan_rhs_r (tree *tp, int *walk_subtrees, void *data) +{ + bitmap *params = (bitmap *)data; + tree t = *tp; + + /* No need to walk into types or decls. */ + if (IS_TYPE_OR_DECL_P (t)) + *walk_subtrees = 0; + + if (TREE_CODE (t) == PARM_DECL && bitmap_bit_p (*params, DECL_UID (t))) + return t; + + return NULL_TREE; +} + +/* Return true if STMT_LIST generates independent iterations in a loop. */ + +static bool +independent_iterations_p (tree stmt_list) +{ + tree_stmt_iterator tsi; + bitmap params = BITMAP_GGC_ALLOC(); + auto_vec<tree> rhs; + tree iter; + int i; + + if (TREE_CODE (stmt_list) == BIND_EXPR) + stmt_list = BIND_EXPR_BODY (stmt_list); + + /* Scan the list and return false on anything that is not either a check + or an assignment to a parameter with restricted aliasing. */ + for (tsi = tsi_start (stmt_list); !tsi_end_p (tsi); tsi_next (&tsi)) + { + tree stmt = tsi_stmt (tsi); + + switch (TREE_CODE (stmt)) + { + case COND_EXPR: + { + if (COND_EXPR_ELSE (stmt)) + return false; + if (TREE_CODE (COND_EXPR_THEN (stmt)) != CALL_EXPR) + return false; + tree func = get_callee_fndecl (COND_EXPR_THEN (stmt)); + if (!(func && TREE_THIS_VOLATILE (func))) + return false; + break; + } + + case MODIFY_EXPR: + { + tree lhs = TREE_OPERAND (stmt, 0); + while (handled_component_p (lhs)) + lhs = TREE_OPERAND (lhs, 0); + if (TREE_CODE (lhs) != INDIRECT_REF) + return false; + lhs = TREE_OPERAND (lhs, 0); + if (!(TREE_CODE (lhs) == PARM_DECL + && DECL_RESTRICTED_ALIASING_P (lhs))) + return false; + bitmap_set_bit (params, DECL_UID (lhs)); + rhs.safe_push (TREE_OPERAND (stmt, 1)); + break; + } + + default: + return false; + } + } + + /* At this point we know that the list contains only statements that will + modify parameters with restricted aliasing. Check that the statements + don't at the time read from these parameters. */ + FOR_EACH_VEC_ELT (rhs, i, iter) + if (walk_tree_without_duplicates (&iter, scan_rhs_r, ¶ms)) + return false; + + return true; +} + /* Subroutine of gnat_to_gnu to translate gnat_node, an N_Loop_Statement, to a GCC tree, which is returned. */ @@ -3038,6 +3121,13 @@ Loop_Statement_to_gnu (Node_Id gnat_node) add_stmt_with_node_force (rci->invariant_cond, gnat_node); } + /* Second, if loop vectorization is enabled and the iterations of the + loop can easily be proved as independent, mark the loop. */ + if (optimize + && flag_tree_loop_vectorize + && independent_iterations_p (LOOP_STMT_BODY (gnu_loop_stmt))) + LOOP_STMT_IVDEP (gnu_loop_stmt) = 1; + add_stmt (gnu_loop_stmt); gnat_poplevel (); gnu_loop_stmt = end_stmt_group (); |