cfgloop.h (struct loop): Add comment.
authorBin Cheng <bin.cheng@arm.com>
Wed, 5 Jul 2017 11:49:02 +0000 (11:49 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Wed, 5 Jul 2017 11:49:02 +0000 (11:49 +0000)
* cfgloop.h (struct loop): Add comment.  New field orig_loop_num.
* cfgloopmanip.c (lv_adjust_loop_entry_edge): Comment change.
* internal-fn.c (expand_LOOP_DIST_ALIAS): New function.
* internal-fn.def (LOOP_DIST_ALIAS): New.
* tree-vectorizer.c (fold_loop_vectorized_call): Rename to ...
(fold_loop_internal_call): ... this.
(vect_loop_dist_alias_call): New function.
(set_uid_loop_bbs): Call fold_loop_internal_call.
(vectorize_loops): Fold IFN_LOOP_VECTORIZED and IFN_LOOP_DIST_ALIAS
internal calls.

From-SVN: r249983

gcc/ChangeLog
gcc/cfgloop.h
gcc/cfgloopmanip.c
gcc/internal-fn.c
gcc/internal-fn.def
gcc/tree-vectorizer.c

index 1f0b0b43999a19d7c2bc08ac685528b48e200ea9..fa8c40cacddf65f43f2277eb4f1914cc0f517e0f 100644 (file)
@@ -1,3 +1,16 @@
+2017-07-05  Bin Cheng  <bin.cheng@arm.com>
+
+       * cfgloop.h (struct loop): Add comment.  New field orig_loop_num.
+       * cfgloopmanip.c (lv_adjust_loop_entry_edge): Comment change.
+       * internal-fn.c (expand_LOOP_DIST_ALIAS): New function.
+       * internal-fn.def (LOOP_DIST_ALIAS): New.
+       * tree-vectorizer.c (fold_loop_vectorized_call): Rename to ...
+       (fold_loop_internal_call): ... this.
+       (vect_loop_dist_alias_call): New function.
+       (set_uid_loop_bbs): Call fold_loop_internal_call.
+       (vectorize_loops): Fold IFN_LOOP_VECTORIZED and IFN_LOOP_DIST_ALIAS
+       internal calls.
+
 2017-07-04  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/81300
index a8bec1d48af1e7acfcaf48c7518afca195abb7cf..e7ffa2364376c256b9a73fd2433e52fc2cca7d83 100644 (file)
@@ -114,7 +114,8 @@ struct GTY ((chain_next ("%h.next"))) control_iv {
 
 /* Structure to hold information for each natural loop.  */
 struct GTY ((chain_next ("%h.next"))) loop {
-  /* Index into loops array.  */
+  /* Index into loops array.  Note indices will never be reused after loop
+     is destroyed.  */
   int num;
 
   /* Number of loop insns.  */
@@ -225,6 +226,16 @@ struct GTY ((chain_next ("%h.next"))) loop {
      builtins.  */
   tree simduid;
 
+  /* In loop optimization, it's common to generate loops from the original
+     loop.  This field records the index of the original loop which can be
+     used to track the original loop from newly generated loops.  This can
+     be done by calling function get_loop (cfun, orig_loop_num).  Note the
+     original loop could be destroyed for various reasons thus no longer
+     exists, as a result, function call to get_loop returns NULL pointer.
+     In this case, this field should not be used and needs to be cleared
+     whenever possible.  */
+  int orig_loop_num;
+
   /* Upper bound on number of iterations of a loop.  */
   struct nb_iter_bound *bounds;
 
index a7d0e612eb26f120702334da34f442bf19178bbd..3f4ff988c7400decf9099a131d6c35c3a3bd73b5 100644 (file)
@@ -1623,7 +1623,8 @@ force_single_succ_latches (void)
 
   THEN_PROB is the probability of then branch of the condition.
   ELSE_PROB is the probability of else branch. Note that they may be both
-  REG_BR_PROB_BASE when condition is IFN_LOOP_VECTORIZED.  */
+  REG_BR_PROB_BASE when condition is IFN_LOOP_VECTORIZED or
+  IFN_LOOP_DIST_ALIAS.  */
 
 static basic_block
 lv_adjust_loop_entry_edge (basic_block first_head, basic_block second_head,
index d276dfecf9a3bf52507783e4e0a804692dc48c22..18466cd53b334515e01285559a2187ea2ac70f13 100644 (file)
@@ -2250,6 +2250,14 @@ expand_LOOP_VECTORIZED (internal_fn, gcall *)
   gcc_unreachable ();
 }
 
+/* This should get folded in tree-vectorizer.c.  */
+
+static void
+expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
+{
+  gcc_unreachable ();
+}
+
 /* Expand MASK_LOAD call STMT using optab OPTAB.  */
 
 static void
index e162d81121cba31f75387bd6e4e3bcbde7d04b02..79c19fb8e7a6948bd8cc6489e76f0e61e5f60d50 100644 (file)
@@ -158,6 +158,7 @@ DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (GOMP_SIMD_ORDERED_START, ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (GOMP_SIMD_ORDERED_END, ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (LOOP_DIST_ALIAS, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (ANNOTATE,  ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW, ".R.")
 DEF_INTERNAL_FN (UBSAN_BOUNDS, ECF_LEAF | ECF_NOTHROW, NULL)
index 0d62c829ef5875f7ce6732d82e64601e79b2b130..33a1f580474cb93ccc4f2f43631bf7a90623c2ad 100644 (file)
@@ -448,11 +448,11 @@ vect_loop_vectorized_call (struct loop *loop)
   return NULL;
 }
 
-/* Fold LOOP_VECTORIZED internal call G to VALUE and
-   update any immediate uses of it's LHS.  */
+/* Fold loop internal call G like IFN_LOOP_VECTORIZED/IFN_LOOP_DIST_ALIAS
+   to VALUE and update any immediate uses of it's LHS.  */
 
 static void
-fold_loop_vectorized_call (gimple *g, tree value)
+fold_loop_internal_call (gimple *g, tree value)
 {
   tree lhs = gimple_call_lhs (g);
   use_operand_p use_p;
@@ -469,6 +469,60 @@ fold_loop_vectorized_call (gimple *g, tree value)
     }
 }
 
+/* If LOOP has been versioned during loop distribution, return the gurading
+   internal call.  */
+
+static gimple *
+vect_loop_dist_alias_call (struct loop *loop)
+{
+  basic_block bb;
+  basic_block entry;
+  struct loop *outer, *orig;
+  gimple_stmt_iterator gsi;
+  gimple *g;
+
+  if (loop->orig_loop_num == 0)
+    return NULL;
+
+  orig = get_loop (cfun, loop->orig_loop_num);
+  if (orig == NULL)
+    {
+      /* The original loop is somehow destroyed.  Clear the information.  */
+      loop->orig_loop_num = 0;
+      return NULL;
+    }
+
+  if (loop != orig)
+    bb = nearest_common_dominator (CDI_DOMINATORS, loop->header, orig->header);
+  else
+    bb = loop_preheader_edge (loop)->src;
+
+  outer = bb->loop_father;
+  entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+
+  /* Look upward in dominance tree.  */
+  for (; bb != entry && flow_bb_inside_loop_p (outer, bb);
+       bb = get_immediate_dominator (CDI_DOMINATORS, bb))
+    {
+      g = last_stmt (bb);
+      if (g == NULL || gimple_code (g) != GIMPLE_COND)
+       continue;
+
+      gsi = gsi_for_stmt (g);
+      gsi_prev (&gsi);
+      if (gsi_end_p (gsi))
+       continue;
+
+      g = gsi_stmt (gsi);
+      /* The guarding internal function call must have the same distribution
+        alias id.  */
+      if (gimple_call_internal_p (g, IFN_LOOP_DIST_ALIAS)
+         && (tree_to_shwi (gimple_call_arg (g, 0)) == loop->orig_loop_num))
+       return g;
+    }
+  return NULL;
+}
+
 /* Set the uids of all the statements in basic blocks inside loop
    represented by LOOP_VINFO. LOOP_VECTORIZED_CALL is the internal
    call guarding the loop which has been if converted.  */
@@ -494,7 +548,7 @@ set_uid_loop_bbs (loop_vec_info loop_vinfo, gimple *loop_vectorized_call)
        {
          arg = gimple_call_arg (g, 0);
          get_loop (cfun, tree_to_shwi (arg))->dont_vectorize = true;
-         fold_loop_vectorized_call (g, boolean_false_node);
+         fold_loop_internal_call (g, boolean_false_node);
        }
     }
   bbs = get_loop_body (scalar_loop);
@@ -595,7 +649,7 @@ vectorize_loops (void)
     else
       {
        loop_vec_info loop_vinfo, orig_loop_vinfo;
-       gimple *loop_vectorized_call;
+       gimple *loop_vectorized_call, *loop_dist_alias_call;
        try_vectorize:
        if (!((flag_tree_loop_vectorize
               && optimize_loop_nest_for_speed_p (loop))
@@ -603,6 +657,7 @@ vectorize_loops (void)
          continue;
        orig_loop_vinfo = NULL;
        loop_vectorized_call = vect_loop_vectorized_call (loop);
+       loop_dist_alias_call = vect_loop_dist_alias_call (loop);
        vectorize_epilogue:
        vect_location = find_loop_location (loop);
         if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOCATION
@@ -652,8 +707,8 @@ vectorize_loops (void)
                  {
                    dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
                                     "basic block vectorized\n");
-                   fold_loop_vectorized_call (loop_vectorized_call,
-                                              boolean_true_node);
+                   fold_loop_internal_call (loop_vectorized_call,
+                                            boolean_true_node);
                    loop_vectorized_call = NULL;
                    ret |= TODO_cleanup_cfg;
                  }
@@ -706,10 +761,17 @@ vectorize_loops (void)
 
        if (loop_vectorized_call)
          {
-           fold_loop_vectorized_call (loop_vectorized_call, boolean_true_node);
+           fold_loop_internal_call (loop_vectorized_call, boolean_true_node);
            loop_vectorized_call = NULL;
            ret |= TODO_cleanup_cfg;
          }
+       if (loop_dist_alias_call)
+         {
+           tree value = gimple_call_arg (loop_dist_alias_call, 1);
+           fold_loop_internal_call (loop_dist_alias_call, value);
+           loop_dist_alias_call = NULL;
+           ret |= TODO_cleanup_cfg;
+         }
 
        if (new_loop)
          {
@@ -741,7 +803,16 @@ vectorize_loops (void)
            gimple *g = vect_loop_vectorized_call (loop);
            if (g)
              {
-               fold_loop_vectorized_call (g, boolean_false_node);
+               fold_loop_internal_call (g, boolean_false_node);
+               ret |= TODO_cleanup_cfg;
+               g = NULL;
+             }
+           else
+             g = vect_loop_dist_alias_call (loop);
+
+           if (g)
+             {
+               fold_loop_internal_call (g, boolean_false_node);
                ret |= TODO_cleanup_cfg;
              }
          }