#include "builtins.h"
#include "tree-dfa.h"
#include "dbgcnt.h"
+#include "graphite-oacc.h"
+#include "internal-fn.h"
/* TODO: Support for predicated code motion. I.e.
Otherwise return MOVE_IMPOSSIBLE. */
enum move_pos
-movement_possibility (gimple *stmt)
+movement_possibility (gimple *stmt, bool restrict_oacc_hoisting)
{
tree lhs;
enum move_pos ret = MOVE_POSSIBLE;
+ if (restrict_oacc_hoisting && oacc_get_fn_attrib (cfun->decl)
+ && gimple_code (stmt) == GIMPLE_ASSIGN)
+ {
+ tree rhs = gimple_assign_rhs1 (stmt);
+
+ if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
+ rhs = TREE_OPERAND (rhs, 0);
+
+ if (TREE_CODE (rhs) == ARRAY_REF)
+ return MOVE_IMPOSSIBLE;
+ }
+
if (flag_unswitch_loops
&& gimple_code (stmt) == GIMPLE_COND)
{
statements. */
static void
-compute_invariantness (basic_block bb)
+compute_invariantness (basic_block bb, bool restrict_oacc_hoisting)
{
enum move_pos pos;
gimple_stmt_iterator bsi;
{
stmt = gsi_stmt (bsi);
- pos = movement_possibility (stmt);
+ pos = movement_possibility (stmt, restrict_oacc_hoisting);
if (pos == MOVE_IMPOSSIBLE)
continue;
{
stmt = gsi_stmt (bsi);
- pos = movement_possibility (stmt);
+ pos = movement_possibility (stmt, restrict_oacc_hoisting);
if (pos == MOVE_IMPOSSIBLE)
{
if (nonpure_call_p (stmt))
if (!gimple_vuse (stmt))
return;
+ /* The expansion of those OpenACC internal function calls which occurs in a
+ * later pass does not introduce any memory references. Hence it is safe to
+ * ignore them. */
+ if (gimple_call_internal_p (stmt, IFN_GOACC_LOOP)
+ || gimple_call_internal_p (stmt, IFN_UNIQUE))
+ return;
+
mem = simple_mem_ref_in_stmt (stmt, &is_stored);
+
if (!mem)
{
/* We use the shared mem_ref for all unanalyzable refs. */
ao_ref_alias_set (&aor);
HOST_WIDE_INT offset, size, max_size;
poly_int64 saved_maxsize = aor.max_size, mem_off;
- tree mem_base;
+ tree mem_base = NULL;
bool ref_decomposed;
if (aor.max_size_known_p ()
&& aor.offset.is_constant (&offset)
Only perform store motion if STORE_MOTION is true. */
unsigned int
-loop_invariant_motion_in_fun (function *fun, bool store_motion)
+loop_invariant_motion_in_fun (function *fun, bool store_motion,
+ bool restrict_oacc_hoisting)
{
unsigned int todo = 0;
/* For each statement determine the outermost loop in that it is
invariant and cost for computing the invariant. */
for (int i = 0; i < n; ++i)
- compute_invariantness (BASIC_BLOCK_FOR_FN (fun, rpo[i]));
+ compute_invariantness (BASIC_BLOCK_FOR_FN (fun, rpo[i]), restrict_oacc_hoisting);
/* Execute store motion. Force the necessary invariants to be moved
out of the loops as well. */
{
public:
pass_lim (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_lim, ctxt)
+ : gimple_opt_pass (pass_data_lim, ctxt), restrict_oacc_hoisting (false)
{}
+ void set_pass_param (unsigned int n, bool param)
+ {
+ gcc_assert (n == 0);
+ restrict_oacc_hoisting = param;
+ }
+
/* opt_pass methods: */
opt_pass * clone () { return new pass_lim (m_ctxt); }
virtual bool gate (function *) { return flag_tree_loop_im != 0; }
virtual unsigned int execute (function *);
+private:
+ bool restrict_oacc_hoisting;
}; // class pass_lim
if (number_of_loops (fun) <= 1)
return 0;
- unsigned int todo = loop_invariant_motion_in_fun (fun, true);
+
+ bool store_motion = true;
+ /* TODO Enabling store motion in OpenACC kernel functions requires further
+ handling of the OpenACC internal function calls. It can also be harmful
+ to data-dependence analysis. Keep it disabled for now. */
+ if (oacc_function_p (cfun) && graphite_analyze_oacc_target_region_type_p (cfun))
+ store_motion = false;
+
+ unsigned int todo = loop_invariant_motion_in_fun (fun, store_motion,
+ restrict_oacc_hoisting);
if (!in_loop_pipeline)
loop_optimizer_finalize ();