diff --git a/gcc/gimple-loop-interchange.cc b/gcc/gimple-loop-interchange.cc
index ccd5083145f8..7c9b7b2345fa 100644
--- a/gcc/gimple-loop-interchange.cc
+++ b/gcc/gimple-loop-interchange.cc
@@ -2107,7 +2107,7 @@ pass_linterchange::execute (function *fun)
   if (changed_p)
     {
       unsigned todo = TODO_update_ssa_only_virtuals;
-      todo |= loop_invariant_motion_in_fun (cfun, false);
+      todo |= loop_invariant_motion_in_fun (cfun, false, false);
       scev_reset ();
       return todo;
     }
diff --git a/gcc/passes.def b/gcc/passes.def
index 681392f8f79f..1da9382bac53 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -250,7 +250,7 @@ along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_cse_sincos);
       NEXT_PASS (pass_optimize_bswap);
       NEXT_PASS (pass_laddress);
-      NEXT_PASS (pass_lim);
+      NEXT_PASS (pass_lim, true /* restrict_oacc_hoisting */);
       NEXT_PASS (pass_walloca, false);
       NEXT_PASS (pass_pre);
       NEXT_PASS (pass_sink_code);
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 4b187c2cdafe..466dc494fb52 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -47,6 +47,8 @@ along with GCC; see the file COPYING3.  If not see
 #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.

@@ -327,11 +329,23 @@ enum move_pos
    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)
     {
@@ -981,7 +995,7 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
    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;
@@ -1009,7 +1023,7 @@ compute_invariantness (basic_block bb)
       {
        stmt = gsi_stmt (bsi);

-       pos = movement_possibility (stmt);
+       pos = movement_possibility (stmt, restrict_oacc_hoisting);
        if (pos == MOVE_IMPOSSIBLE)
          continue;

@@ -1040,7 +1054,7 @@ compute_invariantness (basic_block bb)
     {
       stmt = gsi_stmt (bsi);

-      pos = movement_possibility (stmt);
+      pos = movement_possibility (stmt, restrict_oacc_hoisting);
       if (pos == MOVE_IMPOSSIBLE)
        {
          if (nonpure_call_p (stmt))
@@ -1465,6 +1479,13 @@ gather_mem_refs_stmt (class loop *loop, gimple *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 && is_gimple_assign (stmt))
     {
@@ -1506,7 +1527,7 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt)
       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)
@@ -3244,7 +3265,8 @@ tree_ssa_lim_finalize (void)
    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;

@@ -3262,7 +3284,7 @@ loop_invariant_motion_in_fun (function *fun, bool store_motion)
   /* 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.  */
@@ -3309,13 +3331,21 @@ class pass_lim : public gimple_opt_pass
 {
 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

@@ -3328,7 +3358,16 @@ pass_lim::execute (function *fun)

   if (number_of_loops (fun) <= 1)
     return 0;
-  unsigned int todo = loop_invariant_motion_in_fun (fun, flag_move_loop_stores);
+
+  bool store_motion = flag_move_loop_stores;
+  /* 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 ();
diff --git a/gcc/tree-ssa-loop-manip.h b/gcc/tree-ssa-loop-manip.h
index 4f604e1bd24a..864fb9f1d355 100644
--- a/gcc/tree-ssa-loop-manip.h
+++ b/gcc/tree-ssa-loop-manip.h
@@ -53,7 +53,7 @@ extern void tree_transform_and_unroll_loop (class loop *, unsigned,
                                            transform_callback, void *);
 extern void tree_unroll_loop (class loop *, unsigned, tree_niter_desc *);
 extern tree canonicalize_loop_ivs (class loop *, tree *, bool);
-extern unsigned int loop_invariant_motion_in_fun (function *, bool);
+extern unsigned int loop_invariant_motion_in_fun (function *, bool, bool);


 #endif /* GCC_TREE_SSA_LOOP_MANIP_H */
