LCOV - code coverage report
Current view: top level - gcc - tree-ssa-loop-ch.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 210 221 95.0 %
Date: 2020-03-28 11:57:23 Functions: 14 14 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Loop header copying on trees.
       2                 :            :    Copyright (C) 2004-2020 Free Software Foundation, Inc.
       3                 :            : 
       4                 :            : This file is part of GCC.
       5                 :            : 
       6                 :            : GCC is free software; you can redistribute it and/or modify it
       7                 :            : under the terms of the GNU General Public License as published by the
       8                 :            : Free Software Foundation; either version 3, or (at your option) any
       9                 :            : later version.
      10                 :            : 
      11                 :            : GCC is distributed in the hope that it will be useful, but WITHOUT
      12                 :            : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :            : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :            : for more details.
      15                 :            : 
      16                 :            : You should have received a copy of the GNU General Public License
      17                 :            : along with GCC; see the file COPYING3.  If not see
      18                 :            : <http://www.gnu.org/licenses/>.  */
      19                 :            : 
      20                 :            : #include "config.h"
      21                 :            : #include "system.h"
      22                 :            : #include "coretypes.h"
      23                 :            : #include "backend.h"
      24                 :            : #include "tree.h"
      25                 :            : #include "gimple.h"
      26                 :            : #include "cfghooks.h"
      27                 :            : #include "tree-pass.h"
      28                 :            : #include "gimple-ssa.h"
      29                 :            : #include "gimple-iterator.h"
      30                 :            : #include "tree-cfg.h"
      31                 :            : #include "tree-into-ssa.h"
      32                 :            : #include "cfgloop.h"
      33                 :            : #include "tree-inline.h"
      34                 :            : #include "tree-ssa-scopedtables.h"
      35                 :            : #include "tree-ssa-threadedge.h"
      36                 :            : #include "tree-ssa-sccvn.h"
      37                 :            : #include "tree-phinodes.h"
      38                 :            : #include "ssa-iterators.h"
      39                 :            : 
      40                 :            : /* Duplicates headers of loops if they are small enough, so that the statements
      41                 :            :    in the loop body are always executed when the loop is entered.  This
      42                 :            :    increases effectiveness of code motion optimizations, and reduces the need
      43                 :            :    for loop preconditioning.  */
      44                 :            : 
      45                 :            : /* Check whether we should duplicate HEADER of LOOP.  At most *LIMIT
      46                 :            :    instructions should be duplicated, limit is decreased by the actual
      47                 :            :    amount.  */
      48                 :            : 
      49                 :            : static bool
      50                 :     418340 : should_duplicate_loop_header_p (basic_block header, class loop *loop,
      51                 :            :                                 int *limit)
      52                 :            : {
      53                 :     418340 :   gimple_stmt_iterator bsi;
      54                 :            : 
      55                 :     418340 :   gcc_assert (!header->aux);
      56                 :            : 
      57                 :            :   /* Loop header copying usually increases size of the code.  This used not to
      58                 :            :      be true, since quite often it is possible to verify that the condition is
      59                 :            :      satisfied in the first iteration and therefore to eliminate it.  Jump
      60                 :            :      threading handles these cases now.  */
      61                 :     418340 :   if (optimize_loop_for_size_p (loop)
      62                 :     418340 :       && !loop->force_vectorize)
      63                 :            :     {
      64                 :      16632 :       if (dump_file && (dump_flags & TDF_DETAILS))
      65                 :          0 :         fprintf (dump_file,
      66                 :            :                  "  Not duplicating bb %i: optimizing for size.\n",
      67                 :            :                  header->index);
      68                 :      16632 :       return false;
      69                 :            :     }
      70                 :            : 
      71                 :     401708 :   gcc_assert (EDGE_COUNT (header->succs) > 0);
      72                 :     401708 :   if (single_succ_p (header))
      73                 :            :     {
      74                 :     100135 :       if (dump_file && (dump_flags & TDF_DETAILS))
      75                 :          2 :         fprintf (dump_file,
      76                 :            :                  "  Not duplicating bb %i: it is single succ.\n",
      77                 :            :                  header->index);
      78                 :     100135 :       return false;
      79                 :            :     }
      80                 :            : 
      81                 :     301573 :   if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest)
      82                 :     301573 :       && flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 1)->dest))
      83                 :            :     {
      84                 :      55966 :       if (dump_file && (dump_flags & TDF_DETAILS))
      85                 :          1 :         fprintf (dump_file,
      86                 :            :                  "  Not duplicating bb %i: both successors are in loop.\n",
      87                 :            :                  loop->num);
      88                 :      55966 :       return false;
      89                 :            :     }
      90                 :            : 
      91                 :            :   /* If this is not the original loop header, we want it to have just
      92                 :            :      one predecessor in order to match the && pattern.  */
      93                 :     245607 :   if (header != loop->header && !single_pred_p (header))
      94                 :            :     {
      95                 :          0 :       if (dump_file && (dump_flags & TDF_DETAILS))
      96                 :          0 :         fprintf (dump_file,
      97                 :            :                  "  Not duplicating bb %i: it has mutiple predecestors.\n",
      98                 :            :                  header->index);
      99                 :          0 :       return false;
     100                 :            :     }
     101                 :            : 
     102                 :     245607 :   gcond *last = safe_dyn_cast <gcond *> (last_stmt (header));
     103                 :     230187 :   if (!last)
     104                 :            :     {
     105                 :      15420 :       if (dump_file && (dump_flags & TDF_DETAILS))
     106                 :          0 :         fprintf (dump_file,
     107                 :            :                  "  Not duplicating bb %i: it does not end by conditional.\n",
     108                 :            :                  header->index);
     109                 :      15420 :       return false;
     110                 :            :     }
     111                 :            : 
     112                 :     659100 :   for (gphi_iterator psi = gsi_start_phis (header); !gsi_end_p (psi);
     113                 :     428913 :        gsi_next (&psi))
     114                 :            :     {
     115                 :     428913 :       gphi *phi = psi.phi ();
     116                 :     428913 :       tree res = gimple_phi_result (phi);
     117                 :     857796 :       if (INTEGRAL_TYPE_P (TREE_TYPE (res))
     118                 :     667820 :           || POINTER_TYPE_P (TREE_TYPE (res)))
     119                 :     265944 :         gimple_set_uid (phi, 1 /* IV */);
     120                 :            :       else
     121                 :     428913 :         gimple_set_uid (phi, 0);
     122                 :            :     }
     123                 :            : 
     124                 :            :   /* Count number of instructions and punt on calls.
     125                 :            :      Populate stmts INV/IV flag to later apply heuristics to the
     126                 :            :      kind of conditions we want to copy.  */
     127                 :    1560910 :   for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi))
     128                 :            :     {
     129                 :    1115030 :       gimple *last = gsi_stmt (bsi);
     130                 :            : 
     131                 :    1115030 :       if (gimple_code (last) == GIMPLE_LABEL)
     132                 :       1237 :         continue;
     133                 :            : 
     134                 :    1113800 :       if (is_gimple_debug (last))
     135                 :     607795 :         continue;
     136                 :            : 
     137                 :     506001 :       if (gimple_code (last) == GIMPLE_CALL
     138                 :     506001 :           && (!gimple_inexpensive_call_p (as_a <gcall *> (last))
     139                 :            :               /* IFN_LOOP_DIST_ALIAS means that inner loop is distributed
     140                 :            :                  at current loop's header.  Don't copy in this case.  */
     141                 :        859 :               || gimple_call_internal_p (last, IFN_LOOP_DIST_ALIAS)))
     142                 :            :         {
     143                 :      13944 :           if (dump_file && (dump_flags & TDF_DETAILS))
     144                 :          0 :             fprintf (dump_file,
     145                 :            :                      "  Not duplicating bb %i: it contains call.\n",
     146                 :            :                      header->index);
     147                 :      13944 :           return false;
     148                 :            :         }
     149                 :            : 
     150                 :     492057 :       *limit -= estimate_num_insns (last, &eni_size_weights);
     151                 :     492057 :       if (*limit < 0)
     152                 :            :         {
     153                 :        555 :           if (dump_file && (dump_flags & TDF_DETAILS))
     154                 :          0 :             fprintf (dump_file,
     155                 :            :                      "  Not duplicating bb %i contains too many insns.\n",
     156                 :            :                      header->index);
     157                 :        555 :           return false;
     158                 :            :         }
     159                 :            : 
     160                 :            :       /* Classify the stmt based on whether its computation is based
     161                 :            :          on a IV or whether it is invariant in the loop.  */
     162                 :     491502 :       gimple_set_uid (last, 0);
     163                 :     767316 :       if (!gimple_vuse (last))
     164                 :            :         {
     165                 :     374282 :           bool inv = true;
     166                 :     374282 :           bool iv = false;
     167                 :     374282 :           ssa_op_iter i;
     168                 :     374282 :           tree op;
     169                 :     929233 :           FOR_EACH_SSA_TREE_OPERAND (op, last, i, SSA_OP_USE)
     170                 :     554951 :             if (!SSA_NAME_IS_DEFAULT_DEF (op)
     171                 :     554951 :                 && flow_bb_inside_loop_p (loop,
     172                 :     538714 :                                           gimple_bb (SSA_NAME_DEF_STMT (op))))
     173                 :            :               {
     174                 :     415859 :                 if (!(gimple_uid (SSA_NAME_DEF_STMT (op)) & 2 /* INV */))
     175                 :     410976 :                   inv = false;
     176                 :     415859 :                 if (gimple_uid (SSA_NAME_DEF_STMT (op)) & 1 /* IV */)
     177                 :     281214 :                   iv = true;
     178                 :            :               }
     179                 :     839223 :           gimple_set_uid (last, (iv ? 1 : 0) | (inv ? 2 : 0));
     180                 :            :         }
     181                 :            :     }
     182                 :            : 
     183                 :            :   /* If the condition tests a non-IV loop variant we do not want to rotate
     184                 :            :      the loop further.  Unless this is the original loop header.  */
     185                 :     215688 :   tree lhs = gimple_cond_lhs (last);
     186                 :     215688 :   tree rhs = gimple_cond_rhs (last);
     187                 :     215688 :   if (header != loop->header
     188                 :     215688 :       && ((TREE_CODE (lhs) == SSA_NAME
     189                 :      35155 :            && !SSA_NAME_IS_DEFAULT_DEF (lhs)
     190                 :      34702 :            && flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (lhs)))
     191                 :      31157 :            && gimple_uid (SSA_NAME_DEF_STMT (lhs)) == 0)
     192                 :      15857 :           || (TREE_CODE (rhs) == SSA_NAME
     193                 :       7284 :               && !SSA_NAME_IS_DEFAULT_DEF (rhs)
     194                 :       7160 :               && flow_bb_inside_loop_p (loop,
     195                 :       7160 :                                         gimple_bb (SSA_NAME_DEF_STMT (rhs)))
     196                 :       4543 :               && gimple_uid (SSA_NAME_DEF_STMT (rhs)) == 0)))
     197                 :            :     {
     198                 :      21317 :       if (dump_file && (dump_flags & TDF_DETAILS))
     199                 :          3 :         fprintf (dump_file,
     200                 :            :                  "  Not duplicating bb %i: condition based on non-IV loop"
     201                 :            :                  " variant.\n", header->index);
     202                 :      21317 :       return false;
     203                 :            :     }
     204                 :            : 
     205                 :     194371 :   if (dump_file && (dump_flags & TDF_DETAILS))
     206                 :          8 :     fprintf (dump_file, "    Will duplicate bb %i\n", header->index); 
     207                 :            :   return true;
     208                 :            : }
     209                 :            : 
     210                 :            : /* Checks whether LOOP is a do-while style loop.  */
     211                 :            : 
     212                 :            : static bool
     213                 :     433519 : do_while_loop_p (class loop *loop)
     214                 :            : {
     215                 :     433519 :   gimple *stmt = last_stmt (loop->latch);
     216                 :            : 
     217                 :            :   /* If the latch of the loop is not empty, it is not a do-while loop.  */
     218                 :     433519 :   if (stmt
     219                 :     433519 :       && gimple_code (stmt) != GIMPLE_LABEL)
     220                 :            :     {
     221                 :     203885 :       if (dump_file && (dump_flags & TDF_DETAILS))
     222                 :          5 :         fprintf (dump_file,
     223                 :            :                  "Loop %i is not do-while loop: latch is not empty.\n",
     224                 :            :                  loop->num);
     225                 :     203885 :       return false;
     226                 :            :     }
     227                 :            : 
     228                 :            :   /* If the latch does not have a single predecessor, it is not a
     229                 :            :      do-while loop.  */
     230                 :     229634 :   if (!single_pred_p (loop->latch))
     231                 :            :     {
     232                 :      14544 :       if (dump_file && (dump_flags & TDF_DETAILS))
     233                 :          1 :         fprintf (dump_file,
     234                 :            :                  "Loop %i is not do-while loop: latch has multiple "
     235                 :            :                  "predecessors.\n", loop->num);
     236                 :      14544 :       return false;
     237                 :            :     }
     238                 :            : 
     239                 :            :   /* If the latch predecessor doesn't exit the loop, it is not a
     240                 :            :      do-while loop.  */
     241                 :     215090 :   if (!loop_exits_from_bb_p (loop, single_pred (loop->latch)))
     242                 :            :     {
     243                 :       5540 :       if (dump_file && (dump_flags & TDF_DETAILS))
     244                 :          0 :         fprintf (dump_file,
     245                 :            :                  "Loop %i is not do-while loop: latch predecessor "
     246                 :            :                  "does not exit loop.\n", loop->num);
     247                 :       5540 :       return false;
     248                 :            :     }
     249                 :            : 
     250                 :     209550 :   if (dump_file && (dump_flags & TDF_DETAILS))
     251                 :          8 :     fprintf (dump_file, "Loop %i is do-while loop\n", loop->num);
     252                 :            : 
     253                 :            :   return true;
     254                 :            : }
     255                 :            : 
     256                 :            : namespace {
     257                 :            : 
     258                 :            : /* Common superclass for both header-copying phases.  */
     259                 :            : class ch_base : public gimple_opt_pass
     260                 :            : {
     261                 :            :   protected:
     262                 :     601620 :     ch_base (pass_data data, gcc::context *ctxt)
     263                 :    1203240 :       : gimple_opt_pass (data, ctxt)
     264                 :            :     {}
     265                 :            : 
     266                 :            :   /* Copies headers of all loops in FUN for which process_loop_p is true.  */
     267                 :            :   unsigned int copy_headers (function *fun);
     268                 :            : 
     269                 :            :   /* Return true to copy headers of LOOP or false to skip.  */
     270                 :            :   virtual bool process_loop_p (class loop *loop) = 0;
     271                 :            : };
     272                 :            : 
     273                 :            : const pass_data pass_data_ch =
     274                 :            : {
     275                 :            :   GIMPLE_PASS, /* type */
     276                 :            :   "ch", /* name */
     277                 :            :   OPTGROUP_LOOP, /* optinfo_flags */
     278                 :            :   TV_TREE_CH, /* tv_id */
     279                 :            :   ( PROP_cfg | PROP_ssa ), /* properties_required */
     280                 :            :   0, /* properties_provided */
     281                 :            :   0, /* properties_destroyed */
     282                 :            :   0, /* todo_flags_start */
     283                 :            :   0, /* todo_flags_finish */
     284                 :            : };
     285                 :            : 
     286                 :            : class pass_ch : public ch_base
     287                 :            : {
     288                 :            : public:
     289                 :     401080 :   pass_ch (gcc::context *ctxt)
     290                 :     401080 :     : ch_base (pass_data_ch, ctxt)
     291                 :     401080 :   {}
     292                 :            : 
     293                 :            :   /* opt_pass methods: */
     294                 :     686534 :   virtual bool gate (function *) { return flag_tree_ch != 0; }
     295                 :            :   
     296                 :            :   /* Initialize and finalize loop structures, copying headers inbetween.  */
     297                 :            :   virtual unsigned int execute (function *);
     298                 :            : 
     299                 :     200540 :   opt_pass * clone () { return new pass_ch (m_ctxt); }
     300                 :            : 
     301                 :            : protected:
     302                 :            :   /* ch_base method: */
     303                 :            :   virtual bool process_loop_p (class loop *loop);
     304                 :            : }; // class pass_ch
     305                 :            : 
     306                 :            : const pass_data pass_data_ch_vect =
     307                 :            : {
     308                 :            :   GIMPLE_PASS, /* type */
     309                 :            :   "ch_vect", /* name */
     310                 :            :   OPTGROUP_LOOP, /* optinfo_flags */
     311                 :            :   TV_TREE_CH, /* tv_id */
     312                 :            :   ( PROP_cfg | PROP_ssa ), /* properties_required */
     313                 :            :   0, /* properties_provided */
     314                 :            :   0, /* properties_destroyed */
     315                 :            :   0, /* todo_flags_start */
     316                 :            :   0, /* todo_flags_finish */
     317                 :            : };
     318                 :            : 
     319                 :            : /* This is a more aggressive version of the same pass, designed to run just
     320                 :            :    before if-conversion and vectorization, to put more loops into the form
     321                 :            :    required for those phases.  */
     322                 :            : class pass_ch_vect : public ch_base
     323                 :            : {
     324                 :            : public:
     325                 :     200540 :   pass_ch_vect (gcc::context *ctxt)
     326                 :     200540 :     : ch_base (pass_data_ch_vect, ctxt)
     327                 :     200540 :   {}
     328                 :            : 
     329                 :            :   /* opt_pass methods: */
     330                 :     157439 :   virtual bool gate (function *fun)
     331                 :            :   {
     332                 :     157439 :     return flag_tree_ch != 0
     333                 :     157439 :            && (flag_tree_loop_vectorize != 0 || fun->has_force_vectorize_loops);
     334                 :            :   }
     335                 :            :   
     336                 :            :   /* Just copy headers, no initialization/finalization of loop structures.  */
     337                 :            :   virtual unsigned int execute (function *);
     338                 :            : 
     339                 :            : protected:
     340                 :            :   /* ch_base method: */
     341                 :            :   virtual bool process_loop_p (class loop *loop);
     342                 :            : }; // class pass_ch_vect
     343                 :            : 
     344                 :            : /* For all loops, copy the condition at the end of the loop body in front
     345                 :            :    of the loop.  This is beneficial since it increases efficiency of
     346                 :            :    code motion optimizations.  It also saves one jump on entry to the loop.  */
     347                 :            : 
     348                 :            : unsigned int
     349                 :     720339 : ch_base::copy_headers (function *fun)
     350                 :            : {
     351                 :     720339 :   class loop *loop;
     352                 :     720339 :   basic_block header;
     353                 :     720339 :   edge exit, entry;
     354                 :     720339 :   basic_block *bbs, *copied_bbs;
     355                 :     720339 :   unsigned n_bbs;
     356                 :     720339 :   unsigned bbs_size;
     357                 :     720339 :   bool changed = false;
     358                 :            : 
     359                 :    1440680 :   if (number_of_loops (fun) <= 1)
     360                 :            :     return 0;
     361                 :            : 
     362                 :     192162 :   bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
     363                 :     192162 :   copied_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
     364                 :     192162 :   bbs_size = n_basic_blocks_for_fn (fun);
     365                 :            : 
     366                 :     192162 :   auto_vec<std::pair<edge, loop_p> > copied;
     367                 :            : 
     368                 :     651695 :   FOR_EACH_LOOP (loop, 0)
     369                 :            :     {
     370                 :     459533 :       int initial_limit = param_max_loop_header_insns;
     371                 :     459533 :       int remaining_limit = initial_limit;
     372                 :     459533 :       if (dump_file && (dump_flags & TDF_DETAILS))
     373                 :          8 :         fprintf (dump_file,
     374                 :            :                  "Analyzing loop %i\n", loop->num);
     375                 :            : 
     376                 :     459533 :       header = loop->header;
     377                 :            : 
     378                 :            :       /* If the loop is already a do-while style one (either because it was
     379                 :            :          written as such, or because jump threading transformed it into one),
     380                 :            :          we might be in fact peeling the first iteration of the loop.  This
     381                 :            :          in general is not a good idea.  Also avoid touching infinite loops.  */
     382                 :     459533 :       if (!loop_has_exit_edges (loop)
     383                 :     459533 :           || !process_loop_p (loop))
     384                 :     279089 :         continue;
     385                 :            : 
     386                 :            :       /* Iterate the header copying up to limit; this takes care of the cases
     387                 :            :          like while (a && b) {...}, where we want to have both of the conditions
     388                 :            :          copied.  TODO -- handle while (a || b) - like cases, by not requiring
     389                 :            :          the header to have just a single successor and copying up to
     390                 :            :          postdominator.  */
     391                 :            : 
     392                 :            :       exit = NULL;
     393                 :            :       n_bbs = 0;
     394                 :     418340 :       while (should_duplicate_loop_header_p (header, loop, &remaining_limit))
     395                 :            :         {
     396                 :            :           /* Find a successor of header that is inside a loop; i.e. the new
     397                 :            :              header after the condition is copied.  */
     398                 :     194371 :           if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
     399                 :     115053 :             exit = EDGE_SUCC (header, 0);
     400                 :            :           else
     401                 :      79318 :             exit = EDGE_SUCC (header, 1);
     402                 :     194371 :           bbs[n_bbs++] = header;
     403                 :     194371 :           gcc_assert (bbs_size > n_bbs);
     404                 :     194371 :           header = exit->dest;
     405                 :            :         }
     406                 :            : 
     407                 :     223969 :       if (!exit)
     408                 :      43525 :         continue;
     409                 :            : 
     410                 :     180444 :       if (dump_file && (dump_flags & TDF_DETAILS))
     411                 :          6 :         fprintf (dump_file,
     412                 :            :                  "Duplicating header of the loop %d up to edge %d->%d,"
     413                 :            :                  " %i insns.\n",
     414                 :          6 :                  loop->num, exit->src->index, exit->dest->index,
     415                 :            :                  initial_limit - remaining_limit);
     416                 :            : 
     417                 :            :       /* Ensure that the header will have just the latch as a predecessor
     418                 :            :          inside the loop.  */
     419                 :     180444 :       if (!single_pred_p (exit->dest))
     420                 :         11 :         exit = single_pred_edge (split_edge (exit));
     421                 :            : 
     422                 :     180444 :       entry = loop_preheader_edge (loop);
     423                 :            : 
     424                 :     180444 :       propagate_threaded_block_debug_into (exit->dest, entry->dest);
     425                 :     180444 :       if (!gimple_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs,
     426                 :            :                                          true))
     427                 :            :         {
     428                 :          0 :           fprintf (dump_file, "Duplication failed.\n");
     429                 :          0 :           continue;
     430                 :            :         }
     431                 :     180444 :       copied.safe_push (std::make_pair (entry, loop));
     432                 :            : 
     433                 :            :       /* If the loop has the form "for (i = j; i < j + 10; i++)" then
     434                 :            :          this copying can introduce a case where we rely on undefined
     435                 :            :          signed overflow to eliminate the preheader condition, because
     436                 :            :          we assume that "j < j + 10" is true.  We don't want to warn
     437                 :            :          about that case for -Wstrict-overflow, because in general we
     438                 :            :          don't warn about overflow involving loops.  Prevent the
     439                 :            :          warning by setting the no_warning flag in the condition.  */
     440                 :     180444 :       if (warn_strict_overflow > 0)
     441                 :            :         {
     442                 :            :           unsigned int i;
     443                 :            : 
     444                 :      65956 :           for (i = 0; i < n_bbs; ++i)
     445                 :            :             {
     446                 :      34181 :               gimple_stmt_iterator bsi;
     447                 :            : 
     448                 :      68362 :               for (bsi = gsi_start_bb (copied_bbs[i]);
     449                 :     231079 :                    !gsi_end_p (bsi);
     450                 :     196898 :                    gsi_next (&bsi))
     451                 :            :                 {
     452                 :     196898 :                   gimple *stmt = gsi_stmt (bsi);
     453                 :     196898 :                   if (gimple_code (stmt) == GIMPLE_COND)
     454                 :            :                     {
     455                 :      34181 :                       tree lhs = gimple_cond_lhs (stmt);
     456                 :      34181 :                       if (gimple_cond_code (stmt) != EQ_EXPR
     457                 :      30132 :                           && gimple_cond_code (stmt) != NE_EXPR
     458                 :      26033 :                           && INTEGRAL_TYPE_P (TREE_TYPE (lhs))
     459                 :      59960 :                           && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)))
     460                 :      23202 :                         gimple_set_no_warning (stmt, true);
     461                 :            :                     }
     462                 :     162717 :                   else if (is_gimple_assign (stmt))
     463                 :            :                     {
     464                 :      36212 :                       enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
     465                 :      36212 :                       tree rhs1 = gimple_assign_rhs1 (stmt);
     466                 :      36212 :                       if (TREE_CODE_CLASS (rhs_code) == tcc_comparison
     467                 :            :                           && rhs_code != EQ_EXPR
     468                 :        493 :                           && rhs_code != NE_EXPR
     469                 :        208 :                           && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
     470                 :      36390 :                           && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (rhs1)))
     471                 :     196898 :                         gimple_set_no_warning (stmt, true);
     472                 :            :                     }
     473                 :            :                 }
     474                 :            :             }
     475                 :            :         }
     476                 :            : 
     477                 :            :       /* Ensure that the latch and the preheader is simple (we know that they
     478                 :            :          are not now, since there was the loop exit condition.  */
     479                 :     180444 :       split_edge (loop_preheader_edge (loop));
     480                 :     180444 :       split_edge (loop_latch_edge (loop));
     481                 :            : 
     482                 :     180444 :       if (dump_file && (dump_flags & TDF_DETAILS))
     483                 :            :         {
     484                 :          6 :           if (do_while_loop_p (loop))
     485                 :          6 :             fprintf (dump_file, "Loop %d is now do-while loop.\n", loop->num);
     486                 :            :           else
     487                 :          0 :             fprintf (dump_file, "Loop %d is still not do-while loop.\n",
     488                 :            :                      loop->num);
     489                 :            :         }
     490                 :            : 
     491                 :     180444 :       changed = true;
     492                 :            :     }
     493                 :            : 
     494                 :     192162 :   if (changed)
     495                 :            :     {
     496                 :      78705 :       update_ssa (TODO_update_ssa);
     497                 :            :       /* After updating SSA form perform CSE on the loop header
     498                 :            :          copies.  This is esp. required for the pass before
     499                 :            :          vectorization since nothing cleans up copied exit tests
     500                 :            :          that can now be simplified.  CSE from the entry of the
     501                 :            :          region we copied till all loop exit blocks but not
     502                 :            :          entering the loop itself.  */
     503                 :     518298 :       for (unsigned i = 0; i < copied.length (); ++i)
     504                 :            :         {
     505                 :     180444 :           edge entry = copied[i].first;
     506                 :     180444 :           loop_p loop = copied[i].second;
     507                 :     180444 :           vec<edge> exit_edges = get_loop_exit_edges (loop);
     508                 :     180444 :           bitmap exit_bbs = BITMAP_ALLOC (NULL);
     509                 :    1131070 :           for (unsigned j = 0; j < exit_edges.length (); ++j)
     510                 :     385090 :             bitmap_set_bit (exit_bbs, exit_edges[j]->dest->index);
     511                 :     180444 :           bitmap_set_bit (exit_bbs, loop->header->index);
     512                 :     180444 :           do_rpo_vn (cfun, entry, exit_bbs);
     513                 :     180444 :           BITMAP_FREE (exit_bbs);
     514                 :     360888 :           exit_edges.release ();
     515                 :            :         }
     516                 :            :     }
     517                 :     192162 :   free (bbs);
     518                 :     192162 :   free (copied_bbs);
     519                 :            : 
     520                 :     305619 :   return changed ? TODO_cleanup_cfg : 0;
     521                 :            : }
     522                 :            : 
     523                 :            : /* Initialize the loop structures we need, and finalize after.  */
     524                 :            : 
     525                 :            : unsigned int
     526                 :     686433 : pass_ch::execute (function *fun)
     527                 :            : {
     528                 :     686433 :   loop_optimizer_init (LOOPS_HAVE_PREHEADERS
     529                 :            :                        | LOOPS_HAVE_SIMPLE_LATCHES
     530                 :            :                        | LOOPS_HAVE_RECORDED_EXITS);
     531                 :            : 
     532                 :     686433 :   unsigned int res = copy_headers (fun);
     533                 :            : 
     534                 :     686433 :   loop_optimizer_finalize ();
     535                 :     686433 :   return res;
     536                 :            : }
     537                 :            : 
     538                 :            : /* Assume an earlier phase has already initialized all the loop structures that
     539                 :            :    we need here (and perhaps others too), and that these will be finalized by
     540                 :            :    a later phase.  */
     541                 :            :    
     542                 :            : unsigned int
     543                 :      33906 : pass_ch_vect::execute (function *fun)
     544                 :            : {
     545                 :      33906 :   return copy_headers (fun);
     546                 :            : }
     547                 :            : 
     548                 :            : /* Apply header copying according to a very simple test of do-while shape.  */
     549                 :            : 
     550                 :            : bool
     551                 :     378685 : pass_ch::process_loop_p (class loop *loop)
     552                 :            : {
     553                 :     378685 :   return !do_while_loop_p (loop);
     554                 :            : }
     555                 :            : 
     556                 :            : /* Apply header-copying to loops where we might enable vectorization.  */
     557                 :            : 
     558                 :            : bool
     559                 :      75917 : pass_ch_vect::process_loop_p (class loop *loop)
     560                 :            : {
     561                 :      75917 :   if (!flag_tree_loop_vectorize && !loop->force_vectorize)
     562                 :            :     return false;
     563                 :            : 
     564                 :      71542 :   if (loop->dont_vectorize)
     565                 :            :     return false;
     566                 :            : 
     567                 :            :   /* The vectorizer won't handle anything with multiple exits, so skip.  */
     568                 :      71390 :   edge exit = single_exit (loop);
     569                 :      71390 :   if (!exit)
     570                 :            :     return false;
     571                 :            : 
     572                 :      54828 :   if (!do_while_loop_p (loop))
     573                 :       3256 :     return true;
     574                 :            : 
     575                 :            :   return false;
     576                 :            : }
     577                 :            : 
     578                 :            : } // anon namespace
     579                 :            : 
     580                 :            : gimple_opt_pass *
     581                 :     200540 : make_pass_ch_vect (gcc::context *ctxt)
     582                 :            : {
     583                 :     200540 :   return new pass_ch_vect (ctxt);
     584                 :            : }
     585                 :            : 
     586                 :            : gimple_opt_pass *
     587                 :     200540 : make_pass_ch (gcc::context *ctxt)
     588                 :            : {
     589                 :     200540 :   return new pass_ch (ctxt);
     590                 :            : }

Generated by: LCOV version 1.0

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.