LCOV - code coverage report
Current view: top level - gcc - tree-loop-distribution.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.4 % 1682 1555
Test Date: 2026-10-17 16:30:31 Functions: 90.8 % 87 79
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Loop distribution.
       2              :    Copyright (C) 2006-2026 Free Software Foundation, Inc.
       3              :    Contributed by Georges-Andre Silber <Georges-Andre.Silber@ensmp.fr>
       4              :    and Sebastian Pop <sebastian.pop@amd.com>.
       5              : 
       6              : This file is part of GCC.
       7              : 
       8              : GCC is free software; you can redistribute it and/or modify it
       9              : under the terms of the GNU General Public License as published by the
      10              : Free Software Foundation; either version 3, or (at your option) any
      11              : later version.
      12              : 
      13              : GCC is distributed in the hope that it will be useful, but WITHOUT
      14              : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16              : for more details.
      17              : 
      18              : You should have received a copy of the GNU General Public License
      19              : along with GCC; see the file COPYING3.  If not see
      20              : <http://www.gnu.org/licenses/>.  */
      21              : 
      22              : /* This pass performs loop distribution: for example, the loop
      23              : 
      24              :    |DO I = 2, N
      25              :    |    A(I) = B(I) + C
      26              :    |    D(I) = A(I-1)*E
      27              :    |ENDDO
      28              : 
      29              :    is transformed to
      30              : 
      31              :    |DOALL I = 2, N
      32              :    |   A(I) = B(I) + C
      33              :    |ENDDO
      34              :    |
      35              :    |DOALL I = 2, N
      36              :    |   D(I) = A(I-1)*E
      37              :    |ENDDO
      38              : 
      39              :    Loop distribution is the dual of loop fusion.  It separates statements
      40              :    of a loop (or loop nest) into multiple loops (or loop nests) with the
      41              :    same loop header.  The major goal is to separate statements which may
      42              :    be vectorized from those that can't.  This pass implements distribution
      43              :    in the following steps:
      44              : 
      45              :      1) Seed partitions with specific type statements.  For now we support
      46              :         two types seed statements: statement defining variable used outside
      47              :         of loop; statement storing to memory.
      48              :      2) Build reduced dependence graph (RDG) for loop to be distributed.
      49              :         The vertices (RDG:V) model all statements in the loop and the edges
      50              :         (RDG:E) model flow and control dependencies between statements.
      51              :      3) Apart from RDG, compute data dependencies between memory references.
      52              :      4) Starting from seed statement, build up partition by adding depended
      53              :         statements according to RDG's dependence information.  Partition is
      54              :         classified as parallel type if it can be executed paralleled; or as
      55              :         sequential type if it can't.  Parallel type partition is further
      56              :         classified as different builtin kinds if it can be implemented as
      57              :         builtin function calls.
      58              :      5) Build partition dependence graph (PG) based on data dependencies.
      59              :         The vertices (PG:V) model all partitions and the edges (PG:E) model
      60              :         all data dependencies between every partitions pair.  In general,
      61              :         data dependence is either compilation time known or unknown.  In C
      62              :         family languages, there exists quite amount compilation time unknown
      63              :         dependencies because of possible alias relation of data references.
      64              :         We categorize PG's edge to two types: "true" edge that represents
      65              :         compilation time known data dependencies; "alias" edge for all other
      66              :         data dependencies.
      67              :      6) Traverse subgraph of PG as if all "alias" edges don't exist.  Merge
      68              :         partitions in each strong connected component (SCC) correspondingly.
      69              :         Build new PG for merged partitions.
      70              :      7) Traverse PG again and this time with both "true" and "alias" edges
      71              :         included.  We try to break SCCs by removing some edges.  Because
      72              :         SCCs by "true" edges are all fused in step 6), we can break SCCs
      73              :         by removing some "alias" edges.  It's NP-hard to choose optimal
      74              :         edge set, fortunately simple approximation is good enough for us
      75              :         given the small problem scale.
      76              :      8) Collect all data dependencies of the removed "alias" edges.  Create
      77              :         runtime alias checks for collected data dependencies.
      78              :      9) Version loop under the condition of runtime alias checks.  Given
      79              :         loop distribution generally introduces additional overhead, it is
      80              :         only useful if vectorization is achieved in distributed loop.  We
      81              :         version loop with internal function call IFN_LOOP_DIST_ALIAS.  If
      82              :         no distributed loop can be vectorized, we simply remove distributed
      83              :         loops and recover to the original one.
      84              : 
      85              :    TODO:
      86              :      1) We only distribute innermost two-level loop nest now.  We should
      87              :         extend it for arbitrary loop nests in the future.
      88              :      2) We only fuse partitions in SCC now.  A better fusion algorithm is
      89              :         desired to minimize loop overhead, maximize parallelism and maximize
      90              :         data reuse.  */
      91              : 
      92              : #include "config.h"
      93              : #include "system.h"
      94              : #include "coretypes.h"
      95              : #include "backend.h"
      96              : #include "tree.h"
      97              : #include "gimple.h"
      98              : #include "cfghooks.h"
      99              : #include "tree-pass.h"
     100              : #include "ssa.h"
     101              : #include "gimple-pretty-print.h"
     102              : #include "fold-const.h"
     103              : #include "cfganal.h"
     104              : #include "gimple-iterator.h"
     105              : #include "gimplify-me.h"
     106              : #include "stor-layout.h"
     107              : #include "tree-cfg.h"
     108              : #include "tree-ssa-loop-manip.h"
     109              : #include "tree-ssa-loop-ivopts.h"
     110              : #include "tree-ssa-loop.h"
     111              : #include "tree-into-ssa.h"
     112              : #include "tree-ssa.h"
     113              : #include "cfgloop.h"
     114              : #include "tree-scalar-evolution.h"
     115              : #include "tree-vectorizer.h"
     116              : #include "tree-eh.h"
     117              : #include "gimple-fold.h"
     118              : #include "tree-affine.h"
     119              : #include "intl.h"
     120              : #include "rtl.h"
     121              : #include "memmodel.h"
     122              : #include "optabs.h"
     123              : #include "tree-ssa-loop-niter.h"
     124              : 
     125              : 
     126              : #define MAX_DATAREFS_NUM \
     127              :         ((unsigned) param_loop_max_datarefs_for_datadeps)
     128              : 
     129              : /* Threshold controlling number of distributed partitions.  Given it may
     130              :    be unnecessary if a memory stream cost model is invented in the future,
     131              :    we define it as a temporary macro, rather than a parameter.  */
     132              : #define NUM_PARTITION_THRESHOLD (4)
     133              : 
     134              : /* Hashtable helpers.  */
     135              : 
     136              : struct ddr_hasher : nofree_ptr_hash <struct data_dependence_relation>
     137              : {
     138              :   static inline hashval_t hash (const data_dependence_relation *);
     139              :   static inline bool equal (const data_dependence_relation *,
     140              :                             const data_dependence_relation *);
     141              : };
     142              : 
     143              : /* Hash function for data dependence.  */
     144              : 
     145              : inline hashval_t
     146      8810150 : ddr_hasher::hash (const data_dependence_relation *ddr)
     147              : {
     148      8810150 :   inchash::hash h;
     149      8810150 :   h.add_ptr (DDR_A (ddr));
     150      8810150 :   h.add_ptr (DDR_B (ddr));
     151      8810150 :   return h.end ();
     152              : }
     153              : 
     154              : /* Hash table equality function for data dependence.  */
     155              : 
     156              : inline bool
     157      7810985 : ddr_hasher::equal (const data_dependence_relation *ddr1,
     158              :                    const data_dependence_relation *ddr2)
     159              : {
     160      7810985 :   return (DDR_A (ddr1) == DDR_A (ddr2) && DDR_B (ddr1) == DDR_B (ddr2));
     161              : }
     162              : 
     163              : 
     164              : 
     165              : #define DR_INDEX(dr)      ((uintptr_t) (dr)->aux)
     166              : 
     167              : /* A Reduced Dependence Graph (RDG) vertex representing a statement.  */
     168              : struct rdg_vertex
     169              : {
     170              :   /* The statement represented by this vertex.  */
     171              :   gimple *stmt;
     172              : 
     173              :   /* Vector of data-references in this statement.  */
     174              :   vec<data_reference_p> datarefs;
     175              : 
     176              :   /* True when the statement contains a write to memory.  */
     177              :   bool has_mem_write;
     178              : 
     179              :   /* True when the statement contains a read from memory.  */
     180              :   bool has_mem_reads;
     181              : };
     182              : 
     183              : #define RDGV_STMT(V)     ((struct rdg_vertex *) ((V)->data))->stmt
     184              : #define RDGV_DATAREFS(V) ((struct rdg_vertex *) ((V)->data))->datarefs
     185              : #define RDGV_HAS_MEM_WRITE(V) ((struct rdg_vertex *) ((V)->data))->has_mem_write
     186              : #define RDGV_HAS_MEM_READS(V) ((struct rdg_vertex *) ((V)->data))->has_mem_reads
     187              : #define RDG_STMT(RDG, I) RDGV_STMT (&(RDG->vertices[I]))
     188              : #define RDG_DATAREFS(RDG, I) RDGV_DATAREFS (&(RDG->vertices[I]))
     189              : #define RDG_MEM_WRITE_STMT(RDG, I) RDGV_HAS_MEM_WRITE (&(RDG->vertices[I]))
     190              : #define RDG_MEM_READS_STMT(RDG, I) RDGV_HAS_MEM_READS (&(RDG->vertices[I]))
     191              : 
     192              : /* Data dependence type.  */
     193              : 
     194              : enum rdg_dep_type
     195              : {
     196              :   /* Read After Write (RAW).  */
     197              :   flow_dd = 'f',
     198              : 
     199              :   /* Control dependence (execute conditional on).  */
     200              :   control_dd = 'c'
     201              : };
     202              : 
     203              : /* Dependence information attached to an edge of the RDG.  */
     204              : 
     205              : struct rdg_edge
     206              : {
     207              :   /* Type of the dependence.  */
     208              :   enum rdg_dep_type type;
     209              : };
     210              : 
     211              : #define RDGE_TYPE(E)        ((struct rdg_edge *) ((E)->data))->type
     212              : 
     213              : /* Kind of distributed loop.  */
     214              : enum partition_kind {
     215              :     PKIND_NORMAL,
     216              :     /* Partial memset stands for a partition can be distributed into a loop
     217              :        of memset calls, rather than a single memset call.  It's handled just
     218              :        like a normal partition, i.e, distributed as separate loop, no memset
     219              :        call is generated.
     220              : 
     221              :        Note: This is a hacking fix trying to distribute ZERO-ing stmt in a
     222              :        loop nest as deep as possible.  As a result, parloop achieves better
     223              :        parallelization by parallelizing deeper loop nest.  This hack should
     224              :        be unnecessary and removed once distributed memset can be understood
     225              :        and analyzed in data reference analysis.  See PR82604 for more.  */
     226              :     PKIND_PARTIAL_MEMSET,
     227              :     PKIND_MEMSET, PKIND_MEMCPY, PKIND_MEMMOVE
     228              : };
     229              : 
     230              : /* Type of distributed loop.  */
     231              : enum partition_type {
     232              :     /* The distributed loop can be executed parallelly.  */
     233              :     PTYPE_PARALLEL = 0,
     234              :     /* The distributed loop has to be executed sequentially.  */
     235              :     PTYPE_SEQUENTIAL
     236              : };
     237              : 
     238              : /* Builtin info for loop distribution.  */
     239              : struct builtin_info
     240              : {
     241              :   /* data-references a kind != PKIND_NORMAL partition is about.  */
     242              :   data_reference_p dst_dr;
     243              :   data_reference_p src_dr;
     244              :   /* Base address and size of memory objects operated by the builtin.  Note
     245              :      both dest and source memory objects must have the same size.  */
     246              :   tree dst_base;
     247              :   tree src_base;
     248              :   tree size;
     249              :   /* Base and offset part of dst_base after stripping constant offset.  This
     250              :      is only used in memset builtin distribution for now.  */
     251              :   tree dst_base_base;
     252              :   unsigned HOST_WIDE_INT dst_base_offset;
     253              : };
     254              : 
     255              : /* Partition for loop distribution.  */
     256              : struct partition
     257              : {
     258              :   /* Statements of the partition.  */
     259              :   bitmap stmts;
     260              :   /* True if the partition defines variable which is used outside of loop.  */
     261              :   bool reduction_p;
     262              :   location_t loc;
     263              :   enum partition_kind kind;
     264              :   enum partition_type type;
     265              :   /* Data references in the partition.  */
     266              :   bitmap datarefs;
     267              :   /* Information of builtin partition.  */
     268              :   struct builtin_info *builtin;
     269              : };
     270              : 
     271              : /* Partitions are fused because of different reasons.  */
     272              : enum fuse_type
     273              : {
     274              :   FUSE_NON_BUILTIN = 0,
     275              :   FUSE_REDUCTION = 1,
     276              :   FUSE_SHARE_REF = 2,
     277              :   FUSE_SAME_SCC = 3,
     278              :   FUSE_FINALIZE = 4
     279              : };
     280              : 
     281              : /* Description on different fusing reason.  */
     282              : static const char *fuse_message[] = {
     283              :   "they are non-builtins",
     284              :   "they have reductions",
     285              :   "they have shared memory refs",
     286              :   "they are in the same dependence scc",
     287              :   "there is no point to distribute loop"};
     288              : 
     289              : 
     290              : /* Dump vertex I in RDG to FILE.  */
     291              : 
     292              : static void
     293          871 : dump_rdg_vertex (FILE *file, struct graph *rdg, int i)
     294              : {
     295          871 :   struct vertex *v = &(rdg->vertices[i]);
     296          871 :   struct graph_edge *e;
     297              : 
     298          871 :   fprintf (file, "(vertex %d: (%s%s) (in:", i,
     299          871 :            RDG_MEM_WRITE_STMT (rdg, i) ? "w" : "",
     300          871 :            RDG_MEM_READS_STMT (rdg, i) ? "r" : "");
     301              : 
     302          871 :   if (v->pred)
     303         2903 :     for (e = v->pred; e; e = e->pred_next)
     304         2032 :       fprintf (file, " %d", e->src);
     305              : 
     306          871 :   fprintf (file, ") (out:");
     307              : 
     308          871 :   if (v->succ)
     309         2758 :     for (e = v->succ; e; e = e->succ_next)
     310         2032 :       fprintf (file, " %d", e->dest);
     311              : 
     312          871 :   fprintf (file, ")\n");
     313          871 :   print_gimple_stmt (file, RDGV_STMT (v), 0, TDF_VOPS|TDF_MEMSYMS);
     314          871 :   fprintf (file, ")\n");
     315          871 : }
     316              : 
     317              : /* Call dump_rdg_vertex on stderr.  */
     318              : 
     319              : DEBUG_FUNCTION void
     320            0 : debug_rdg_vertex (struct graph *rdg, int i)
     321              : {
     322            0 :   dump_rdg_vertex (stderr, rdg, i);
     323            0 : }
     324              : 
     325              : /* Dump the reduced dependence graph RDG to FILE.  */
     326              : 
     327              : static void
     328           70 : dump_rdg (FILE *file, struct graph *rdg)
     329              : {
     330           70 :   fprintf (file, "(rdg\n");
     331         1011 :   for (int i = 0; i < rdg->n_vertices; i++)
     332          871 :     dump_rdg_vertex (file, rdg, i);
     333           70 :   fprintf (file, ")\n");
     334           70 : }
     335              : 
     336              : /* Call dump_rdg on stderr.  */
     337              : 
     338              : DEBUG_FUNCTION void
     339            0 : debug_rdg (struct graph *rdg)
     340              : {
     341            0 :   dump_rdg (stderr, rdg);
     342            0 : }
     343              : 
     344              : static void
     345            0 : dot_rdg_1 (FILE *file, struct graph *rdg)
     346              : {
     347            0 :   int i;
     348            0 :   pretty_printer pp;
     349            0 :   pp_needs_newline (&pp) = false;
     350            0 :   pp.set_output_stream (file);
     351              : 
     352            0 :   fprintf (file, "digraph RDG {\n");
     353              : 
     354            0 :   for (i = 0; i < rdg->n_vertices; i++)
     355              :     {
     356            0 :       struct vertex *v = &(rdg->vertices[i]);
     357            0 :       struct graph_edge *e;
     358              : 
     359            0 :       fprintf (file, "%d [label=\"[%d] ", i, i);
     360            0 :       pp_gimple_stmt_1 (&pp, RDGV_STMT (v), 0, TDF_SLIM);
     361            0 :       pp_flush (&pp);
     362            0 :       fprintf (file, "\"]\n");
     363              : 
     364              :       /* Highlight reads from memory.  */
     365            0 :       if (RDG_MEM_READS_STMT (rdg, i))
     366            0 :        fprintf (file, "%d [style=filled, fillcolor=green]\n", i);
     367              : 
     368              :       /* Highlight stores to memory.  */
     369            0 :       if (RDG_MEM_WRITE_STMT (rdg, i))
     370            0 :        fprintf (file, "%d [style=filled, fillcolor=red]\n", i);
     371              : 
     372            0 :       if (v->succ)
     373            0 :        for (e = v->succ; e; e = e->succ_next)
     374            0 :          switch (RDGE_TYPE (e))
     375              :            {
     376            0 :            case flow_dd:
     377              :              /* These are the most common dependences: don't print these. */
     378            0 :              fprintf (file, "%d -> %d \n", i, e->dest);
     379            0 :              break;
     380              : 
     381            0 :            case control_dd:
     382            0 :              fprintf (file, "%d -> %d [label=control] \n", i, e->dest);
     383            0 :              break;
     384              : 
     385            0 :            default:
     386            0 :              gcc_unreachable ();
     387              :            }
     388              :     }
     389              : 
     390            0 :   fprintf (file, "}\n\n");
     391            0 : }
     392              : 
     393              : /* Display the Reduced Dependence Graph using dotty.  */
     394              : 
     395              : DEBUG_FUNCTION void
     396            0 : dot_rdg (struct graph *rdg)
     397              : {
     398              :   /* When debugging, you may want to enable the following code.  */
     399              : #ifdef HAVE_POPEN
     400            0 :   FILE *file = popen ("dot -Tx11", "w");
     401            0 :   if (!file)
     402              :     return;
     403            0 :   dot_rdg_1 (file, rdg);
     404            0 :   fflush (file);
     405            0 :   close (fileno (file));
     406            0 :   pclose (file);
     407              : #else
     408              :   dot_rdg_1 (stderr, rdg);
     409              : #endif
     410              : }
     411              : 
     412              : /* Returns the index of STMT in RDG.  */
     413              : 
     414              : static int
     415     13541215 : rdg_vertex_for_stmt (struct graph *rdg ATTRIBUTE_UNUSED, gimple *stmt)
     416              : {
     417     13541215 :   int index = gimple_uid (stmt);
     418     13541215 :   gcc_checking_assert (index == -1 || RDG_STMT (rdg, index) == stmt);
     419     13541215 :   return index;
     420              : }
     421              : 
     422              : /* Creates dependence edges in RDG for all the uses of DEF.  IDEF is
     423              :    the index of DEF in RDG.  */
     424              : 
     425              : static void
     426      1836581 : create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef)
     427              : {
     428      1836581 :   use_operand_p imm_use_p;
     429      1836581 :   imm_use_iterator iterator;
     430              : 
     431      4989049 :   FOR_EACH_IMM_USE_FAST (imm_use_p, iterator, def)
     432              :     {
     433      3152468 :       struct graph_edge *e;
     434      3152468 :       int use = rdg_vertex_for_stmt (rdg, USE_STMT (imm_use_p));
     435              : 
     436      3152468 :       if (use < 0)
     437       459646 :         continue;
     438              : 
     439      2692822 :       e = add_edge (rdg, idef, use);
     440      2692822 :       e->data = XNEW (struct rdg_edge);
     441      2692822 :       RDGE_TYPE (e) = flow_dd;
     442      1836581 :     }
     443      1836581 : }
     444              : 
     445              : /* Creates an edge for the control dependences of BB to the vertex V.  */
     446              : 
     447              : static void
     448      2341201 : create_edge_for_control_dependence (struct graph *rdg, basic_block bb,
     449              :                                     int v, control_dependences *cd)
     450              : {
     451      2341201 :   bitmap_iterator bi;
     452      2341201 :   unsigned edge_n;
     453      6655077 :   EXECUTE_IF_SET_IN_BITMAP (cd->get_edges_dependent_on (bb->index),
     454              :                             0, edge_n, bi)
     455              :     {
     456      4313876 :       basic_block cond_bb = cd->get_edge_src (edge_n);
     457      4313876 :       gimple *stmt = *gsi_last_bb (cond_bb);
     458      4313876 :       if (stmt && is_ctrl_stmt (stmt))
     459              :         {
     460      3866765 :           struct graph_edge *e;
     461      3866765 :           int c = rdg_vertex_for_stmt (rdg, stmt);
     462      3866765 :           if (c < 0)
     463      1268529 :             continue;
     464              : 
     465      2598236 :           e = add_edge (rdg, c, v);
     466      2598236 :           e->data = XNEW (struct rdg_edge);
     467      2598236 :           RDGE_TYPE (e) = control_dd;
     468              :         }
     469              :     }
     470      2341201 : }
     471              : 
     472              : /* Creates the edges of the reduced dependence graph RDG.  */
     473              : 
     474              : static void
     475       150878 : create_rdg_flow_edges (struct graph *rdg)
     476              : {
     477       150878 :   int i;
     478       150878 :   def_operand_p def_p;
     479       150878 :   ssa_op_iter iter;
     480              : 
     481      2420288 :   for (i = 0; i < rdg->n_vertices; i++)
     482      6375401 :     FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i),
     483              :                               iter, SSA_OP_DEF)
     484      1836581 :       create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i);
     485       150878 : }
     486              : 
     487              : /* Creates the edges of the reduced dependence graph RDG.  */
     488              : 
     489              : static void
     490       142585 : create_rdg_cd_edges (struct graph *rdg, control_dependences *cd, loop_p loop)
     491              : {
     492       142585 :   int i;
     493              : 
     494      2357851 :   for (i = 0; i < rdg->n_vertices; i++)
     495              :     {
     496      2215266 :       gimple *stmt = RDG_STMT (rdg, i);
     497      2215266 :       if (gimple_code (stmt) == GIMPLE_PHI)
     498              :         {
     499       431655 :           edge_iterator ei;
     500       431655 :           edge e;
     501      1302413 :           FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
     502       870758 :             if (flow_bb_inside_loop_p (loop, e->src))
     503       557590 :               create_edge_for_control_dependence (rdg, e->src, i, cd);
     504              :         }
     505              :       else
     506      1783611 :         create_edge_for_control_dependence (rdg, gimple_bb (stmt), i, cd);
     507              :     }
     508       142585 : }
     509              : 
     510              : 
     511              : class loop_distribution
     512              : {
     513              :   private:
     514              :   /* The loop (nest) to be distributed.  */
     515              :   vec<loop_p> loop_nest;
     516              : 
     517              :   /* Vector of data references in the loop to be distributed.  */
     518              :   vec<data_reference_p> datarefs_vec;
     519              : 
     520              :   /* If there is nonaddressable data reference in above vector.  */
     521              :   bool has_nonaddressable_dataref_p;
     522              : 
     523              :   /* Store index of data reference in aux field.  */
     524              : 
     525              :   /* Hash table for data dependence relation in the loop to be distributed.  */
     526              :   hash_table<ddr_hasher> *ddrs_table;
     527              : 
     528              :   /* Array mapping basic block's index to its topological order.  */
     529              :   int *bb_top_order_index;
     530              :   /* And size of the array.  */
     531              :   int bb_top_order_index_size;
     532              : 
     533              :   /* Build the vertices of the reduced dependence graph RDG.  Return false
     534              :      if that failed.  */
     535              :   bool create_rdg_vertices (struct graph *rdg, const vec<gimple *> &stmts,
     536              :                             loop_p loop);
     537              : 
     538              :   /* Initialize STMTS with all the statements of LOOP.  We use topological
     539              :      order to discover all statements.  The order is important because
     540              :      generate_loops_for_partition is using the same traversal for identifying
     541              :      statements in loop copies.  */
     542              :   void stmts_from_loop (class loop *loop, vec<gimple *> *stmts);
     543              : 
     544              : 
     545              :   /* Build the Reduced Dependence Graph (RDG) with one vertex per statement of
     546              :      LOOP, and one edge per flow dependence or control dependence from control
     547              :      dependence CD.  During visiting each statement, data references are also
     548              :      collected and recorded in global data DATAREFS_VEC.  */
     549              :   struct graph * build_rdg (class loop *loop, control_dependences *cd);
     550              : 
     551              : /* Merge PARTITION into the partition DEST.  RDG is the reduced dependence
     552              :    graph and we update type for result partition if it is non-NULL.  */
     553              :   void partition_merge_into (struct graph *rdg,
     554              :                              partition *dest, partition *partition,
     555              :                              enum fuse_type ft);
     556              : 
     557              : 
     558              :   /* Return data dependence relation for data references A and B.  The two
     559              :      data references must be in lexicographic order wrto reduced dependence
     560              :      graph RDG.  We firstly try to find ddr from global ddr hash table.  If
     561              :      it doesn't exist, compute the ddr and cache it.  */
     562              :   data_dependence_relation * get_data_dependence (struct graph *rdg,
     563              :                                                   data_reference_p a,
     564              :                                                   data_reference_p b);
     565              : 
     566              : 
     567              :   /* In reduced dependence graph RDG for loop distribution, return true if
     568              :      dependence between references DR1 and DR2 leads to a dependence cycle
     569              :      and such dependence cycle can't be resolved by runtime alias check.  */
     570              :   bool data_dep_in_cycle_p (struct graph *rdg, data_reference_p dr1,
     571              :                             data_reference_p dr2);
     572              : 
     573              : 
     574              :   /* Given reduced dependence graph RDG, PARTITION1 and PARTITION2, update
     575              :      PARTITION1's type after merging PARTITION2 into PARTITION1.  */
     576              :   void update_type_for_merge (struct graph *rdg,
     577              :                               partition *partition1, partition *partition2);
     578              : 
     579              : 
     580              :   /* Returns a partition with all the statements needed for computing
     581              :      the vertex V of the RDG, also including the loop exit conditions.  */
     582              :   partition *build_rdg_partition_for_vertex (struct graph *rdg, int v);
     583              : 
     584              :   /* Given data references DST_DR and SRC_DR in loop nest LOOP and RDG, classify
     585              :      if it forms builtin memcpy or memmove call.  */
     586              :   void classify_builtin_ldst (loop_p loop, struct graph *rdg, partition *partition,
     587              :                               data_reference_p dst_dr, data_reference_p src_dr);
     588              : 
     589              :   /* Classifies the builtin kind we can generate for PARTITION of RDG and LOOP.
     590              :      For the moment we detect memset, memcpy and memmove patterns.  Bitmap
     591              :      STMT_IN_ALL_PARTITIONS contains statements belonging to all partitions.
     592              :      Returns true if there is a reduction in all partitions and we
     593              :      possibly did not mark PARTITION as having one for this reason.  */
     594              : 
     595              :   bool
     596              :   classify_partition (loop_p loop,
     597              :                       struct graph *rdg, partition *partition,
     598              :                       bitmap stmt_in_all_partitions);
     599              : 
     600              : 
     601              :   /* Returns true when PARTITION1 and PARTITION2 access the same memory
     602              :      object in RDG.  */
     603              :   bool share_memory_accesses (struct graph *rdg,
     604              :                               partition *partition1, partition *partition2);
     605              : 
     606              :   /* For each seed statement in STARTING_STMTS, this function builds
     607              :      partition for it by adding depended statements according to RDG.
     608              :      All partitions are recorded in PARTITIONS.  */
     609              :   void rdg_build_partitions (struct graph *rdg,
     610              :                              vec<gimple *> starting_stmts,
     611              :                              vec<partition *> *partitions);
     612              : 
     613              :   /* Compute partition dependence created by the data references in DRS1
     614              :      and DRS2, modify and return DIR according to that.  IF ALIAS_DDR is
     615              :      not NULL, we record dependence introduced by possible alias between
     616              :      two data references in ALIAS_DDRS; otherwise, we simply ignore such
     617              :      dependence as if it doesn't exist at all.  */
     618              :   int pg_add_dependence_edges (struct graph *rdg, int dir, bitmap drs1,
     619              :                                bitmap drs2, vec<ddr_p> *alias_ddrs);
     620              : 
     621              : 
     622              :   /* Build and return partition dependence graph for PARTITIONS.  RDG is
     623              :      reduced dependence graph for the loop to be distributed.  If IGNORE_ALIAS_P
     624              :      is true, data dependence caused by possible alias between references
     625              :      is ignored, as if it doesn't exist at all; otherwise all dependences
     626              :      are considered.  */
     627              :   struct graph *build_partition_graph (struct graph *rdg,
     628              :                                        vec<struct partition *> *partitions,
     629              :                                        bool ignore_alias_p);
     630              : 
     631              :   /* Given reduced dependence graph RDG merge strong connected components
     632              :      of PARTITIONS.  If IGNORE_ALIAS_P is true, data dependence caused by
     633              :      possible alias between references is ignored, as if it doesn't exist
     634              :      at all; otherwise all dependences are considered.  */
     635              :   void merge_dep_scc_partitions (struct graph *rdg, vec<struct partition *>
     636              :                                  *partitions, bool ignore_alias_p);
     637              : 
     638              : /* This is the main function breaking strong connected components in
     639              :    PARTITIONS giving reduced dependence graph RDG.  Store data dependence
     640              :    relations for runtime alias check in ALIAS_DDRS.  */
     641              :   void break_alias_scc_partitions (struct graph *rdg, vec<struct partition *>
     642              :                                    *partitions, vec<ddr_p> *alias_ddrs);
     643              : 
     644              : 
     645              :   /* Fuse PARTITIONS of LOOP if necessary before finalizing distribution.
     646              :      ALIAS_DDRS contains ddrs which need runtime alias check.  */
     647              :   void finalize_partitions (class loop *loop, vec<struct partition *>
     648              :                             *partitions, vec<ddr_p> *alias_ddrs);
     649              : 
     650              :   /* Distributes the code from LOOP in such a way that producer statements
     651              :      are placed before consumer statements.  Tries to separate only the
     652              :      statements from STMTS into separate loops.  Returns the number of
     653              :      distributed loops.  Set NB_CALLS to number of generated builtin calls.
     654              :      Set *DESTROY_P to whether LOOP needs to be destroyed.  */
     655              :   int distribute_loop (class loop *loop, const vec<gimple *> &stmts,
     656              :                        control_dependences *cd, int *nb_calls, bool *destroy_p,
     657              :                        bool only_patterns_p);
     658              : 
     659              :   /* Transform loops which mimic the effects of builtins rawmemchr or strlen and
     660              :      replace them accordingly.  */
     661              :   bool transform_reduction_loop (loop_p loop);
     662              : 
     663              :   /* Compute topological order for basic blocks.  Topological order is
     664              :      needed because data dependence is computed for data references in
     665              :      lexicographical order.  */
     666              :   void bb_top_order_init (void);
     667              : 
     668              :   void bb_top_order_destroy (void);
     669              : 
     670              :   public:
     671              : 
     672              :   /* Getter for bb_top_order.  */
     673              : 
     674      3133767 :   inline int get_bb_top_order_index_size (void)
     675              :     {
     676      3133767 :       return bb_top_order_index_size;
     677              :     }
     678              : 
     679      6267534 :   inline int get_bb_top_order_index (int i)
     680              :     {
     681      6267534 :       return bb_top_order_index[i];
     682              :     }
     683              : 
     684              :   unsigned int execute (function *fun);
     685              : };
     686              : 
     687              : 
     688              : /* If X has a smaller topological sort number than Y, returns -1;
     689              :    if greater, returns 1.  */
     690              : static int
     691      3133767 : bb_top_order_cmp_r (const void *x, const void *y, void *loop)
     692              : {
     693      3133767 :   loop_distribution *_loop =
     694              :     (loop_distribution *) loop;
     695              : 
     696      3133767 :   basic_block bb1 = *(const basic_block *) x;
     697      3133767 :   basic_block bb2 = *(const basic_block *) y;
     698              : 
     699      3133767 :   int bb_top_order_index_size = _loop->get_bb_top_order_index_size ();
     700              : 
     701      3133767 :   gcc_assert (bb1->index < bb_top_order_index_size
     702              :               && bb2->index < bb_top_order_index_size);
     703      3133767 :   gcc_assert (bb1 == bb2
     704              :               || _loop->get_bb_top_order_index(bb1->index)
     705              :                  != _loop->get_bb_top_order_index(bb2->index));
     706              : 
     707      3133767 :   return (_loop->get_bb_top_order_index(bb1->index) -
     708      3133767 :           _loop->get_bb_top_order_index(bb2->index));
     709              : }
     710              : 
     711              : bool
     712       152506 : loop_distribution::create_rdg_vertices (struct graph *rdg,
     713              :                                         const vec<gimple *> &stmts,
     714              :                                         loop_p loop)
     715              : {
     716       152506 :   int i;
     717       152506 :   gimple *stmt;
     718              : 
     719      2439299 :   FOR_EACH_VEC_ELT (stmts, i, stmt)
     720              :     {
     721      2288421 :       struct vertex *v = &(rdg->vertices[i]);
     722              : 
     723              :       /* Record statement to vertex mapping.  */
     724      2288421 :       gimple_set_uid (stmt, i);
     725              : 
     726      2288421 :       v->data = XNEW (struct rdg_vertex);
     727      2288421 :       RDGV_STMT (v) = stmt;
     728      2288421 :       RDGV_DATAREFS (v).create (0);
     729      2288421 :       RDGV_HAS_MEM_WRITE (v) = false;
     730      2288421 :       RDGV_HAS_MEM_READS (v) = false;
     731      2288421 :       if (gimple_code (stmt) == GIMPLE_PHI)
     732       455170 :         continue;
     733              : 
     734      1833251 :       unsigned drp = datarefs_vec.length ();
     735      1833251 :       if (!find_data_references_in_stmt (loop, stmt, &datarefs_vec))
     736              :         return false;
     737      2744686 :       for (unsigned j = drp; j < datarefs_vec.length (); ++j)
     738              :         {
     739       457893 :           data_reference_p dr = datarefs_vec[j];
     740       457893 :           if (DR_IS_READ (dr))
     741       245090 :             RDGV_HAS_MEM_READS (v) = true;
     742              :           else
     743       212803 :             RDGV_HAS_MEM_WRITE (v) = true;
     744       457893 :           RDGV_DATAREFS (v).safe_push (dr);
     745       457893 :           has_nonaddressable_dataref_p |= may_be_nonaddressable_p (dr->ref);
     746              :         }
     747              :     }
     748              :   return true;
     749              : }
     750              : 
     751              : void
     752       152506 : loop_distribution::stmts_from_loop (class loop *loop, vec<gimple *> *stmts)
     753              : {
     754       152506 :   unsigned int i;
     755       152506 :   basic_block *bbs = get_loop_body_in_custom_order (loop, this, bb_top_order_cmp_r);
     756              : 
     757       799710 :   for (i = 0; i < loop->num_nodes; i++)
     758              :     {
     759       494698 :       basic_block bb = bbs[i];
     760              : 
     761      1099306 :       for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
     762       604608 :            gsi_next (&bsi))
     763      1209216 :         if (!virtual_operand_p (gimple_phi_result (bsi.phi ())))
     764       456411 :           stmts->safe_push (bsi.phi ());
     765              : 
     766      4038006 :       for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
     767      3048610 :            gsi_next (&bsi))
     768              :         {
     769      3048610 :           gimple *stmt = gsi_stmt (bsi);
     770      3048610 :           if (gimple_code (stmt) != GIMPLE_LABEL && !is_gimple_debug (stmt))
     771      1853415 :             stmts->safe_push (stmt);
     772              :         }
     773              :     }
     774              : 
     775       152506 :   free (bbs);
     776       152506 : }
     777              : 
     778              : /* Free the reduced dependence graph RDG.  */
     779              : 
     780              : static void
     781       152506 : free_rdg (struct graph *rdg, loop_p loop)
     782              : {
     783       152506 :   int i;
     784              : 
     785      2462332 :   for (i = 0; i < rdg->n_vertices; i++)
     786              :     {
     787      2309826 :       struct vertex *v = &(rdg->vertices[i]);
     788      2309826 :       struct graph_edge *e;
     789              : 
     790      7600884 :       for (e = v->succ; e; e = e->succ_next)
     791      5291058 :         free (e->data);
     792              : 
     793      2309826 :       if (v->data)
     794              :         {
     795      2288421 :           (RDGV_DATAREFS (v)).release ();
     796      2288421 :           free (v->data);
     797              :         }
     798              :     }
     799              : 
     800       152506 :   free_graph (rdg);
     801              : 
     802              :   /* Reset UIDs of stmts still in the loop.  */
     803       152506 :   basic_block *bbs = get_loop_body (loop);
     804       799710 :   for (unsigned i = 0; i < loop->num_nodes; ++i)
     805              :     {
     806       494698 :       basic_block bb = bbs[i];
     807       494698 :       gimple_stmt_iterator gsi;
     808      1099245 :       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     809       604547 :         gimple_set_uid (gsi_stmt (gsi), -1);
     810      4034791 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     811      3045395 :         gimple_set_uid (gsi_stmt (gsi), -1);
     812              :     }
     813       152506 :   free (bbs);
     814       152506 : }
     815              : 
     816              : struct graph *
     817       152506 : loop_distribution::build_rdg (class loop *loop, control_dependences *cd)
     818              : {
     819       152506 :   struct graph *rdg;
     820              : 
     821              :   /* Create the RDG vertices from the stmts of the loop nest.  */
     822       152506 :   auto_vec<gimple *, 10> stmts;
     823       152506 :   stmts_from_loop (loop, &stmts);
     824       305012 :   rdg = new_graph (stmts.length ());
     825       152506 :   if (!create_rdg_vertices (rdg, stmts, loop))
     826              :     {
     827         1628 :       free_rdg (rdg, loop);
     828         1628 :       return NULL;
     829              :     }
     830       150878 :   stmts.release ();
     831              : 
     832       150878 :   create_rdg_flow_edges (rdg);
     833       150878 :   if (cd)
     834       142585 :     create_rdg_cd_edges (rdg, cd, loop);
     835              : 
     836              :   return rdg;
     837       152506 : }
     838              : 
     839              : 
     840              : /* Allocate and initialize a partition from BITMAP.  */
     841              : 
     842              : static partition *
     843       254005 : partition_alloc (void)
     844              : {
     845       254005 :   partition *partition = XCNEW (struct partition);
     846       254005 :   partition->stmts = BITMAP_ALLOC (NULL);
     847       254005 :   partition->reduction_p = false;
     848       254005 :   partition->loc = UNKNOWN_LOCATION;
     849       254005 :   partition->kind = PKIND_NORMAL;
     850       254005 :   partition->type = PTYPE_PARALLEL;
     851       254005 :   partition->datarefs = BITMAP_ALLOC (NULL);
     852       254005 :   return partition;
     853              : }
     854              : 
     855              : /* Free PARTITION.  */
     856              : 
     857              : static void
     858       254005 : partition_free (partition *partition)
     859              : {
     860       254005 :   BITMAP_FREE (partition->stmts);
     861       254005 :   BITMAP_FREE (partition->datarefs);
     862       254005 :   if (partition->builtin)
     863        14347 :     free (partition->builtin);
     864              : 
     865       254005 :   free (partition);
     866       254005 : }
     867              : 
     868              : /* Returns true if the partition can be generated as a builtin.  */
     869              : 
     870              : static bool
     871       365211 : partition_builtin_p (partition *partition)
     872              : {
     873       365211 :   return partition->kind > PKIND_PARTIAL_MEMSET;
     874              : }
     875              : 
     876              : /* Returns true if the partition contains a reduction.  */
     877              : 
     878              : static bool
     879      2084580 : partition_reduction_p (partition *partition)
     880              : {
     881      2084580 :   return partition->reduction_p;
     882              : }
     883              : 
     884              : void
     885        35128 : loop_distribution::partition_merge_into (struct graph *rdg,
     886              :                       partition *dest, partition *partition, enum fuse_type ft)
     887              : {
     888        35128 :   if (dump_file && (dump_flags & TDF_DETAILS))
     889              :     {
     890           42 :       fprintf (dump_file, "Fuse partitions because %s:\n", fuse_message[ft]);
     891           42 :       fprintf (dump_file, "  Part 1: ");
     892           42 :       dump_bitmap (dump_file, dest->stmts);
     893           42 :       fprintf (dump_file, "  Part 2: ");
     894           42 :       dump_bitmap (dump_file, partition->stmts);
     895              :     }
     896              : 
     897        35128 :   dest->kind = PKIND_NORMAL;
     898        35128 :   if (dest->type == PTYPE_PARALLEL)
     899        24797 :     dest->type = partition->type;
     900              : 
     901        35128 :   bitmap_ior_into (dest->stmts, partition->stmts);
     902        35128 :   if (partition_reduction_p (partition))
     903         3613 :     dest->reduction_p = true;
     904              : 
     905              :   /* Further check if any data dependence prevents us from executing the
     906              :      new partition parallelly.  */
     907        35128 :   if (dest->type == PTYPE_PARALLEL && rdg != NULL)
     908         6921 :     update_type_for_merge (rdg, dest, partition);
     909              : 
     910        35128 :   bitmap_ior_into (dest->datarefs, partition->datarefs);
     911        35128 : }
     912              : 
     913              : 
     914              : /* Returns true when DEF is an SSA_NAME defined in LOOP and used after
     915              :    the LOOP.  */
     916              : 
     917              : static bool
     918      4972845 : ssa_name_has_uses_outside_loop_p (tree def, loop_p loop)
     919              : {
     920      4972845 :   imm_use_iterator imm_iter;
     921      4972845 :   use_operand_p use_p;
     922              : 
     923     14767780 :   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, def)
     924              :     {
     925      9932065 :       if (is_gimple_debug (USE_STMT (use_p)))
     926       993224 :         continue;
     927              : 
     928      8938841 :       basic_block use_bb = gimple_bb (USE_STMT (use_p));
     929      8938841 :       if (!flow_bb_inside_loop_p (loop, use_bb))
     930       137130 :         return true;
     931       137130 :     }
     932              : 
     933      4835715 :   return false;
     934              : }
     935              : 
     936              : /* Returns true when STMT defines a scalar variable used after the
     937              :    loop LOOP.  */
     938              : 
     939              : static bool
     940      7292220 : stmt_has_scalar_dependences_outside_loop (loop_p loop, gimple *stmt)
     941              : {
     942      7292220 :   def_operand_p def_p;
     943      7292220 :   ssa_op_iter op_iter;
     944              : 
     945      7292220 :   if (gimple_code (stmt) == GIMPLE_PHI)
     946      1231599 :     return ssa_name_has_uses_outside_loop_p (gimple_phi_result (stmt), loop);
     947              : 
     948      9726412 :   FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
     949      3741246 :     if (ssa_name_has_uses_outside_loop_p (DEF_FROM_PTR (def_p), loop))
     950              :       return true;
     951              : 
     952              :   return false;
     953              : }
     954              : 
     955              : /* Return a copy of LOOP placed before LOOP.  */
     956              : 
     957              : static class loop *
     958         1207 : copy_loop_before (class loop *loop, bool redirect_lc_phi_defs)
     959              : {
     960         1207 :   class loop *res;
     961         1207 :   edge preheader = loop_preheader_edge (loop);
     962              : 
     963         1207 :   initialize_original_copy_tables ();
     964         1207 :   res = slpeel_tree_duplicate_loop_to_edge_cfg (loop, single_exit (loop), NULL,
     965              :                                                 NULL, preheader, NULL, false);
     966         1207 :   gcc_assert (res != NULL);
     967              : 
     968              :   /* When a not last partition is supposed to keep the LC PHIs computed
     969              :      adjust their definitions.  */
     970         1207 :   if (redirect_lc_phi_defs)
     971              :     {
     972            3 :       edge exit = single_exit (loop);
     973           14 :       for (gphi_iterator si = gsi_start_phis (exit->dest); !gsi_end_p (si);
     974           11 :            gsi_next (&si))
     975              :         {
     976           11 :           gphi *phi = si.phi ();
     977           22 :           if (virtual_operand_p (gimple_phi_result (phi)))
     978            3 :             continue;
     979            8 :           use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, exit);
     980            8 :           if (TREE_CODE (USE_FROM_PTR (use_p)) == SSA_NAME)
     981              :             {
     982            5 :               tree new_def = get_current_def (USE_FROM_PTR (use_p));
     983            5 :               if (!new_def)
     984              :                 /* Something defined outside of the loop.  */
     985            2 :                 continue;
     986            3 :               SET_USE (use_p, new_def);
     987              :             }
     988              :         }
     989              :     }
     990              : 
     991         1207 :   free_original_copy_tables ();
     992         1207 :   delete_update_ssa ();
     993              : 
     994         1207 :   return res;
     995              : }
     996              : 
     997              : /* Creates an empty basic block after LOOP.  */
     998              : 
     999              : static void
    1000         1207 : create_bb_after_loop (class loop *loop)
    1001              : {
    1002         1207 :   edge exit = single_exit (loop);
    1003              : 
    1004         1207 :   if (!exit)
    1005              :     return;
    1006              : 
    1007         1207 :   split_edge (exit);
    1008              : }
    1009              : 
    1010              : /* Generate code for PARTITION from the code in LOOP.  The loop is
    1011              :    copied when COPY_P is true.  All the statements not flagged in the
    1012              :    PARTITION bitmap are removed from the loop or from its copy.  The
    1013              :    statements are indexed in sequence inside a basic block, and the
    1014              :    basic blocks of a loop are taken in dom order.  */
    1015              : 
    1016              : static void
    1017         3160 : generate_loops_for_partition (class loop *loop, partition *partition,
    1018              :                               bool copy_p, bool keep_lc_phis_p)
    1019              : {
    1020         3160 :   unsigned i;
    1021         3160 :   basic_block *bbs;
    1022              : 
    1023         3160 :   if (copy_p)
    1024              :     {
    1025         1207 :       int orig_loop_num = loop->orig_loop_num;
    1026         1207 :       loop = copy_loop_before (loop, keep_lc_phis_p);
    1027         1207 :       gcc_assert (loop != NULL);
    1028         1207 :       loop->orig_loop_num = orig_loop_num;
    1029         1207 :       create_preheader (loop, CP_SIMPLE_PREHEADERS);
    1030         1207 :       create_bb_after_loop (loop);
    1031              :     }
    1032              :   else
    1033              :     {
    1034              :       /* Origin number is set to the new versioned loop's num.  */
    1035         1953 :       gcc_assert (loop->orig_loop_num != loop->num);
    1036              :     }
    1037              : 
    1038              :   /* Remove stmts not in the PARTITION bitmap.  */
    1039         3160 :   bbs = get_loop_body_in_dom_order (loop);
    1040              : 
    1041         3160 :   if (MAY_HAVE_DEBUG_BIND_STMTS)
    1042         7963 :     for (i = 0; i < loop->num_nodes; i++)
    1043              :       {
    1044         6144 :         basic_block bb = bbs[i];
    1045              : 
    1046        11506 :         for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
    1047         5362 :              gsi_next (&bsi))
    1048              :           {
    1049         5362 :             gphi *phi = bsi.phi ();
    1050         8896 :             if (!virtual_operand_p (gimple_phi_result (phi))
    1051         5362 :                 && !bitmap_bit_p (partition->stmts, gimple_uid (phi)))
    1052          404 :               reset_debug_uses (phi);
    1053              :           }
    1054              : 
    1055        50179 :         for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
    1056              :           {
    1057        37891 :             gimple *stmt = gsi_stmt (bsi);
    1058        37891 :             if (gimple_code (stmt) != GIMPLE_LABEL
    1059        37891 :                 && !is_gimple_debug (stmt)
    1060        62431 :                 && !bitmap_bit_p (partition->stmts, gimple_uid (stmt)))
    1061         6906 :               reset_debug_uses (stmt);
    1062              :           }
    1063              :       }
    1064              : 
    1065        14213 :   for (i = 0; i < loop->num_nodes; i++)
    1066              :     {
    1067        11053 :       basic_block bb = bbs[i];
    1068        11053 :       edge inner_exit = NULL;
    1069              : 
    1070        11053 :       if (loop != bb->loop_father)
    1071          126 :         inner_exit = single_exit (bb->loop_father);
    1072              : 
    1073        20762 :       for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);)
    1074              :         {
    1075         9709 :           gphi *phi = bsi.phi ();
    1076        16127 :           if (!virtual_operand_p (gimple_phi_result (phi))
    1077         9709 :               && !bitmap_bit_p (partition->stmts, gimple_uid (phi)))
    1078          921 :             remove_phi_node (&bsi, true);
    1079              :           else
    1080         8788 :             gsi_next (&bsi);
    1081              :         }
    1082              : 
    1083        80215 :       for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);)
    1084              :         {
    1085        58109 :           gimple *stmt = gsi_stmt (bsi);
    1086        58109 :           if (gimple_code (stmt) != GIMPLE_LABEL
    1087        58101 :               && !is_gimple_debug (stmt)
    1088       102859 :               && !bitmap_bit_p (partition->stmts, gimple_uid (stmt)))
    1089              :             {
    1090              :               /* In distribution of loop nest, if bb is inner loop's exit_bb,
    1091              :                  we choose its exit edge/path in order to avoid generating
    1092              :                  infinite loop.  For all other cases, we choose an arbitrary
    1093              :                  path through the empty CFG part that this unnecessary
    1094              :                  control stmt controls.  */
    1095        14482 :               if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
    1096              :                 {
    1097          722 :                   if (inner_exit && inner_exit->flags & EDGE_TRUE_VALUE)
    1098            5 :                     gimple_cond_make_true (cond_stmt);
    1099              :                   else
    1100          717 :                     gimple_cond_make_false (cond_stmt);
    1101          722 :                   update_stmt (stmt);
    1102              :                 }
    1103        13760 :               else if (gimple_code (stmt) == GIMPLE_SWITCH)
    1104              :                 {
    1105            0 :                   gswitch *switch_stmt = as_a <gswitch *> (stmt);
    1106            0 :                   gimple_switch_set_index
    1107            0 :                       (switch_stmt, CASE_LOW (gimple_switch_label (switch_stmt, 1)));
    1108            0 :                   update_stmt (stmt);
    1109              :                 }
    1110              :               else
    1111              :                 {
    1112        13760 :                   unlink_stmt_vdef (stmt);
    1113        13760 :                   gsi_remove (&bsi, true);
    1114        13760 :                   release_defs (stmt);
    1115        13760 :                   continue;
    1116              :                 }
    1117              :             }
    1118        44349 :           gsi_next (&bsi);
    1119              :         }
    1120              :     }
    1121              : 
    1122         3160 :   free (bbs);
    1123         3160 : }
    1124              : 
    1125              : /* If VAL memory representation contains the same value in all bytes,
    1126              :    return that value, otherwise return -1.
    1127              :    E.g. for 0x24242424 return 0x24, for IEEE double
    1128              :    747708026454360457216.0 return 0x44, etc.  */
    1129              : 
    1130              : static int
    1131        83071 : const_with_all_bytes_same (tree val)
    1132              : {
    1133        83071 :   unsigned char buf[64];
    1134        83071 :   int i, len;
    1135              : 
    1136        83071 :   if (integer_zerop (val)
    1137        83071 :       || (TREE_CODE (val) == CONSTRUCTOR
    1138          269 :           && !TREE_CLOBBER_P (val)
    1139          269 :           && CONSTRUCTOR_NELTS (val) == 0))
    1140              :     return 0;
    1141              : 
    1142        51063 :   if (real_zerop (val))
    1143              :     {
    1144              :       /* Only return 0 for +0.0, not for -0.0, which doesn't have
    1145              :          an all bytes same memory representation.  Don't transform
    1146              :          -0.0 stores into +0.0 even for !HONOR_SIGNED_ZEROS.  */
    1147         2468 :       switch (TREE_CODE (val))
    1148              :         {
    1149         2455 :         case REAL_CST:
    1150         2455 :           if (!real_isneg (TREE_REAL_CST_PTR (val)))
    1151              :             return 0;
    1152              :           break;
    1153            6 :         case COMPLEX_CST:
    1154            6 :           if (!const_with_all_bytes_same (TREE_REALPART (val))
    1155           12 :               && !const_with_all_bytes_same (TREE_IMAGPART (val)))
    1156              :             return 0;
    1157              :           break;
    1158            7 :         case VECTOR_CST:
    1159            7 :           {
    1160            7 :             unsigned int count = vector_cst_encoded_nelts (val);
    1161            7 :             unsigned int j;
    1162           21 :             for (j = 0; j < count; ++j)
    1163           14 :               if (const_with_all_bytes_same (VECTOR_CST_ENCODED_ELT (val, j)))
    1164              :                 break;
    1165            7 :             if (j == count)
    1166              :               return 0;
    1167              :             break;
    1168              :           }
    1169              :         default:
    1170              :           break;
    1171              :         }
    1172              :     }
    1173              : 
    1174        48623 :   if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
    1175              :     return -1;
    1176              : 
    1177        48623 :   len = native_encode_expr (val, buf, sizeof (buf));
    1178        48623 :   if (len == 0)
    1179              :     return -1;
    1180        31899 :   for (i = 1; i < len; i++)
    1181        26522 :     if (buf[i] != buf[0])
    1182              :       return -1;
    1183         5377 :   return buf[0];
    1184              : }
    1185              : 
    1186              : /* Generate a call to memset for PARTITION in LOOP.  */
    1187              : 
    1188              : static void
    1189         8823 : generate_memset_builtin (class loop *loop, partition *partition)
    1190              : {
    1191         8823 :   gimple_stmt_iterator gsi;
    1192         8823 :   tree mem, fn, nb_bytes;
    1193         8823 :   tree val;
    1194         8823 :   struct builtin_info *builtin = partition->builtin;
    1195         8823 :   gimple *fn_call;
    1196              : 
    1197              :   /* The new statements will be placed before LOOP.  */
    1198         8823 :   gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
    1199              : 
    1200         8823 :   nb_bytes = rewrite_to_non_trapping_overflow (builtin->size);
    1201         8823 :   nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
    1202              :                                        false, GSI_CONTINUE_LINKING);
    1203         8823 :   mem = rewrite_to_non_trapping_overflow (builtin->dst_base);
    1204         8823 :   mem = force_gimple_operand_gsi (&gsi, mem, true, NULL_TREE,
    1205              :                                   false, GSI_CONTINUE_LINKING);
    1206              : 
    1207              :   /* This exactly matches the pattern recognition in classify_partition.  */
    1208         8823 :   val = gimple_assign_rhs1 (DR_STMT (builtin->dst_dr));
    1209              :   /* Handle constants like 0x15151515 and similarly
    1210              :      floating point constants etc. where all bytes are the same.  */
    1211         8823 :   int bytev = const_with_all_bytes_same (val);
    1212         8823 :   if (bytev != -1)
    1213         8722 :     val = build_int_cst (integer_type_node, bytev);
    1214          101 :   else if (TREE_CODE (val) == INTEGER_CST)
    1215            0 :     val = fold_convert (integer_type_node, val);
    1216          101 :   else if (!useless_type_conversion_p (integer_type_node, TREE_TYPE (val)))
    1217              :     {
    1218          101 :       tree tem = make_ssa_name (integer_type_node);
    1219          101 :       gimple *cstmt = gimple_build_assign (tem, NOP_EXPR, val);
    1220          101 :       gsi_insert_after (&gsi, cstmt, GSI_CONTINUE_LINKING);
    1221          101 :       val = tem;
    1222              :     }
    1223              : 
    1224        17646 :   fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
    1225         8823 :   fn_call = gimple_build_call (fn, 3, mem, val, nb_bytes);
    1226         8823 :   gimple_set_location (fn_call, partition->loc);
    1227         8823 :   gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
    1228         8823 :   fold_stmt (&gsi);
    1229              : 
    1230         8823 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1231              :     {
    1232           39 :       fprintf (dump_file, "generated memset");
    1233           39 :       if (bytev == 0)
    1234           33 :         fprintf (dump_file, " zero\n");
    1235              :       else
    1236            6 :         fprintf (dump_file, "\n");
    1237              :     }
    1238         8823 : }
    1239              : 
    1240              : /* Generate a call to memcpy for PARTITION in LOOP.  */
    1241              : 
    1242              : static void
    1243         4773 : generate_memcpy_builtin (class loop *loop, partition *partition)
    1244              : {
    1245         4773 :   gimple_stmt_iterator gsi;
    1246         4773 :   gimple *fn_call;
    1247         4773 :   tree dest, src, fn, nb_bytes;
    1248         4773 :   enum built_in_function kind;
    1249         4773 :   struct builtin_info *builtin = partition->builtin;
    1250              : 
    1251              :   /* The new statements will be placed before LOOP.  */
    1252         4773 :   gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
    1253              : 
    1254         4773 :   nb_bytes = rewrite_to_non_trapping_overflow (builtin->size);
    1255         4773 :   nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
    1256              :                                        false, GSI_CONTINUE_LINKING);
    1257         4773 :   dest = rewrite_to_non_trapping_overflow (builtin->dst_base);
    1258         4773 :   src = rewrite_to_non_trapping_overflow (builtin->src_base);
    1259         4773 :   if (partition->kind == PKIND_MEMCPY
    1260         4773 :       || ! ptr_derefs_may_alias_p (dest, src))
    1261              :     kind = BUILT_IN_MEMCPY;
    1262              :   else
    1263          185 :     kind = BUILT_IN_MEMMOVE;
    1264              :   /* Try harder if we're copying a constant size.  */
    1265          185 :   if (kind == BUILT_IN_MEMMOVE && poly_int_tree_p (nb_bytes))
    1266              :     {
    1267          202 :       aff_tree asrc, adest;
    1268          101 :       tree_to_aff_combination (src, ptr_type_node, &asrc);
    1269          101 :       tree_to_aff_combination (dest, ptr_type_node, &adest);
    1270          101 :       aff_combination_scale (&adest, -1);
    1271          101 :       aff_combination_add (&asrc, &adest);
    1272          202 :       if (aff_comb_cannot_overlap_p (&asrc, wi::to_poly_widest (nb_bytes),
    1273          202 :                                      wi::to_poly_widest (nb_bytes)))
    1274            0 :         kind = BUILT_IN_MEMCPY;
    1275          101 :     }
    1276              : 
    1277         4773 :   dest = force_gimple_operand_gsi (&gsi, dest, true, NULL_TREE,
    1278              :                                    false, GSI_CONTINUE_LINKING);
    1279         4773 :   src = force_gimple_operand_gsi (&gsi, src, true, NULL_TREE,
    1280              :                                   false, GSI_CONTINUE_LINKING);
    1281         4773 :   fn = build_fold_addr_expr (builtin_decl_implicit (kind));
    1282         4773 :   fn_call = gimple_build_call (fn, 3, dest, src, nb_bytes);
    1283         4773 :   gimple_set_location (fn_call, partition->loc);
    1284         4773 :   gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
    1285         4773 :   fold_stmt (&gsi);
    1286              : 
    1287         4773 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1288              :     {
    1289           13 :       if (kind == BUILT_IN_MEMCPY)
    1290           10 :         fprintf (dump_file, "generated memcpy\n");
    1291              :       else
    1292            3 :         fprintf (dump_file, "generated memmove\n");
    1293              :     }
    1294         4773 : }
    1295              : 
    1296              : /* Remove and destroy the loop LOOP.  */
    1297              : 
    1298              : static void
    1299        11440 : destroy_loop (class loop *loop)
    1300              : {
    1301        11440 :   unsigned nbbs = loop->num_nodes;
    1302        11440 :   edge exit = single_exit (loop);
    1303        11440 :   basic_block src = loop_preheader_edge (loop)->src, dest = exit->dest;
    1304        11440 :   basic_block *bbs;
    1305        11440 :   unsigned i;
    1306              : 
    1307        11440 :   bbs = get_loop_body_in_dom_order (loop);
    1308              : 
    1309        11440 :   gimple_stmt_iterator dst_gsi = gsi_after_labels (exit->dest);
    1310        11440 :   bool safe_p = single_pred_p (exit->dest);
    1311        35844 :   for (unsigned i = 0; i < nbbs; ++i)
    1312              :     {
    1313              :       /* We have made sure to not leave any dangling uses of SSA
    1314              :          names defined in the loop.  With the exception of virtuals.
    1315              :          Make sure we replace all uses of virtual defs that will remain
    1316              :          outside of the loop with the bare symbol as delete_basic_block
    1317              :          will release them.  */
    1318        57967 :       for (gphi_iterator gsi = gsi_start_phis (bbs[i]); !gsi_end_p (gsi);
    1319        33563 :            gsi_next (&gsi))
    1320              :         {
    1321        33563 :           gphi *phi = gsi.phi ();
    1322        79524 :           if (virtual_operand_p (gimple_phi_result (phi)))
    1323        12398 :             mark_virtual_phi_result_for_renaming (phi);
    1324              :         }
    1325       142969 :       for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);)
    1326              :         {
    1327        94161 :           gimple *stmt = gsi_stmt (gsi);
    1328        94161 :           tree vdef = gimple_vdef (stmt);
    1329        54141 :           if (vdef && TREE_CODE (vdef) == SSA_NAME)
    1330        13344 :             mark_virtual_operand_for_renaming (vdef);
    1331              :           /* Also move and eventually reset debug stmts.  We can leave
    1332              :              constant values in place in case the stmt dominates the exit.
    1333              :              ???  Non-constant values from the last iteration can be
    1334              :              replaced with final values if we can compute them.  */
    1335        94161 :           if (gimple_debug_bind_p (stmt))
    1336              :             {
    1337        19169 :               tree val = gimple_debug_bind_get_value (stmt);
    1338        19169 :               gsi_move_before (&gsi, &dst_gsi);
    1339        19169 :               if (val
    1340        19169 :                   && (!safe_p
    1341        10328 :                       || !is_gimple_min_invariant (val)
    1342          944 :                       || !dominated_by_p (CDI_DOMINATORS, exit->src, bbs[i])))
    1343              :                 {
    1344        10533 :                   gimple_debug_bind_reset_value (stmt);
    1345        10533 :                   update_stmt (stmt);
    1346              :                 }
    1347              :             }
    1348              :           else
    1349        74992 :             gsi_next (&gsi);
    1350              :         }
    1351              :     }
    1352              : 
    1353        11440 :   redirect_edge_pred (exit, src);
    1354        11440 :   exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
    1355        11440 :   exit->flags |= EDGE_FALLTHRU;
    1356        11440 :   exit->probability = profile_probability::always ();
    1357        11440 :   cancel_loop_tree (loop);
    1358        11440 :   rescan_loop_exit (exit, false, true);
    1359              : 
    1360        11440 :   i = nbbs;
    1361        24404 :   do
    1362              :     {
    1363        24404 :       --i;
    1364        24404 :       delete_basic_block (bbs[i]);
    1365              :     }
    1366        24404 :   while (i != 0);
    1367              : 
    1368        11440 :   free (bbs);
    1369              : 
    1370        11440 :   set_immediate_dominator (CDI_DOMINATORS, dest,
    1371              :                            recompute_dominator (CDI_DOMINATORS, dest));
    1372        11440 : }
    1373              : 
    1374              : /* Generates code for PARTITION.  Return whether LOOP needs to be destroyed.  */
    1375              : 
    1376              : static bool
    1377        16756 : generate_code_for_partition (class loop *loop,
    1378              :                              partition *partition, bool copy_p,
    1379              :                              bool keep_lc_phis_p)
    1380              : {
    1381        16756 :   switch (partition->kind)
    1382              :     {
    1383         3160 :     case PKIND_NORMAL:
    1384         3160 :     case PKIND_PARTIAL_MEMSET:
    1385              :       /* Reductions all have to be in the last partition.  */
    1386         3160 :       gcc_assert (!partition_reduction_p (partition)
    1387              :                   || !copy_p);
    1388         3160 :       generate_loops_for_partition (loop, partition, copy_p,
    1389              :                                     keep_lc_phis_p);
    1390         3160 :       return false;
    1391              : 
    1392         8823 :     case PKIND_MEMSET:
    1393         8823 :       generate_memset_builtin (loop, partition);
    1394         8823 :       break;
    1395              : 
    1396         4773 :     case PKIND_MEMCPY:
    1397         4773 :     case PKIND_MEMMOVE:
    1398         4773 :       generate_memcpy_builtin (loop, partition);
    1399         4773 :       break;
    1400              : 
    1401            0 :     default:
    1402            0 :       gcc_unreachable ();
    1403              :     }
    1404              : 
    1405              :   /* Common tail for partitions we turn into a call.  If this was the last
    1406              :      partition for which we generate code, we have to destroy the loop.  */
    1407        13596 :   if (!copy_p)
    1408        11411 :     return true;
    1409              :   return false;
    1410              : }
    1411              : 
    1412              : data_dependence_relation *
    1413      1571845 : loop_distribution::get_data_dependence (struct graph *rdg, data_reference_p a,
    1414              :                                         data_reference_p b)
    1415              : {
    1416      1571845 :   struct data_dependence_relation ent, **slot;
    1417      1571845 :   struct data_dependence_relation *ddr;
    1418              : 
    1419      1571845 :   gcc_assert (DR_IS_WRITE (a) || DR_IS_WRITE (b));
    1420      1571845 :   gcc_assert (rdg_vertex_for_stmt (rdg, DR_STMT (a))
    1421              :               <= rdg_vertex_for_stmt (rdg, DR_STMT (b)));
    1422      1571845 :   ent.a = a;
    1423      1571845 :   ent.b = b;
    1424      1571845 :   slot = ddrs_table->find_slot (&ent, INSERT);
    1425      1571845 :   if (*slot == NULL)
    1426              :     {
    1427      1188714 :       ddr = initialize_data_dependence_relation (a, b, loop_nest);
    1428      1188714 :       compute_affine_dependence (ddr, loop_nest[0]);
    1429      1188714 :       *slot = ddr;
    1430              :     }
    1431              : 
    1432      1571845 :   return *slot;
    1433              : }
    1434              : 
    1435              : bool
    1436       261019 : loop_distribution::data_dep_in_cycle_p (struct graph *rdg,
    1437              :                                         data_reference_p dr1,
    1438              :                                         data_reference_p dr2)
    1439              : {
    1440       261019 :   struct data_dependence_relation *ddr;
    1441              : 
    1442              :   /* Re-shuffle data-refs to be in topological order.  */
    1443       522038 :   if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
    1444       261019 :       > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
    1445        49671 :     std::swap (dr1, dr2);
    1446              : 
    1447       261019 :   ddr = get_data_dependence (rdg, dr1, dr2);
    1448              : 
    1449              :   /* In case of no data dependence.  */
    1450       261019 :   if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
    1451              :     return false;
    1452              :   /* For unknown data dependence or known data dependence which can't be
    1453              :      expressed in classic distance vector, we check if it can be resolved
    1454              :      by runtime alias check.  If yes, we still consider data dependence
    1455              :      as won't introduce data dependence cycle.  */
    1456        95438 :   else if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know
    1457        95438 :            || DDR_NUM_DIST_VECTS (ddr) == 0)
    1458        51483 :     return !runtime_alias_check_p (ddr, NULL, true);
    1459        43955 :   else if (DDR_NUM_DIST_VECTS (ddr) > 1)
    1460              :     return true;
    1461        39492 :   else if (DDR_REVERSED_P (ddr)
    1462       116208 :            || lambda_vector_zerop (DDR_DIST_VECT (ddr, 0), DDR_NB_LOOPS (ddr)))
    1463        34371 :     return false;
    1464              : 
    1465              :   return true;
    1466              : }
    1467              : 
    1468              : void
    1469       244302 : loop_distribution::update_type_for_merge (struct graph *rdg,
    1470              :                                            partition *partition1,
    1471              :                                            partition *partition2)
    1472              : {
    1473       244302 :   unsigned i, j;
    1474       244302 :   bitmap_iterator bi, bj;
    1475       244302 :   data_reference_p dr1, dr2;
    1476              : 
    1477       736682 :   EXECUTE_IF_SET_IN_BITMAP (partition1->datarefs, 0, i, bi)
    1478              :     {
    1479       501965 :       unsigned start = (partition1 == partition2) ? i + 1 : 0;
    1480              : 
    1481       501965 :       dr1 = datarefs_vec[i];
    1482      1231275 :       EXECUTE_IF_SET_IN_BITMAP (partition2->datarefs, start, j, bj)
    1483              :         {
    1484       738895 :           dr2 = datarefs_vec[j];
    1485       738895 :           if (DR_IS_READ (dr1) && DR_IS_READ (dr2))
    1486       477876 :             continue;
    1487              : 
    1488              :           /* Partition can only be executed sequentially if there is any
    1489              :              data dependence cycle.  */
    1490       261019 :           if (data_dep_in_cycle_p (rdg, dr1, dr2))
    1491              :             {
    1492         9585 :               partition1->type = PTYPE_SEQUENTIAL;
    1493         9585 :               return;
    1494              :             }
    1495              :         }
    1496              :     }
    1497              : }
    1498              : 
    1499              : partition *
    1500       254005 : loop_distribution::build_rdg_partition_for_vertex (struct graph *rdg, int v)
    1501              : {
    1502       254005 :   partition *partition = partition_alloc ();
    1503       254005 :   auto_vec<int, 3> nodes;
    1504       254005 :   unsigned i, j;
    1505       254005 :   int x;
    1506       254005 :   data_reference_p dr;
    1507              : 
    1508       254005 :   graphds_dfs (rdg, &v, 1, &nodes, false, NULL);
    1509              : 
    1510      3802529 :   FOR_EACH_VEC_ELT (nodes, i, x)
    1511              :     {
    1512      3294519 :       bitmap_set_bit (partition->stmts, x);
    1513              : 
    1514      7625349 :       for (j = 0; RDG_DATAREFS (rdg, x).iterate (j, &dr); ++j)
    1515              :         {
    1516       521170 :           unsigned idx = (unsigned) DR_INDEX (dr);
    1517       521170 :           gcc_assert (idx < datarefs_vec.length ());
    1518              : 
    1519              :           /* Partition can only be executed sequentially if there is any
    1520              :              unknown data reference.  */
    1521       521170 :           if (!DR_BASE_ADDRESS (dr) || !DR_OFFSET (dr)
    1522       492429 :               || !DR_INIT (dr) || !DR_STEP (dr))
    1523        28741 :             partition->type = PTYPE_SEQUENTIAL;
    1524              : 
    1525       521170 :           bitmap_set_bit (partition->datarefs, idx);
    1526              :         }
    1527              :     }
    1528              : 
    1529       254005 :   if (partition->type == PTYPE_SEQUENTIAL)
    1530              :     return partition;
    1531              : 
    1532              :   /* Further check if any data dependence prevents us from executing the
    1533              :      partition parallelly.  */
    1534       237381 :   update_type_for_merge (rdg, partition, partition);
    1535              : 
    1536       237381 :   return partition;
    1537       254005 : }
    1538              : 
    1539              : /* Given PARTITION of LOOP and RDG, record single load/store data references
    1540              :    for builtin partition in SRC_DR/DST_DR, return false if there is no such
    1541              :    data references.  */
    1542              : 
    1543              : static bool
    1544       235147 : find_single_drs (class loop *loop, struct graph *rdg, const bitmap &partition_stmts,
    1545              :                  data_reference_p *dst_dr, data_reference_p *src_dr)
    1546              : {
    1547       235147 :   unsigned i;
    1548       235147 :   data_reference_p single_ld = NULL, single_st = NULL;
    1549       235147 :   bitmap_iterator bi;
    1550              : 
    1551      2407427 :   EXECUTE_IF_SET_IN_BITMAP (partition_stmts, 0, i, bi)
    1552              :     {
    1553      2236188 :       gimple *stmt = RDG_STMT (rdg, i);
    1554      2236188 :       data_reference_p dr;
    1555              : 
    1556      2236188 :       if (gimple_code (stmt) == GIMPLE_PHI)
    1557       510977 :         continue;
    1558              : 
    1559              :       /* Any scalar stmts are ok.  */
    1560      3212644 :       if (!gimple_vuse (stmt))
    1561      1362362 :         continue;
    1562              : 
    1563              :       /* Otherwise just regular loads/stores.  */
    1564       362849 :       if (!gimple_assign_single_p (stmt))
    1565       235147 :         return false;
    1566              : 
    1567              :       /* But exactly one store and/or load.  */
    1568      2839482 :       for (unsigned j = 0; RDG_DATAREFS (rdg, i).iterate (j, &dr); ++j)
    1569              :         {
    1570       368282 :           tree type = TREE_TYPE (DR_REF (dr));
    1571              : 
    1572              :           /* The memset, memcpy and memmove library calls are only
    1573              :              able to deal with generic address space.  */
    1574       368282 :           if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type)))
    1575              :             return false;
    1576              : 
    1577       368264 :           if (DR_IS_READ (dr))
    1578              :             {
    1579       215526 :               if (single_ld != NULL)
    1580              :                 return false;
    1581              :               single_ld = dr;
    1582              :             }
    1583              :           else
    1584              :             {
    1585       152738 :               if (single_st != NULL)
    1586              :                 return false;
    1587              :               single_st = dr;
    1588              :             }
    1589              :         }
    1590              :     }
    1591              : 
    1592       171239 :   if (!single_ld && !single_st)
    1593              :     return false;
    1594              : 
    1595       165335 :   basic_block bb_ld = NULL;
    1596       165335 :   basic_block bb_st = NULL;
    1597       165335 :   edge exit = single_exit (loop);
    1598              : 
    1599       165335 :   if (single_ld)
    1600              :     {
    1601              :       /* Bail out if this is a bitfield memory reference.  */
    1602        87810 :       if (TREE_CODE (DR_REF (single_ld)) == COMPONENT_REF
    1603        87810 :           && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (single_ld), 1)))
    1604              :         return false;
    1605              : 
    1606              :       /* Data reference must be executed exactly once per iteration of each
    1607              :          loop in the loop nest.  We only need to check dominance information
    1608              :          against the outermost one in a perfect loop nest because a bb can't
    1609              :          dominate outermost loop's latch without dominating inner loop's.  */
    1610        87810 :       bb_ld = gimple_bb (DR_STMT (single_ld));
    1611        87810 :       if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_ld))
    1612              :         return false;
    1613              : 
    1614              :       /* The data reference must also be executed before possibly exiting
    1615              :          the loop as otherwise we'd for example unconditionally execute
    1616              :          memset (ptr, 0, n) which even with n == 0 implies ptr is non-NULL.  */
    1617        81213 :       if (bb_ld != loop->header
    1618        81213 :           && (!exit
    1619        10318 :               || !dominated_by_p (CDI_DOMINATORS, exit->src, bb_ld)))
    1620              :         return false;
    1621              :     }
    1622              : 
    1623       156358 :   if (single_st)
    1624              :     {
    1625              :       /* Bail out if this is a bitfield memory reference.  */
    1626       142334 :       if (TREE_CODE (DR_REF (single_st)) == COMPONENT_REF
    1627       142334 :           && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (single_st), 1)))
    1628              :         return false;
    1629              : 
    1630              :       /* Data reference must be executed exactly once per iteration.
    1631              :          Same as single_ld, we only need to check against the outermost
    1632              :          loop.  */
    1633       142334 :       bb_st = gimple_bb (DR_STMT (single_st));
    1634       142334 :       if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_st))
    1635              :         return false;
    1636              : 
    1637              :       /* And before exiting the loop.  */
    1638       138293 :       if (bb_st != loop->header
    1639       138293 :           && (!exit
    1640        18729 :               || !dominated_by_p (CDI_DOMINATORS, exit->src, bb_st)))
    1641              :         return false;
    1642              :     }
    1643              : 
    1644       151001 :   if (single_ld && single_st)
    1645              :     {
    1646              :       /* Load and store must be in the same loop nest.  */
    1647        62965 :       if (bb_st->loop_father != bb_ld->loop_father)
    1648              :         return false;
    1649              : 
    1650        62362 :       edge e = single_exit (bb_st->loop_father);
    1651        62362 :       bool dom_ld = dominated_by_p (CDI_DOMINATORS, e->src, bb_ld);
    1652        62362 :       bool dom_st = dominated_by_p (CDI_DOMINATORS, e->src, bb_st);
    1653        62362 :       if (dom_ld != dom_st)
    1654              :         return false;
    1655              :     }
    1656              : 
    1657       150398 :   *src_dr = single_ld;
    1658       150398 :   *dst_dr = single_st;
    1659       150398 :   return true;
    1660              : }
    1661              : 
    1662              : /* Given data reference DR in LOOP_NEST, this function checks the enclosing
    1663              :    loops from inner to outer to see if loop's step equals to access size at
    1664              :    each level of loop.  Return 2 if we can prove this at all level loops;
    1665              :    record access base and size in BASE and SIZE; save loop's step at each
    1666              :    level of loop in STEPS if it is not null.  For example:
    1667              : 
    1668              :      int arr[100][100][100];
    1669              :      for (i = 0; i < 100; i++)       ;steps[2] = 40000
    1670              :        for (j = 100; j > 0; j--)     ;steps[1] = -400
    1671              :          for (k = 0; k < 100; k++)   ;steps[0] = 4
    1672              :            arr[i][j - 1][k] = 0;     ;base = &arr, size = 4000000
    1673              : 
    1674              :    Return 1 if we can prove the equality at the innermost loop, but not all
    1675              :    level loops.  In this case, no information is recorded.
    1676              : 
    1677              :    Return 0 if no equality can be proven at any level loops.  */
    1678              : 
    1679              : static int
    1680        88157 : compute_access_range (loop_p loop_nest, data_reference_p dr, tree *base,
    1681              :                       tree *size, vec<tree> *steps = NULL)
    1682              : {
    1683        88157 :   location_t loc = gimple_location (DR_STMT (dr));
    1684        88157 :   basic_block bb = gimple_bb (DR_STMT (dr));
    1685        88157 :   class loop *loop = bb->loop_father;
    1686        88157 :   tree ref = DR_REF (dr);
    1687        88157 :   tree access_base = build_fold_addr_expr (ref);
    1688        88157 :   tree access_size = TYPE_SIZE_UNIT (TREE_TYPE (ref));
    1689        88157 :   int res = 0;
    1690              : 
    1691        89636 :   do {
    1692        89636 :       tree scev_fn = analyze_scalar_evolution (loop, access_base);
    1693        89636 :       if (TREE_CODE (scev_fn) != POLYNOMIAL_CHREC)
    1694        45725 :         return res;
    1695              : 
    1696        87745 :       access_base = CHREC_LEFT (scev_fn);
    1697        87745 :       if (tree_contains_chrecs (access_base, NULL))
    1698              :         return res;
    1699              : 
    1700        87745 :       tree scev_step = CHREC_RIGHT (scev_fn);
    1701              :       /* Only support constant steps.  */
    1702        87745 :       if (TREE_CODE (scev_step) != INTEGER_CST)
    1703              :         return res;
    1704              : 
    1705        82959 :       enum ev_direction access_dir = scev_direction (scev_fn);
    1706        82959 :       if (access_dir == EV_DIR_UNKNOWN)
    1707              :         return res;
    1708              : 
    1709        82959 :       if (steps != NULL)
    1710        53465 :         steps->safe_push (scev_step);
    1711              : 
    1712        82959 :       scev_step = fold_convert_loc (loc, sizetype, scev_step);
    1713              :       /* Compute absolute value of scev step.  */
    1714        82959 :       if (access_dir == EV_DIR_DECREASES)
    1715         3092 :         scev_step = fold_build1_loc (loc, NEGATE_EXPR, sizetype, scev_step);
    1716              : 
    1717              :       /* At each level of loop, scev step must equal to access size.  In other
    1718              :          words, DR must access consecutive memory between loop iterations.  */
    1719        82959 :       if (!operand_equal_p (scev_step, access_size, 0))
    1720              :         return res;
    1721              : 
    1722              :       /* Access stride can be computed for data reference at least for the
    1723              :          innermost loop.  */
    1724        43911 :       res = 1;
    1725              : 
    1726              :       /* Compute DR's execution times in loop.  */
    1727        43911 :       tree niters = number_of_latch_executions (loop);
    1728        43911 :       niters = fold_convert_loc (loc, sizetype, niters);
    1729        43911 :       if (dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src, bb))
    1730        43911 :         niters = size_binop_loc (loc, PLUS_EXPR, niters, size_one_node);
    1731              : 
    1732              :       /* Compute DR's overall access size in loop.  */
    1733        43911 :       access_size = fold_build2_loc (loc, MULT_EXPR, sizetype,
    1734              :                                      niters, scev_step);
    1735              :       /* Adjust base address in case of negative step.  */
    1736        43911 :       if (access_dir == EV_DIR_DECREASES)
    1737              :         {
    1738         2122 :           tree adj = fold_build2_loc (loc, MINUS_EXPR, sizetype,
    1739              :                                       scev_step, access_size);
    1740         2122 :           access_base = fold_build_pointer_plus_loc (loc, access_base, adj);
    1741              :         }
    1742        43911 :   } while (loop != loop_nest && (loop = loop_outer (loop)) != NULL);
    1743              : 
    1744        42432 :   *base = access_base;
    1745        42432 :   *size = access_size;
    1746              :   /* Access stride can be computed for data reference at each level loop.  */
    1747        42432 :   return 2;
    1748              : }
    1749              : 
    1750              : /* Allocate and return builtin struct.  Record information like DST_DR,
    1751              :    SRC_DR, DST_BASE, SRC_BASE and SIZE in the allocated struct.  */
    1752              : 
    1753              : static struct builtin_info *
    1754        14347 : alloc_builtin (data_reference_p dst_dr, data_reference_p src_dr,
    1755              :                tree dst_base, tree src_base, tree size)
    1756              : {
    1757            0 :   struct builtin_info *builtin = XNEW (struct builtin_info);
    1758        14347 :   builtin->dst_dr = dst_dr;
    1759        14347 :   builtin->src_dr = src_dr;
    1760        14347 :   builtin->dst_base = dst_base;
    1761        14347 :   builtin->src_base = src_base;
    1762        14347 :   builtin->size = size;
    1763        14347 :   return builtin;
    1764              : }
    1765              : 
    1766              : /* Given data reference DR in loop nest LOOP, classify if it forms builtin
    1767              :    memset call.  */
    1768              : 
    1769              : static void
    1770        74002 : classify_builtin_st (loop_p loop, partition *partition, data_reference_p dr)
    1771              : {
    1772        74002 :   gimple *stmt = DR_STMT (dr);
    1773        74002 :   tree base, size, rhs = gimple_assign_rhs1 (stmt);
    1774              : 
    1775        74002 :   if (const_with_all_bytes_same (rhs) == -1
    1776        74002 :       && (!INTEGRAL_TYPE_P (TREE_TYPE (rhs))
    1777        56334 :           || (TYPE_MODE (TREE_TYPE (rhs))
    1778        28167 :               != TYPE_MODE (unsigned_char_type_node))))
    1779        64936 :     return;
    1780              : 
    1781        35662 :   if (TREE_CODE (rhs) == SSA_NAME
    1782         4798 :       && !SSA_NAME_IS_DEFAULT_DEF (rhs)
    1783        39788 :       && flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
    1784              :     return;
    1785              : 
    1786        31682 :   int res = compute_access_range (loop, dr, &base, &size);
    1787        31682 :   if (res == 0)
    1788              :     return;
    1789         9127 :   if (res == 1)
    1790              :     {
    1791           61 :       partition->kind = PKIND_PARTIAL_MEMSET;
    1792           61 :       return;
    1793              :     }
    1794              : 
    1795         9066 :   tree base_offset;
    1796         9066 :   tree base_base;
    1797         9066 :   split_constant_offset (base, &base_base, &base_offset);
    1798         9066 :   if (!cst_and_fits_in_hwi (base_offset))
    1799              :     return;
    1800         9066 :   unsigned HOST_WIDE_INT const_base_offset = int_cst_value (base_offset);
    1801              : 
    1802         9066 :   struct builtin_info *builtin;
    1803         9066 :   builtin = alloc_builtin (dr, NULL, base, NULL_TREE, size);
    1804         9066 :   builtin->dst_base_base = base_base;
    1805         9066 :   builtin->dst_base_offset = const_base_offset;
    1806         9066 :   partition->builtin = builtin;
    1807         9066 :   partition->kind = PKIND_MEMSET;
    1808              : }
    1809              : 
    1810              : /* Given data references DST_DR and SRC_DR in loop nest LOOP and RDG, classify
    1811              :    if it forms builtin memcpy or memmove call.  */
    1812              : 
    1813              : void
    1814        36569 : loop_distribution::classify_builtin_ldst (loop_p loop, struct graph *rdg,
    1815              :                                           partition *partition,
    1816              :                                           data_reference_p dst_dr,
    1817              :                                           data_reference_p src_dr)
    1818              : {
    1819        36569 :   tree base, size, src_base, src_size;
    1820        36569 :   auto_vec<tree> dst_steps, src_steps;
    1821              : 
    1822              :   /* Compute access range of both load and store.  */
    1823        36569 :   int res = compute_access_range (loop, dst_dr, &base, &size, &dst_steps);
    1824        36569 :   if (res != 2)
    1825              :     return;
    1826        19906 :   res = compute_access_range (loop, src_dr, &src_base, &src_size, &src_steps);
    1827        19906 :   if (res != 2)
    1828              :     return;
    1829              : 
    1830              :   /* They must have the same access size.  */
    1831        13460 :   if (!operand_equal_p (size, src_size, 0))
    1832              :     return;
    1833              : 
    1834              :   /* They must have the same storage order.  */
    1835        26920 :   if (reverse_storage_order_for_component_p (DR_REF (dst_dr))
    1836        13460 :       != reverse_storage_order_for_component_p (DR_REF (src_dr)))
    1837              :     return;
    1838              : 
    1839              :   /* Load and store in loop nest must access memory in the same way, i.e,
    1840              :      their must have the same steps in each loop of the nest.  */
    1841        40380 :   if (dst_steps.length () != src_steps.length ())
    1842              :     return;
    1843        27016 :   for (unsigned i = 0; i < dst_steps.length (); ++i)
    1844        13859 :     if (!operand_equal_p (dst_steps[i], src_steps[i], 0))
    1845              :       return;
    1846              : 
    1847              :   /* Now check that if there is a dependence.  */
    1848        13157 :   ddr_p ddr = get_data_dependence (rdg, src_dr, dst_dr);
    1849              : 
    1850              :   /* Classify as memcpy if no dependence between load and store.  */
    1851        13157 :   if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
    1852              :     {
    1853         4977 :       partition->builtin = alloc_builtin (dst_dr, src_dr, base, src_base, size);
    1854         4977 :       partition->kind = PKIND_MEMCPY;
    1855         4977 :       return;
    1856              :     }
    1857              : 
    1858              :   /* Can't do memmove in case of unknown dependence or dependence without
    1859              :      classical distance vector.  */
    1860         8180 :   if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know
    1861        37226 :       || DDR_NUM_DIST_VECTS (ddr) == 0)
    1862              :     return;
    1863              : 
    1864          657 :   unsigned i;
    1865          657 :   lambda_vector dist_v;
    1866          657 :   int num_lev = (DDR_LOOP_NEST (ddr)).length ();
    1867         1250 :   FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v)
    1868              :     {
    1869          593 :       unsigned dep_lev = dependence_level (dist_v, num_lev);
    1870              :       /* Can't do memmove if load depends on store.  */
    1871          637 :       if (dep_lev > 0 && dist_v[dep_lev - 1] > 0 && !DDR_REVERSED_P (ddr))
    1872              :         return;
    1873              :     }
    1874              : 
    1875          304 :   partition->builtin = alloc_builtin (dst_dr, src_dr, base, src_base, size);
    1876          304 :   partition->kind = PKIND_MEMMOVE;
    1877          304 :   return;
    1878        36569 : }
    1879              : 
    1880              : bool
    1881       254005 : loop_distribution::classify_partition (loop_p loop,
    1882              :                                        struct graph *rdg, partition *partition,
    1883              :                                        bitmap stmt_in_all_partitions)
    1884              : {
    1885       254005 :   bitmap_iterator bi;
    1886       254005 :   unsigned i;
    1887       254005 :   data_reference_p single_ld = NULL, single_st = NULL;
    1888       254005 :   bool volatiles_p = false, has_reduction = false;
    1889              : 
    1890      3548524 :   EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
    1891              :     {
    1892      3294519 :       gimple *stmt = RDG_STMT (rdg, i);
    1893              : 
    1894      5566931 :       if (gimple_has_volatile_ops (stmt))
    1895      3294519 :         volatiles_p = true;
    1896              : 
    1897              :       /* If the stmt is not included by all partitions and there is uses
    1898              :          outside of the loop, then mark the partition as reduction.  */
    1899      3294519 :       if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
    1900              :         {
    1901              :           /* Due to limitation in the transform phase we have to fuse all
    1902              :              reduction partitions.  As a result, this could cancel valid
    1903              :              loop distribution especially for loop that induction variable
    1904              :              is used outside of loop.  To workaround this issue, we skip
    1905              :              marking partition as reduction if the reduction stmt belongs
    1906              :              to all partitions.  In such case, reduction will be computed
    1907              :              correctly no matter how partitions are fused/distributed.  */
    1908        64743 :           if (!bitmap_bit_p (stmt_in_all_partitions, i))
    1909        26190 :             partition->reduction_p = true;
    1910              :           else
    1911              :             has_reduction = true;
    1912              :         }
    1913              :     }
    1914              : 
    1915              :   /* Simple workaround to prevent classifying the partition as builtin
    1916              :      if it contains any use outside of loop.  For the case where all
    1917              :      partitions have the reduction this simple workaround is delayed
    1918              :      to only affect the last partition.  */
    1919       254005 :   if (partition->reduction_p)
    1920              :      return has_reduction;
    1921              : 
    1922              :   /* Perform general partition disqualification for builtins.  */
    1923       229430 :   if (volatiles_p
    1924       229430 :       || has_nonaddressable_dataref_p
    1925       229051 :       || !flag_tree_loop_distribute_patterns)
    1926              :     return has_reduction;
    1927              : 
    1928              :   /* Find single load/store data references for builtin partition.  */
    1929       226854 :   if (!find_single_drs (loop, rdg, partition->stmts, &single_st, &single_ld)
    1930       226854 :       || !single_st)
    1931              :     return has_reduction;
    1932              : 
    1933       136255 :   if (single_ld && single_st)
    1934              :     {
    1935        62253 :       gimple *store = DR_STMT (single_st), *load = DR_STMT (single_ld);
    1936              :       /* Direct aggregate copy or via an SSA name temporary.  */
    1937        62253 :       if (load != store
    1938        62253 :           && gimple_assign_lhs (load) != gimple_assign_rhs1 (store))
    1939              :         return has_reduction;
    1940              :     }
    1941              : 
    1942       110571 :   partition->loc = gimple_location (DR_STMT (single_st));
    1943              : 
    1944              :   /* Classify the builtin kind.  */
    1945       110571 :   if (single_ld == NULL)
    1946        74002 :     classify_builtin_st (loop, partition, single_st);
    1947              :   else
    1948        36569 :     classify_builtin_ldst (loop, rdg, partition, single_st, single_ld);
    1949              :   return has_reduction;
    1950              : }
    1951              : 
    1952              : bool
    1953       873040 : loop_distribution::share_memory_accesses (struct graph *rdg,
    1954              :                        partition *partition1, partition *partition2)
    1955              : {
    1956       873040 :   unsigned i, j;
    1957       873040 :   bitmap_iterator bi, bj;
    1958       873040 :   data_reference_p dr1, dr2;
    1959              : 
    1960              :   /* First check whether in the intersection of the two partitions are
    1961              :      any loads or stores.  Common loads are the situation that happens
    1962              :      most often.  */
    1963      6426972 :   EXECUTE_IF_AND_IN_BITMAP (partition1->stmts, partition2->stmts, 0, i, bi)
    1964      5558626 :     if (RDG_MEM_WRITE_STMT (rdg, i)
    1965      5558626 :         || RDG_MEM_READS_STMT (rdg, i))
    1966              :       return true;
    1967              : 
    1968              :   /* Then check whether the two partitions access the same memory object.  */
    1969      1935164 :   EXECUTE_IF_SET_IN_BITMAP (partition1->datarefs, 0, i, bi)
    1970              :     {
    1971      1069338 :       dr1 = datarefs_vec[i];
    1972              : 
    1973      1069338 :       if (!DR_BASE_ADDRESS (dr1)
    1974      1067257 :           || !DR_OFFSET (dr1) || !DR_INIT (dr1) || !DR_STEP (dr1))
    1975         2081 :         continue;
    1976              : 
    1977      2288840 :       EXECUTE_IF_SET_IN_BITMAP (partition2->datarefs, 0, j, bj)
    1978              :         {
    1979      1224103 :           dr2 = datarefs_vec[j];
    1980              : 
    1981      1224103 :           if (!DR_BASE_ADDRESS (dr2)
    1982      1223557 :               || !DR_OFFSET (dr2) || !DR_INIT (dr2) || !DR_STEP (dr2))
    1983          546 :             continue;
    1984              : 
    1985      1223557 :           if (operand_equal_p (DR_BASE_ADDRESS (dr1), DR_BASE_ADDRESS (dr2), 0)
    1986      1069901 :               && operand_equal_p (DR_OFFSET (dr1), DR_OFFSET (dr2), 0)
    1987      1068459 :               && operand_equal_p (DR_INIT (dr1), DR_INIT (dr2), 0)
    1988      1226108 :               && operand_equal_p (DR_STEP (dr1), DR_STEP (dr2), 0))
    1989              :             return true;
    1990              :         }
    1991              :     }
    1992              : 
    1993              :   return false;
    1994              : }
    1995              : 
    1996              : /* For each seed statement in STARTING_STMTS, this function builds
    1997              :    partition for it by adding depended statements according to RDG.
    1998              :    All partitions are recorded in PARTITIONS.  */
    1999              : 
    2000              : void
    2001       142585 : loop_distribution::rdg_build_partitions (struct graph *rdg,
    2002              :                                          vec<gimple *> starting_stmts,
    2003              :                                          vec<partition *> *partitions)
    2004              : {
    2005       142585 :   auto_bitmap processed;
    2006       142585 :   int i;
    2007       142585 :   gimple *stmt;
    2008              : 
    2009       546086 :   FOR_EACH_VEC_ELT (starting_stmts, i, stmt)
    2010              :     {
    2011       260916 :       int v = rdg_vertex_for_stmt (rdg, stmt);
    2012              : 
    2013       260916 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2014          141 :         fprintf (dump_file,
    2015              :                  "ldist asked to generate code for vertex %d\n", v);
    2016              : 
    2017              :       /* If the vertex is already contained in another partition so
    2018              :          is the partition rooted at it.  */
    2019       260916 :       if (bitmap_bit_p (processed, v))
    2020         6911 :         continue;
    2021              : 
    2022       254005 :       partition *partition = build_rdg_partition_for_vertex (rdg, v);
    2023       254005 :       bitmap_ior_into (processed, partition->stmts);
    2024              : 
    2025       254005 :       if (dump_file && (dump_flags & TDF_DETAILS))
    2026              :         {
    2027          141 :           fprintf (dump_file, "ldist creates useful %s partition:\n",
    2028          141 :                    partition->type == PTYPE_PARALLEL ? "parallel" : "sequent");
    2029          141 :           bitmap_print (dump_file, partition->stmts, "  ", "\n");
    2030              :         }
    2031              : 
    2032       254005 :       partitions->safe_push (partition);
    2033              :     }
    2034              : 
    2035              :   /* All vertices should have been assigned to at least one partition now,
    2036              :      other than vertices belonging to dead code.  */
    2037       142585 : }
    2038              : 
    2039              : /* Dump to FILE the PARTITIONS.  */
    2040              : 
    2041              : static void
    2042           42 : dump_rdg_partitions (FILE *file, const vec<partition *> &partitions)
    2043              : {
    2044           42 :   int i;
    2045           42 :   partition *partition;
    2046              : 
    2047          108 :   FOR_EACH_VEC_ELT (partitions, i, partition)
    2048           66 :     debug_bitmap_file (file, partition->stmts);
    2049           42 : }
    2050              : 
    2051              : /* Debug PARTITIONS.  */
    2052              : extern void debug_rdg_partitions (const vec<partition *> &);
    2053              : 
    2054              : DEBUG_FUNCTION void
    2055            0 : debug_rdg_partitions (const vec<partition *> &partitions)
    2056              : {
    2057            0 :   dump_rdg_partitions (stderr, partitions);
    2058            0 : }
    2059              : 
    2060              : /* Returns the number of read and write operations in the RDG.  */
    2061              : 
    2062              : static int
    2063         2931 : number_of_rw_in_rdg (struct graph *rdg)
    2064              : {
    2065         2931 :   int i, res = 0;
    2066              : 
    2067        43243 :   for (i = 0; i < rdg->n_vertices; i++)
    2068              :     {
    2069        40312 :       if (RDG_MEM_WRITE_STMT (rdg, i))
    2070         8163 :         ++res;
    2071              : 
    2072        40312 :       if (RDG_MEM_READS_STMT (rdg, i))
    2073         5740 :         ++res;
    2074              :     }
    2075              : 
    2076         2931 :   return res;
    2077              : }
    2078              : 
    2079              : /* Returns the number of read and write operations in a PARTITION of
    2080              :    the RDG.  */
    2081              : 
    2082              : static int
    2083         6355 : number_of_rw_in_partition (struct graph *rdg, partition *partition)
    2084              : {
    2085         6355 :   int res = 0;
    2086         6355 :   unsigned i;
    2087         6355 :   bitmap_iterator ii;
    2088              : 
    2089        60468 :   EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, ii)
    2090              :     {
    2091        54113 :       if (RDG_MEM_WRITE_STMT (rdg, i))
    2092         8155 :         ++res;
    2093              : 
    2094        54113 :       if (RDG_MEM_READS_STMT (rdg, i))
    2095         5740 :         ++res;
    2096              :     }
    2097              : 
    2098         6355 :   return res;
    2099              : }
    2100              : 
    2101              : /* Returns true when one of the PARTITIONS contains all the read or
    2102              :    write operations of RDG.  */
    2103              : 
    2104              : static bool
    2105         2931 : partition_contains_all_rw (struct graph *rdg,
    2106              :                            const vec<partition *> &partitions)
    2107              : {
    2108         2931 :   int i;
    2109         2931 :   partition *partition;
    2110         2931 :   int nrw = number_of_rw_in_rdg (rdg);
    2111              : 
    2112         9169 :   FOR_EACH_VEC_ELT (partitions, i, partition)
    2113         6355 :     if (nrw == number_of_rw_in_partition (rdg, partition))
    2114              :       return true;
    2115              : 
    2116              :   return false;
    2117              : }
    2118              : 
    2119              : int
    2120       983988 : loop_distribution::pg_add_dependence_edges (struct graph *rdg, int dir,
    2121              :                          bitmap drs1, bitmap drs2, vec<ddr_p> *alias_ddrs)
    2122              : {
    2123       983988 :   unsigned i, j;
    2124       983988 :   bitmap_iterator bi, bj;
    2125       983988 :   data_reference_p dr1, dr2, saved_dr1;
    2126              : 
    2127              :   /* dependence direction - 0 is no dependence, -1 is back,
    2128              :      1 is forth, 2 is both (we can stop then, merging will occur).  */
    2129      1892902 :   EXECUTE_IF_SET_IN_BITMAP (drs1, 0, i, bi)
    2130              :     {
    2131      1110601 :       dr1 = datarefs_vec[i];
    2132              : 
    2133      2317373 :       EXECUTE_IF_SET_IN_BITMAP (drs2, 0, j, bj)
    2134              :         {
    2135      1408459 :           int res, this_dir = 1;
    2136      1408459 :           ddr_p ddr;
    2137              : 
    2138      1408459 :           dr2 = datarefs_vec[j];
    2139              : 
    2140              :           /* Skip all <read, read> data dependence.  */
    2141      1408459 :           if (DR_IS_READ (dr1) && DR_IS_READ (dr2))
    2142       110790 :             continue;
    2143              : 
    2144      1297669 :           saved_dr1 = dr1;
    2145              :           /* Re-shuffle data-refs to be in topological order.  */
    2146      2595338 :           if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
    2147      1297669 :               > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
    2148              :             {
    2149        93134 :               std::swap (dr1, dr2);
    2150        93134 :               this_dir = -this_dir;
    2151              :             }
    2152      1297669 :           ddr = get_data_dependence (rdg, dr1, dr2);
    2153      1297669 :           if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
    2154              :             {
    2155       213490 :               this_dir = 0;
    2156       213490 :               res = data_ref_compare_tree (DR_BASE_ADDRESS (dr1),
    2157              :                                            DR_BASE_ADDRESS (dr2));
    2158              :               /* Be conservative.  If data references are not well analyzed,
    2159              :                  or the two data references have the same base address and
    2160              :                  offset, add dependence and consider it alias to each other.
    2161              :                  In other words, the dependence cannot be resolved by
    2162              :                  runtime alias check.  */
    2163       213490 :               if (!DR_BASE_ADDRESS (dr1) || !DR_BASE_ADDRESS (dr2)
    2164       212962 :                   || !DR_OFFSET (dr1) || !DR_OFFSET (dr2)
    2165       212962 :                   || !DR_INIT (dr1) || !DR_INIT (dr2)
    2166       212962 :                   || !DR_STEP (dr1) || !tree_fits_uhwi_p (DR_STEP (dr1))
    2167       204930 :                   || !DR_STEP (dr2) || !tree_fits_uhwi_p (DR_STEP (dr2))
    2168       204784 :                   || res == 0)
    2169              :                 this_dir = 2;
    2170              :               /* Data dependence could be resolved by runtime alias check,
    2171              :                  record it in ALIAS_DDRS.  */
    2172        13108 :               else if (alias_ddrs != NULL)
    2173         6531 :                 alias_ddrs->safe_push (ddr);
    2174              :               /* Or simply ignore it.  */
    2175              :             }
    2176      1084179 :           else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
    2177              :             {
    2178              :               /* Known dependences can still be unordered throughout the
    2179              :                  iteration space, see gcc.dg/tree-ssa/ldist-16.c and
    2180              :                  gcc.dg/tree-ssa/pr94969.c.  */
    2181         2183 :               if (DDR_NUM_DIST_VECTS (ddr) != 1)
    2182              :                 this_dir = 2;
    2183              :               else
    2184              :                 {
    2185              :                   /* If the overlap is exact preserve stmt order.  */
    2186         1838 :                   if (lambda_vector_zerop (DDR_DIST_VECT (ddr, 0),
    2187         1838 :                                            DDR_NB_LOOPS (ddr)))
    2188              :                     ;
    2189              :                   /* Else as the distance vector is lexicographic positive swap
    2190              :                      the dependence direction.  */
    2191              :                   else
    2192              :                     {
    2193          842 :                       if (DDR_REVERSED_P (ddr))
    2194           42 :                         this_dir = -this_dir;
    2195          842 :                       this_dir = -this_dir;
    2196              :                     }
    2197              :                   /* When then dependence distance of the innermost common
    2198              :                      loop of the DRs is zero we have a conflict.  This is
    2199              :                      due to wonky dependence analysis which sometimes
    2200              :                      ends up using a zero distance in place of unknown.  */
    2201          919 :                   auto l1 = gimple_bb (DR_STMT (dr1))->loop_father;
    2202          919 :                   auto l2 = gimple_bb (DR_STMT (dr2))->loop_father;
    2203          919 :                   int idx = index_in_loop_nest (find_common_loop (l1, l2)->num,
    2204          919 :                                                 DDR_LOOP_NEST (ddr));
    2205          919 :                   if (DDR_DIST_VECT (ddr, 0)[idx] == 0
    2206              :                       /* Unless it is the outermost loop which is the one
    2207              :                          we eventually distribute.  */
    2208          919 :                       && idx != 0)
    2209              :                     this_dir = 2;
    2210              :                 }
    2211              :             }
    2212              :           else
    2213              :             this_dir = 0;
    2214         7467 :           if (this_dir == 2)
    2215       201687 :             return 2;
    2216      1095995 :           else if (dir == 0)
    2217              :             dir = this_dir;
    2218         7344 :           else if (this_dir != 0 && dir != this_dir)
    2219              :             return 2;
    2220              :           /* Shuffle "back" dr1.  */
    2221      1095982 :           dr1 = saved_dr1;
    2222              :         }
    2223              :     }
    2224              :   return dir;
    2225              : }
    2226              : 
    2227              : /* Compare postorder number of the partition graph vertices V1 and V2.  */
    2228              : 
    2229              : static int
    2230       809079 : pgcmp (const void *v1_, const void *v2_)
    2231              : {
    2232       809079 :   const vertex *v1 = (const vertex *)v1_;
    2233       809079 :   const vertex *v2 = (const vertex *)v2_;
    2234       809079 :   return v2->post - v1->post;
    2235              : }
    2236              : 
    2237              : /* Data attached to vertices of partition dependence graph.  */
    2238              : struct pg_vdata
    2239              : {
    2240              :   /* ID of the corresponding partition.  */
    2241              :   int id;
    2242              :   /* The partition.  */
    2243              :   struct partition *partition;
    2244              : };
    2245              : 
    2246              : /* Data attached to edges of partition dependence graph.  */
    2247              : struct pg_edata
    2248              : {
    2249              :   /* If the dependence edge can be resolved by runtime alias check,
    2250              :      this vector contains data dependence relations for runtime alias
    2251              :      check.  On the other hand, if the dependence edge is introduced
    2252              :      because of compilation time known data dependence, this vector
    2253              :      contains nothing.  */
    2254              :   vec<ddr_p> alias_ddrs;
    2255              : };
    2256              : 
    2257              : /* Callback data for traversing edges in graph.  */
    2258              : struct pg_edge_callback_data
    2259              : {
    2260              :   /* Bitmap contains strong connected components should be merged.  */
    2261              :   bitmap sccs_to_merge;
    2262              :   /* Array constains component information for all vertices.  */
    2263              :   int *vertices_component;
    2264              :   /* Vector to record all data dependence relations which are needed
    2265              :      to break strong connected components by runtime alias checks.  */
    2266              :   vec<ddr_p> *alias_ddrs;
    2267              : };
    2268              : 
    2269              : /* Initialize vertice's data for partition dependence graph PG with
    2270              :    PARTITIONS.  */
    2271              : 
    2272              : static void
    2273        13074 : init_partition_graph_vertices (struct graph *pg,
    2274              :                                vec<struct partition *> *partitions)
    2275              : {
    2276        13074 :   int i;
    2277        13074 :   partition *partition;
    2278        13074 :   struct pg_vdata *data;
    2279              : 
    2280        72229 :   for (i = 0; partitions->iterate (i, &partition); ++i)
    2281              :     {
    2282        59155 :       data = new pg_vdata;
    2283        59155 :       pg->vertices[i].data = data;
    2284        59155 :       data->id = i;
    2285        59155 :       data->partition = partition;
    2286              :     }
    2287        13074 : }
    2288              : 
    2289              : /* Add edge <I, J> to partition dependence graph PG.  Attach vector of data
    2290              :    dependence relations to the EDGE if DDRS isn't NULL.  */
    2291              : 
    2292              : static void
    2293       415477 : add_partition_graph_edge (struct graph *pg, int i, int j, vec<ddr_p> *ddrs)
    2294              : {
    2295       415477 :   struct graph_edge *e = add_edge (pg, i, j);
    2296              : 
    2297              :   /* If the edge is attached with data dependence relations, it means this
    2298              :      dependence edge can be resolved by runtime alias checks.  */
    2299       415477 :   if (ddrs != NULL)
    2300              :     {
    2301        10099 :       struct pg_edata *data = new pg_edata;
    2302              : 
    2303        10099 :       gcc_assert (ddrs->length () > 0);
    2304        10099 :       e->data = data;
    2305        10099 :       data->alias_ddrs = vNULL;
    2306        10099 :       data->alias_ddrs.safe_splice (*ddrs);
    2307              :     }
    2308       415477 : }
    2309              : 
    2310              : /* Callback function for graph traversal algorithm.  It returns true
    2311              :    if edge E should skipped when traversing the graph.  */
    2312              : 
    2313              : static bool
    2314         1959 : pg_skip_alias_edge (struct graph_edge *e)
    2315              : {
    2316         1959 :   struct pg_edata *data = (struct pg_edata *)e->data;
    2317         1959 :   return (data != NULL && data->alias_ddrs.length () > 0);
    2318              : }
    2319              : 
    2320              : /* Callback function freeing data attached to edge E of graph.  */
    2321              : 
    2322              : static void
    2323       415477 : free_partition_graph_edata_cb (struct graph *, struct graph_edge *e, void *)
    2324              : {
    2325       415477 :   if (e->data != NULL)
    2326              :     {
    2327        10098 :       struct pg_edata *data = (struct pg_edata *)e->data;
    2328        10098 :       data->alias_ddrs.release ();
    2329        10098 :       delete data;
    2330              :     }
    2331       415477 : }
    2332              : 
    2333              : /* Free data attached to vertice of partition dependence graph PG.  */
    2334              : 
    2335              : static void
    2336        13074 : free_partition_graph_vdata (struct graph *pg)
    2337              : {
    2338        13074 :   int i;
    2339        13074 :   struct pg_vdata *data;
    2340              : 
    2341        72229 :   for (i = 0; i < pg->n_vertices; ++i)
    2342              :     {
    2343        59155 :       data = (struct pg_vdata *)pg->vertices[i].data;
    2344        59155 :       delete data;
    2345              :     }
    2346        13074 : }
    2347              : 
    2348              : /* Build and return partition dependence graph for PARTITIONS.  RDG is
    2349              :    reduced dependence graph for the loop to be distributed.  If IGNORE_ALIAS_P
    2350              :    is true, data dependence caused by possible alias between references
    2351              :    is ignored, as if it doesn't exist at all; otherwise all dependences
    2352              :    are considered.  */
    2353              : 
    2354              : struct graph *
    2355        13074 : loop_distribution::build_partition_graph (struct graph *rdg,
    2356              :                                           vec<struct partition *> *partitions,
    2357              :                                           bool ignore_alias_p)
    2358              : {
    2359        13074 :   int i, j;
    2360        13074 :   struct partition *partition1, *partition2;
    2361        26148 :   graph *pg = new_graph (partitions->length ());
    2362        13074 :   auto_vec<ddr_p> alias_ddrs, *alias_ddrs_p;
    2363              : 
    2364        13074 :   alias_ddrs_p = ignore_alias_p ? NULL : &alias_ddrs;
    2365              : 
    2366        13074 :   init_partition_graph_vertices (pg, partitions);
    2367              : 
    2368        85303 :   for (i = 0; partitions->iterate (i, &partition1); ++i)
    2369              :     {
    2370      1102298 :       for (j = i + 1; partitions->iterate (j, &partition2); ++j)
    2371              :         {
    2372              :           /* dependence direction - 0 is no dependence, -1 is back,
    2373              :              1 is forth, 2 is both (we can stop then, merging will occur).  */
    2374       983988 :           int dir = 0;
    2375              : 
    2376              :           /* If the first partition has reduction, add back edge; if the
    2377              :              second partition has reduction, add forth edge.  This makes
    2378              :              sure that reduction partition will be sorted as the last one.  */
    2379       983988 :           if (partition_reduction_p (partition1))
    2380              :             dir = -1;
    2381       983791 :           else if (partition_reduction_p (partition2))
    2382         1491 :             dir = 1;
    2383              : 
    2384              :           /* Cleanup the temporary vector.  */
    2385       983988 :           alias_ddrs.truncate (0);
    2386              : 
    2387       983988 :           dir = pg_add_dependence_edges (rdg, dir, partition1->datarefs,
    2388              :                                          partition2->datarefs, alias_ddrs_p);
    2389              : 
    2390              :           /* Add edge to partition graph if there exists dependence.  There
    2391              :              are two types of edges.  One type edge is caused by compilation
    2392              :              time known dependence, this type cannot be resolved by runtime
    2393              :              alias check.  The other type can be resolved by runtime alias
    2394              :              check.  */
    2395       983988 :           if (dir == 1 || dir == 2
    2396       990729 :               || alias_ddrs.length () > 0)
    2397              :             {
    2398              :               /* Attach data dependence relations to edge that can be resolved
    2399              :                  by runtime alias check.  */
    2400       208462 :               bool alias_edge_p = (dir != 1 && dir != 2);
    2401       411904 :               add_partition_graph_edge (pg, i, j,
    2402              :                                         (alias_edge_p) ? &alias_ddrs : NULL);
    2403              :             }
    2404       983988 :           if (dir == -1 || dir == 2
    2405      1973055 :               || alias_ddrs.length () > 0)
    2406              :             {
    2407              :               /* Attach data dependence relations to edge that can be resolved
    2408              :                  by runtime alias check.  */
    2409       207015 :               bool alias_edge_p = (dir != -1 && dir != 2);
    2410       408951 :               add_partition_graph_edge (pg, j, i,
    2411              :                                         (alias_edge_p) ? &alias_ddrs : NULL);
    2412              :             }
    2413              :         }
    2414              :     }
    2415        13074 :   return pg;
    2416        13074 : }
    2417              : 
    2418              : /* Sort partitions in PG in descending post order and store them in
    2419              :    PARTITIONS.  */
    2420              : 
    2421              : static void
    2422        13074 : sort_partitions_by_post_order (struct graph *pg,
    2423              :                                vec<struct partition *> *partitions)
    2424              : {
    2425        13074 :   int i;
    2426        13074 :   struct pg_vdata *data;
    2427              : 
    2428              :   /* Now order the remaining nodes in descending postorder.  */
    2429        13074 :   qsort (pg->vertices, pg->n_vertices, sizeof (vertex), pgcmp);
    2430        13074 :   partitions->truncate (0);
    2431        85303 :   for (i = 0; i < pg->n_vertices; ++i)
    2432              :     {
    2433        59155 :       data = (struct pg_vdata *)pg->vertices[i].data;
    2434        59155 :       if (data->partition)
    2435        51353 :         partitions->safe_push (data->partition);
    2436              :     }
    2437        13074 : }
    2438              : 
    2439              : void
    2440         7112 : loop_distribution::merge_dep_scc_partitions (struct graph *rdg,
    2441              :                                              vec<struct partition *> *partitions,
    2442              :                                              bool ignore_alias_p)
    2443              : {
    2444         7112 :   struct partition *partition1, *partition2;
    2445         7112 :   struct pg_vdata *data;
    2446         7112 :   graph *pg = build_partition_graph (rdg, partitions, ignore_alias_p);
    2447         7112 :   int i, j, num_sccs = graphds_scc (pg, NULL);
    2448              : 
    2449              :   /* Strong connected compoenent means dependence cycle, we cannot distribute
    2450              :      them.  So fuse them together.  */
    2451         7112 :   if ((unsigned) num_sccs < partitions->length ())
    2452              :     {
    2453         1989 :       for (i = 0; i < num_sccs; ++i)
    2454              :         {
    2455         2162 :           for (j = 0; partitions->iterate (j, &partition1); ++j)
    2456         2162 :             if (pg->vertices[j].component == i)
    2457              :               break;
    2458         9990 :           for (j = j + 1; partitions->iterate (j, &partition2); ++j)
    2459         7920 :             if (pg->vertices[j].component == i)
    2460              :               {
    2461         6845 :                 partition_merge_into (NULL, partition1,
    2462              :                                       partition2, FUSE_SAME_SCC);
    2463         6845 :                 partition1->type = PTYPE_SEQUENTIAL;
    2464         6845 :                 (*partitions)[j] = NULL;
    2465         6845 :                 partition_free (partition2);
    2466         6845 :                 data = (struct pg_vdata *)pg->vertices[j].data;
    2467         6845 :                 data->partition = NULL;
    2468              :               }
    2469              :         }
    2470              :     }
    2471              : 
    2472         7112 :   sort_partitions_by_post_order (pg, partitions);
    2473        14224 :   gcc_assert (partitions->length () == (unsigned)num_sccs);
    2474         7112 :   free_partition_graph_vdata (pg);
    2475         7112 :   for_each_edge (pg, free_partition_graph_edata_cb, NULL);
    2476         7112 :   free_graph (pg);
    2477         7112 : }
    2478              : 
    2479              : /* Callback function for traversing edge E in graph G.  DATA is private
    2480              :    callback data.  */
    2481              : 
    2482              : static void
    2483          743 : pg_collect_alias_ddrs (struct graph *g, struct graph_edge *e, void *data)
    2484              : {
    2485          743 :   int i, j, component;
    2486          743 :   struct pg_edge_callback_data *cbdata;
    2487          743 :   struct pg_edata *edata = (struct pg_edata *) e->data;
    2488              : 
    2489              :   /* If the edge doesn't have attached data dependence, it represents
    2490              :      compilation time known dependences.  This type dependence cannot
    2491              :      be resolved by runtime alias check.  */
    2492          743 :   if (edata == NULL || edata->alias_ddrs.length () == 0)
    2493              :     return;
    2494              : 
    2495          725 :   cbdata = (struct pg_edge_callback_data *) data;
    2496          725 :   i = e->src;
    2497          725 :   j = e->dest;
    2498          725 :   component = cbdata->vertices_component[i];
    2499              :   /* Vertices are topologically sorted according to compilation time
    2500              :      known dependences, so we can break strong connected components
    2501              :      by removing edges of the opposite direction, i.e, edges pointing
    2502              :      from vertice with smaller post number to vertice with bigger post
    2503              :      number.  */
    2504          725 :   if (g->vertices[i].post < g->vertices[j].post
    2505              :       /* We only need to remove edges connecting vertices in the same
    2506              :          strong connected component to break it.  */
    2507          369 :       && component == cbdata->vertices_component[j]
    2508              :       /* Check if we want to break the strong connected component or not.  */
    2509         1094 :       && !bitmap_bit_p (cbdata->sccs_to_merge, component))
    2510          369 :     cbdata->alias_ddrs->safe_splice (edata->alias_ddrs);
    2511              : }
    2512              : 
    2513              : /* Callback function for traversing edge E.  DATA is private
    2514              :    callback data.  */
    2515              : 
    2516              : static void
    2517          743 : pg_unmark_merged_alias_ddrs (struct graph *, struct graph_edge *e, void *data)
    2518              : {
    2519          743 :   int i, j, component;
    2520          743 :   struct pg_edge_callback_data *cbdata;
    2521          743 :   struct pg_edata *edata = (struct pg_edata *) e->data;
    2522              : 
    2523          743 :   if (edata == NULL || edata->alias_ddrs.length () == 0)
    2524              :     return;
    2525              : 
    2526          726 :   cbdata = (struct pg_edge_callback_data *) data;
    2527          726 :   i = e->src;
    2528          726 :   j = e->dest;
    2529          726 :   component = cbdata->vertices_component[i];
    2530              :   /* Make sure to not skip vertices inside SCCs we are going to merge.  */
    2531          726 :   if (component == cbdata->vertices_component[j]
    2532          726 :       && bitmap_bit_p (cbdata->sccs_to_merge, component))
    2533              :     {
    2534            1 :       edata->alias_ddrs.release ();
    2535            1 :       delete edata;
    2536            1 :       e->data = NULL;
    2537              :     }
    2538              : }
    2539              : 
    2540              : /* This is the main function breaking strong connected components in
    2541              :    PARTITIONS giving reduced dependence graph RDG.  Store data dependence
    2542              :    relations for runtime alias check in ALIAS_DDRS.  */
    2543              : void
    2544         5962 : loop_distribution::break_alias_scc_partitions (struct graph *rdg,
    2545              :                                                vec<struct partition *> *partitions,
    2546              :                                                vec<ddr_p> *alias_ddrs)
    2547              : {
    2548         5962 :   int i, j, k, num_sccs, num_sccs_no_alias = 0;
    2549              :   /* Build partition dependence graph.  */
    2550         5962 :   graph *pg = build_partition_graph (rdg, partitions, false);
    2551              : 
    2552         5962 :   alias_ddrs->truncate (0);
    2553              :   /* Find strong connected components in the graph, with all dependence edges
    2554              :      considered.  */
    2555         5962 :   num_sccs = graphds_scc (pg, NULL);
    2556              :   /* All SCCs now can be broken by runtime alias checks because SCCs caused by
    2557              :      compilation time known dependences are merged before this function.  */
    2558         5962 :   if ((unsigned) num_sccs < partitions->length ())
    2559              :     {
    2560          299 :       struct pg_edge_callback_data cbdata;
    2561          299 :       auto_bitmap sccs_to_merge;
    2562          299 :       auto_vec<enum partition_type> scc_types;
    2563          299 :       struct partition *partition, *first;
    2564              : 
    2565              :       /* If all partitions in a SCC have the same type, we can simply merge the
    2566              :          SCC.  This loop finds out such SCCS and record them in bitmap.  */
    2567          299 :       bitmap_set_range (sccs_to_merge, 0, (unsigned) num_sccs);
    2568          914 :       for (i = 0; i < num_sccs; ++i)
    2569              :         {
    2570          339 :           for (j = 0; partitions->iterate (j, &first); ++j)
    2571          339 :             if (pg->vertices[j].component == i)
    2572              :               break;
    2573              : 
    2574          316 :           bool same_type = true, all_builtins = partition_builtin_p (first);
    2575         1556 :           for (++j; partitions->iterate (j, &partition); ++j)
    2576              :             {
    2577         1278 :               if (pg->vertices[j].component != i)
    2578          154 :                 continue;
    2579              : 
    2580         1124 :               if (first->type != partition->type)
    2581              :                 {
    2582              :                   same_type = false;
    2583              :                   break;
    2584              :                 }
    2585         1086 :               all_builtins &= partition_builtin_p (partition);
    2586              :             }
    2587              :           /* Merge SCC if all partitions in SCC have the same type, though the
    2588              :              result partition is sequential, because vectorizer can do better
    2589              :              runtime alias check.  One expecption is all partitions in SCC are
    2590              :              builtins.  */
    2591          316 :           if (!same_type || all_builtins)
    2592           80 :             bitmap_clear_bit (sccs_to_merge, i);
    2593              :         }
    2594              : 
    2595              :       /* Initialize callback data for traversing.  */
    2596          299 :       cbdata.sccs_to_merge = sccs_to_merge;
    2597          299 :       cbdata.alias_ddrs = alias_ddrs;
    2598          299 :       cbdata.vertices_component = XNEWVEC (int, pg->n_vertices);
    2599              :       /* Record the component information which will be corrupted by next
    2600              :          graph scc finding call.  */
    2601         1743 :       for (i = 0; i < pg->n_vertices; ++i)
    2602         1444 :         cbdata.vertices_component[i] = pg->vertices[i].component;
    2603              : 
    2604              :       /* Collect data dependences for runtime alias checks to break SCCs.  */
    2605          299 :       if (bitmap_count_bits (sccs_to_merge) != (unsigned) num_sccs)
    2606              :         {
    2607              :           /* For SCCs we want to merge clear all alias_ddrs for edges
    2608              :              inside the component.  */
    2609           76 :           for_each_edge (pg, pg_unmark_merged_alias_ddrs, &cbdata);
    2610              : 
    2611              :           /* Run SCC finding algorithm again, with alias dependence edges
    2612              :              skipped.  This is to topologically sort partitions according to
    2613              :              compilation time known dependence.  Note the topological order
    2614              :              is stored in the form of pg's post order number.  */
    2615           76 :           num_sccs_no_alias = graphds_scc (pg, NULL, pg_skip_alias_edge);
    2616              :           /* We cannot assert partitions->length () == num_sccs_no_alias
    2617              :              since we are not ignoring alias edges in cycles we are
    2618              :              going to merge.  That's required to compute correct postorder.  */
    2619              :           /* With topological order, we can construct two subgraphs L and R.
    2620              :              L contains edge <x, y> where x < y in terms of post order, while
    2621              :              R contains edge <x, y> where x > y.  Edges for compilation time
    2622              :              known dependence all fall in R, so we break SCCs by removing all
    2623              :              (alias) edges of in subgraph L.  */
    2624           76 :           for_each_edge (pg, pg_collect_alias_ddrs, &cbdata);
    2625              :         }
    2626              : 
    2627              :       /* For SCC that doesn't need to be broken, merge it.  */
    2628          615 :       for (i = 0; i < num_sccs; ++i)
    2629              :         {
    2630          316 :           if (!bitmap_bit_p (sccs_to_merge, i))
    2631           80 :             continue;
    2632              : 
    2633          253 :           for (j = 0; partitions->iterate (j, &first); ++j)
    2634          253 :             if (cbdata.vertices_component[j] == i)
    2635              :               break;
    2636         1655 :           for (k = j + 1; partitions->iterate (k, &partition); ++k)
    2637              :             {
    2638         1103 :               struct pg_vdata *data;
    2639              : 
    2640         1103 :               if (cbdata.vertices_component[k] != i)
    2641          146 :                 continue;
    2642              : 
    2643          957 :               partition_merge_into (NULL, first, partition, FUSE_SAME_SCC);
    2644          957 :               (*partitions)[k] = NULL;
    2645          957 :               partition_free (partition);
    2646          957 :               data = (struct pg_vdata *)pg->vertices[k].data;
    2647          957 :               gcc_assert (data->id == k);
    2648          957 :               data->partition = NULL;
    2649              :               /* The result partition of merged SCC must be sequential.  */
    2650          957 :               first->type = PTYPE_SEQUENTIAL;
    2651              :             }
    2652              :         }
    2653              :       /* If reduction partition's SCC is broken by runtime alias checks,
    2654              :          we force a negative post order to it making sure it will be scheduled
    2655              :          in the last.  */
    2656          299 :       if (num_sccs_no_alias > 0)
    2657              :         {
    2658              :           j = -1;
    2659          330 :           for (i = 0; i < pg->n_vertices; ++i)
    2660              :             {
    2661          254 :               struct pg_vdata *data = (struct pg_vdata *)pg->vertices[i].data;
    2662          254 :               if (data->partition && partition_reduction_p (data->partition))
    2663              :                 {
    2664            5 :                   gcc_assert (j == -1);
    2665              :                   j = i;
    2666              :                 }
    2667              :             }
    2668           76 :           if (j >= 0)
    2669            5 :             pg->vertices[j].post = -1;
    2670              :         }
    2671              : 
    2672          299 :       free (cbdata.vertices_component);
    2673          299 :     }
    2674              : 
    2675         5962 :   sort_partitions_by_post_order (pg, partitions);
    2676         5962 :   free_partition_graph_vdata (pg);
    2677         5962 :   for_each_edge (pg, free_partition_graph_edata_cb, NULL);
    2678         5962 :   free_graph (pg);
    2679              : 
    2680         5962 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2681              :     {
    2682           15 :       fprintf (dump_file, "Possible alias data dependence to break:\n");
    2683           15 :       dump_data_dependence_relations (dump_file, *alias_ddrs);
    2684              :     }
    2685         5962 : }
    2686              : 
    2687              : /* Compute and return an expression whose value is the segment length which
    2688              :    will be accessed by DR in NITERS iterations.  */
    2689              : 
    2690              : static tree
    2691         1292 : data_ref_segment_size (struct data_reference *dr, tree niters)
    2692              : {
    2693         1292 :   niters = size_binop (MINUS_EXPR,
    2694              :                        fold_convert (sizetype, niters),
    2695              :                        size_one_node);
    2696         1292 :   return size_binop (MULT_EXPR,
    2697              :                      fold_convert (sizetype, DR_STEP (dr)),
    2698              :                      fold_convert (sizetype, niters));
    2699              : }
    2700              : 
    2701              : /* Return true if LOOP's latch is dominated by statement for data reference
    2702              :    DR.  */
    2703              : 
    2704              : static inline bool
    2705         1292 : latch_dominated_by_data_ref (class loop *loop, data_reference *dr)
    2706              : {
    2707         1292 :   return dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src,
    2708         1292 :                          gimple_bb (DR_STMT (dr)));
    2709              : }
    2710              : 
    2711              : /* Compute alias check pairs and store them in COMP_ALIAS_PAIRS for LOOP's
    2712              :    data dependence relations ALIAS_DDRS.  */
    2713              : 
    2714              : static void
    2715           76 : compute_alias_check_pairs (class loop *loop, vec<ddr_p> *alias_ddrs,
    2716              :                            vec<dr_with_seg_len_pair_t> *comp_alias_pairs)
    2717              : {
    2718           76 :   unsigned int i;
    2719           76 :   unsigned HOST_WIDE_INT factor = 1;
    2720           76 :   tree niters_plus_one, niters = number_of_latch_executions (loop);
    2721              : 
    2722           76 :   gcc_assert (niters != NULL_TREE && niters != chrec_dont_know);
    2723           76 :   niters = fold_convert (sizetype, niters);
    2724           76 :   niters_plus_one = size_binop (PLUS_EXPR, niters, size_one_node);
    2725              : 
    2726           76 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2727            0 :     fprintf (dump_file, "Creating alias check pairs:\n");
    2728              : 
    2729              :   /* Iterate all data dependence relations and compute alias check pairs.  */
    2730          722 :   for (i = 0; i < alias_ddrs->length (); i++)
    2731              :     {
    2732          646 :       ddr_p ddr = (*alias_ddrs)[i];
    2733          646 :       struct data_reference *dr_a = DDR_A (ddr);
    2734          646 :       struct data_reference *dr_b = DDR_B (ddr);
    2735          646 :       tree seg_length_a, seg_length_b;
    2736              : 
    2737          646 :       if (latch_dominated_by_data_ref (loop, dr_a))
    2738          642 :         seg_length_a = data_ref_segment_size (dr_a, niters_plus_one);
    2739              :       else
    2740            4 :         seg_length_a = data_ref_segment_size (dr_a, niters);
    2741              : 
    2742          646 :       if (latch_dominated_by_data_ref (loop, dr_b))
    2743          642 :         seg_length_b = data_ref_segment_size (dr_b, niters_plus_one);
    2744              :       else
    2745            4 :         seg_length_b = data_ref_segment_size (dr_b, niters);
    2746              : 
    2747          646 :       unsigned HOST_WIDE_INT access_size_a
    2748          646 :         = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a))));
    2749          646 :       unsigned HOST_WIDE_INT access_size_b
    2750          646 :         = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_b))));
    2751          646 :       unsigned int align_a = TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_a)));
    2752          646 :       unsigned int align_b = TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_b)));
    2753              : 
    2754          646 :       dr_with_seg_len_pair_t dr_with_seg_len_pair
    2755         1292 :         (dr_with_seg_len (dr_a, seg_length_a, access_size_a, align_a),
    2756         1292 :          dr_with_seg_len (dr_b, seg_length_b, access_size_b, align_b),
    2757              :          /* ??? Would WELL_ORDERED be safe?  */
    2758          646 :          dr_with_seg_len_pair_t::REORDERED);
    2759              : 
    2760          646 :       comp_alias_pairs->safe_push (dr_with_seg_len_pair);
    2761              :     }
    2762              : 
    2763           76 :   if (tree_fits_uhwi_p (niters))
    2764           46 :     factor = tree_to_uhwi (niters);
    2765              : 
    2766              :   /* Prune alias check pairs.  */
    2767           76 :   prune_runtime_alias_test_list (comp_alias_pairs, factor);
    2768           76 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2769            0 :     fprintf (dump_file,
    2770              :              "Improved number of alias checks from %d to %d\n",
    2771              :              alias_ddrs->length (), comp_alias_pairs->length ());
    2772           76 : }
    2773              : 
    2774              : /* Given data dependence relations in ALIAS_DDRS, generate runtime alias
    2775              :    checks and version LOOP under condition of these runtime alias checks.  */
    2776              : 
    2777              : static void
    2778           76 : version_loop_by_alias_check (vec<struct partition *> *partitions,
    2779              :                              class loop *loop, vec<ddr_p> *alias_ddrs)
    2780              : {
    2781           76 :   profile_probability prob;
    2782           76 :   basic_block cond_bb;
    2783           76 :   class loop *nloop;
    2784           76 :   tree lhs, arg0, cond_expr = NULL_TREE;
    2785           76 :   gimple_seq cond_stmts = NULL;
    2786           76 :   gimple *call_stmt = NULL;
    2787           76 :   auto_vec<dr_with_seg_len_pair_t> comp_alias_pairs;
    2788              : 
    2789              :   /* Generate code for runtime alias checks if necessary.  */
    2790           76 :   gcc_assert (alias_ddrs->length () > 0);
    2791              : 
    2792           76 :   if (dump_file && (dump_flags & TDF_DETAILS))
    2793            0 :     fprintf (dump_file,
    2794              :              "Version loop <%d> with runtime alias check\n", loop->num);
    2795              : 
    2796           76 :   compute_alias_check_pairs (loop, alias_ddrs, &comp_alias_pairs);
    2797           76 :   create_runtime_alias_checks (loop, &comp_alias_pairs, &cond_expr);
    2798           76 :   cond_expr = force_gimple_operand_1 (cond_expr, &cond_stmts,
    2799              :                                       is_gimple_val, NULL_TREE);
    2800              : 
    2801              :   /* Depend on vectorizer to fold IFN_LOOP_DIST_ALIAS.  */
    2802           76 :   bool cancelable_p = flag_tree_loop_vectorize;
    2803           76 :   if (cancelable_p)
    2804              :     {
    2805              :       unsigned i = 0;
    2806              :       struct partition *partition;
    2807          217 :       for (; partitions->iterate (i, &partition); ++i)
    2808          183 :         if (!partition_builtin_p (partition))
    2809              :           break;
    2810              : 
    2811              :      /* If all partitions are builtins, distributing it would be profitable and
    2812              :         we don't want to cancel the runtime alias checks.  */
    2813          144 :       if (i == partitions->length ())
    2814              :         cancelable_p = false;
    2815              :     }
    2816              : 
    2817              :   /* Generate internal function call for loop distribution alias check if the
    2818              :      runtime alias check should be cancelable.  */
    2819           42 :   if (cancelable_p)
    2820              :     {
    2821           38 :       call_stmt = gimple_build_call_internal (IFN_LOOP_DIST_ALIAS,
    2822              :                                               2, NULL_TREE, cond_expr);
    2823           38 :       lhs = make_ssa_name (boolean_type_node);
    2824           38 :       gimple_call_set_lhs (call_stmt, lhs);
    2825              :     }
    2826              :   else
    2827              :     lhs = cond_expr;
    2828              : 
    2829           76 :   prob = profile_probability::guessed_always ().apply_scale (9, 10);
    2830           76 :   initialize_original_copy_tables ();
    2831           76 :   nloop = loop_version (loop, lhs, &cond_bb, prob, prob.invert (),
    2832              :                         prob, prob.invert (), true);
    2833           76 :   free_original_copy_tables ();
    2834              :   /* Record the original loop number in newly generated loops.  In case of
    2835              :      distribution, the original loop will be distributed and the new loop
    2836              :      is kept.  */
    2837           76 :   loop->orig_loop_num = nloop->num;
    2838           76 :   nloop->orig_loop_num = nloop->num;
    2839           76 :   nloop->dont_vectorize = true;
    2840           76 :   nloop->force_vectorize = false;
    2841              : 
    2842           76 :   if (call_stmt)
    2843              :     {
    2844              :       /* Record new loop's num in IFN_LOOP_DIST_ALIAS because the original
    2845              :          loop could be destroyed.  */
    2846           38 :       arg0 = build_int_cst (integer_type_node, loop->orig_loop_num);
    2847           38 :       gimple_call_set_arg (call_stmt, 0, arg0);
    2848           38 :       gimple_seq_add_stmt_without_update (&cond_stmts, call_stmt);
    2849              :     }
    2850              : 
    2851           76 :   if (cond_stmts)
    2852              :     {
    2853           76 :       gimple_stmt_iterator cond_gsi = gsi_last_bb (cond_bb);
    2854           76 :       gsi_insert_seq_before (&cond_gsi, cond_stmts, GSI_SAME_STMT);
    2855              :     }
    2856           76 :   update_ssa (TODO_update_ssa_no_phi);
    2857           76 : }
    2858              : 
    2859              : /* Return true if loop versioning is needed to distribute PARTITIONS.
    2860              :    ALIAS_DDRS are data dependence relations for runtime alias check.  */
    2861              : 
    2862              : static inline bool
    2863        13364 : version_for_distribution_p (vec<struct partition *> *partitions,
    2864              :                             vec<ddr_p> *alias_ddrs)
    2865              : {
    2866              :   /* No need to version loop if we have only one partition.  */
    2867        16178 :   if (partitions->length () == 1)
    2868              :     return false;
    2869              : 
    2870              :   /* Need to version loop if runtime alias check is necessary.  */
    2871         2814 :   return (alias_ddrs->length () > 0);
    2872              : }
    2873              : 
    2874              : /* Compare base offset of builtin mem* partitions P1 and P2.  */
    2875              : 
    2876              : static int
    2877          367 : offset_cmp (const void *vp1, const void *vp2)
    2878              : {
    2879          367 :   struct partition *p1 = *(struct partition *const *) vp1;
    2880          367 :   struct partition *p2 = *(struct partition *const *) vp2;
    2881          367 :   unsigned HOST_WIDE_INT o1 = p1->builtin->dst_base_offset;
    2882          367 :   unsigned HOST_WIDE_INT o2 = p2->builtin->dst_base_offset;
    2883          367 :   return (o2 < o1) - (o1 < o2);
    2884              : }
    2885              : 
    2886              : /* Fuse adjacent memset builtin PARTITIONS if possible.  This is a special
    2887              :    case optimization transforming below code:
    2888              : 
    2889              :      __builtin_memset (&obj, 0, 100);
    2890              :      _1 = &obj + 100;
    2891              :      __builtin_memset (_1, 0, 200);
    2892              :      _2 = &obj + 300;
    2893              :      __builtin_memset (_2, 0, 100);
    2894              : 
    2895              :    into:
    2896              : 
    2897              :      __builtin_memset (&obj, 0, 400);
    2898              : 
    2899              :    Note we don't have dependence information between different partitions
    2900              :    at this point, as a result, we can't handle nonadjacent memset builtin
    2901              :    partitions since dependence might be broken.  */
    2902              : 
    2903              : static void
    2904         2863 : fuse_memset_builtins (vec<struct partition *> *partitions)
    2905              : {
    2906         2863 :   unsigned i, j;
    2907         2863 :   struct partition *part1, *part2;
    2908         2863 :   tree rhs1, rhs2;
    2909              : 
    2910         9014 :   for (i = 0; partitions->iterate (i, &part1);)
    2911              :     {
    2912         6151 :       if (part1->kind != PKIND_MEMSET)
    2913              :         {
    2914         3604 :           i++;
    2915         3604 :           continue;
    2916              :         }
    2917              : 
    2918              :       /* Find sub-array of memset builtins of the same base.  Index range
    2919              :          of the sub-array is [i, j) with "j > i".  */
    2920         2619 :       for (j = i + 1; partitions->iterate (j, &part2); ++j)
    2921              :         {
    2922         1919 :           if (part2->kind != PKIND_MEMSET
    2923         2642 :               || !operand_equal_p (part1->builtin->dst_base_base,
    2924          723 :                                    part2->builtin->dst_base_base, 0))
    2925              :             break;
    2926              : 
    2927              :           /* Memset calls setting different values can't be merged.  */
    2928          118 :           rhs1 = gimple_assign_rhs1 (DR_STMT (part1->builtin->dst_dr));
    2929          118 :           rhs2 = gimple_assign_rhs1 (DR_STMT (part2->builtin->dst_dr));
    2930          118 :           if (!operand_equal_p (rhs1, rhs2, 0))
    2931              :             break;
    2932              :         }
    2933              : 
    2934              :       /* Stable sort is required in order to avoid breaking dependence.  */
    2935         2547 :       gcc_stablesort (&(*partitions)[i], j - i, sizeof (*partitions)[i],
    2936              :                       offset_cmp);
    2937              :       /* Continue with next partition.  */
    2938         2547 :       i = j;
    2939              :     }
    2940              : 
    2941              :   /* Merge all consecutive memset builtin partitions.  */
    2942        12446 :   for (i = 0; i < partitions->length () - 1;)
    2943              :     {
    2944         3360 :       part1 = (*partitions)[i];
    2945         3360 :       if (part1->kind != PKIND_MEMSET)
    2946              :         {
    2947         1441 :           i++;
    2948         3332 :           continue;
    2949              :         }
    2950              : 
    2951         1919 :       part2 = (*partitions)[i + 1];
    2952              :       /* Only merge memset partitions of the same base and with constant
    2953              :          access sizes.  */
    2954         3728 :       if (part2->kind != PKIND_MEMSET
    2955          723 :           || TREE_CODE (part1->builtin->size) != INTEGER_CST
    2956          458 :           || TREE_CODE (part2->builtin->size) != INTEGER_CST
    2957         2377 :           || !operand_equal_p (part1->builtin->dst_base_base,
    2958          458 :                                part2->builtin->dst_base_base, 0))
    2959              :         {
    2960         1809 :           i++;
    2961         1809 :           continue;
    2962              :         }
    2963          110 :       rhs1 = gimple_assign_rhs1 (DR_STMT (part1->builtin->dst_dr));
    2964          110 :       rhs2 = gimple_assign_rhs1 (DR_STMT (part2->builtin->dst_dr));
    2965          110 :       int bytev1 = const_with_all_bytes_same (rhs1);
    2966          110 :       int bytev2 = const_with_all_bytes_same (rhs2);
    2967              :       /* Only merge memset partitions of the same value.  */
    2968          110 :       if (bytev1 != bytev2 || bytev1 == -1)
    2969              :         {
    2970           42 :           i++;
    2971           42 :           continue;
    2972              :         }
    2973          136 :       wide_int end1 = wi::add (part1->builtin->dst_base_offset,
    2974           68 :                                wi::to_wide (part1->builtin->size));
    2975              :       /* Only merge adjacent memset partitions.  */
    2976           68 :       if (wi::ne_p (end1, part2->builtin->dst_base_offset))
    2977              :         {
    2978           40 :           i++;
    2979           40 :           continue;
    2980              :         }
    2981              :       /* Merge partitions[i] and partitions[i+1].  */
    2982           28 :       part1->builtin->size = fold_build2 (PLUS_EXPR, sizetype,
    2983              :                                           part1->builtin->size,
    2984              :                                           part2->builtin->size);
    2985           28 :       partition_free (part2);
    2986           28 :       partitions->ordered_remove (i + 1);
    2987           68 :     }
    2988         2863 : }
    2989              : 
    2990              : void
    2991        41590 : loop_distribution::finalize_partitions (class loop *loop,
    2992              :                                         vec<struct partition *> *partitions,
    2993              :                                         vec<ddr_p> *alias_ddrs)
    2994              : {
    2995        41590 :   unsigned i;
    2996        41590 :   struct partition *partition, *a;
    2997              : 
    2998        47591 :   if (partitions->length () == 1
    2999        41666 :       || alias_ddrs->length () > 0)
    3000        41590 :     return;
    3001              : 
    3002         5925 :   unsigned num_builtin = 0, num_normal = 0, num_partial_memset = 0;
    3003         5925 :   bool same_type_p = true;
    3004         5925 :   enum partition_type type = ((*partitions)[0])->type;
    3005        30976 :   for (i = 0; partitions->iterate (i, &partition); ++i)
    3006              :     {
    3007        25051 :       same_type_p &= (type == partition->type);
    3008        25051 :       if (partition_builtin_p (partition))
    3009              :         {
    3010         2991 :           num_builtin++;
    3011         2991 :           continue;
    3012              :         }
    3013        22060 :       num_normal++;
    3014        22060 :       if (partition->kind == PKIND_PARTIAL_MEMSET)
    3015            4 :         num_partial_memset++;
    3016              :     }
    3017              : 
    3018              :   /* Don't distribute current loop into too many loops given we don't have
    3019              :      memory stream cost model.  Be even more conservative in case of loop
    3020              :      nest distribution.  */
    3021         5925 :   if ((same_type_p && num_builtin == 0
    3022         3035 :        && (loop->inner == NULL || num_normal != 2 || num_partial_memset != 1))
    3023         2894 :       || (loop->inner != NULL
    3024           74 :           && i >= NUM_PARTITION_THRESHOLD && num_normal > 1)
    3025         2885 :       || (loop->inner == NULL
    3026         2820 :           && i >= NUM_PARTITION_THRESHOLD && num_normal > num_builtin))
    3027              :     {
    3028              :       a = (*partitions)[0];
    3029        18828 :       for (i = 1; partitions->iterate (i, &partition); ++i)
    3030              :         {
    3031        15766 :           partition_merge_into (NULL, a, partition, FUSE_FINALIZE);
    3032        15766 :           partition_free (partition);
    3033              :         }
    3034         3062 :       partitions->truncate (1);
    3035              :     }
    3036              : 
    3037              :   /* Fuse memset builtins if possible.  */
    3038         5925 :   if (partitions->length () > 1)
    3039         2863 :     fuse_memset_builtins (partitions);
    3040              : }
    3041              : 
    3042              : /* Distributes the code from LOOP in such a way that producer statements
    3043              :    are placed before consumer statements.  Tries to separate only the
    3044              :    statements from STMTS into separate loops.  Returns the number of
    3045              :    distributed loops.  Set NB_CALLS to number of generated builtin calls.
    3046              :    Set *DESTROY_P to whether LOOP needs to be destroyed.  */
    3047              : 
    3048              : int
    3049       143514 : loop_distribution::distribute_loop (class loop *loop,
    3050              :                  const vec<gimple *> &stmts,
    3051              :                  control_dependences *cd, int *nb_calls, bool *destroy_p,
    3052              :                  bool only_patterns_p)
    3053              : {
    3054       143514 :   ddrs_table = new hash_table<ddr_hasher> (389);
    3055       143514 :   struct graph *rdg;
    3056       143514 :   partition *partition;
    3057       143514 :   int i, nbp;
    3058              : 
    3059       143514 :   *destroy_p = false;
    3060       143514 :   *nb_calls = 0;
    3061       143514 :   loop_nest.create (0);
    3062       143514 :   if (!find_loop_nest (loop, &loop_nest))
    3063              :     {
    3064            0 :       loop_nest.release ();
    3065            0 :       delete ddrs_table;
    3066              :       return 0;
    3067              :     }
    3068              : 
    3069       143514 :   datarefs_vec.create (20);
    3070       143514 :   has_nonaddressable_dataref_p = false;
    3071       143514 :   rdg = build_rdg (loop, cd);
    3072       143514 :   if (!rdg)
    3073              :     {
    3074          929 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3075            0 :         fprintf (dump_file,
    3076              :                  "Loop %d not distributed: failed to build the RDG.\n",
    3077              :                  loop->num);
    3078              : 
    3079          929 :       loop_nest.release ();
    3080          929 :       free_data_refs (datarefs_vec);
    3081          929 :       delete ddrs_table;
    3082              :       return 0;
    3083              :     }
    3084              : 
    3085       285170 :   if (datarefs_vec.length () > MAX_DATAREFS_NUM)
    3086              :     {
    3087            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3088            0 :         fprintf (dump_file,
    3089              :                  "Loop %d not distributed: too many memory references.\n",
    3090              :                  loop->num);
    3091              : 
    3092            0 :       free_rdg (rdg, loop);
    3093            0 :       loop_nest.release ();
    3094            0 :       free_data_refs (datarefs_vec);
    3095            0 :       delete ddrs_table;
    3096              :       return 0;
    3097              :     }
    3098              : 
    3099              :   data_reference_p dref;
    3100       584226 :   for (i = 0; datarefs_vec.iterate (i, &dref); ++i)
    3101       441641 :     dref->aux = (void *) (uintptr_t) i;
    3102              : 
    3103       142585 :   if (dump_file && (dump_flags & TDF_DETAILS))
    3104           70 :     dump_rdg (dump_file, rdg);
    3105              : 
    3106       142585 :   auto_vec<struct partition *, 3> partitions;
    3107       142585 :   rdg_build_partitions (rdg, stmts, &partitions);
    3108              : 
    3109       142585 :   auto_vec<ddr_p> alias_ddrs;
    3110              : 
    3111       142585 :   auto_bitmap stmt_in_all_partitions;
    3112       142585 :   bitmap_copy (stmt_in_all_partitions, partitions[0]->stmts);
    3113       396590 :   for (i = 1; partitions.iterate (i, &partition); ++i)
    3114       111420 :     bitmap_and_into (stmt_in_all_partitions, partitions[i]->stmts);
    3115              : 
    3116              :   bool any_builtin = false;
    3117              :   bool reduction_in_all = false;
    3118       396590 :   int reduction_partition_num = -1;
    3119       539175 :   FOR_EACH_VEC_ELT (partitions, i, partition)
    3120              :     {
    3121       254005 :       reduction_in_all
    3122       254005 :         |= classify_partition (loop, rdg, partition, stmt_in_all_partitions);
    3123       254005 :       any_builtin |= partition_builtin_p (partition);
    3124              :     }
    3125              : 
    3126              :   /* If we are only distributing patterns but did not detect any,
    3127              :      simply bail out.  */
    3128       142585 :   if (only_patterns_p
    3129       142585 :       && !any_builtin)
    3130              :     {
    3131       100995 :       nbp = 0;
    3132       100995 :       goto ldist_done;
    3133              :     }
    3134              : 
    3135              :   /* If we are only distributing patterns fuse all partitions that
    3136              :      were not classified as builtins.  This also avoids chopping
    3137              :      a loop into pieces, separated by builtin calls.  That is, we
    3138              :      only want no or a single loop body remaining.  */
    3139        41590 :   struct partition *into;
    3140        41590 :   if (only_patterns_p)
    3141              :     {
    3142        20349 :       for (i = 0; partitions.iterate (i, &into); ++i)
    3143        11974 :         if (!partition_builtin_p (into))
    3144              :           break;
    3145        54205 :       for (++i; partitions.iterate (i, &partition); ++i)
    3146         2667 :         if (!partition_builtin_p (partition))
    3147              :           {
    3148         1995 :             partition_merge_into (NULL, into, partition, FUSE_NON_BUILTIN);
    3149         1995 :             partitions.unordered_remove (i);
    3150         1995 :             partition_free (partition);
    3151         1995 :             i--;
    3152              :           }
    3153              :     }
    3154              : 
    3155              :   /* Due to limitations in the transform phase we have to fuse all
    3156              :      reduction partitions into the last partition so the existing
    3157              :      loop will contain all loop-closed PHI nodes.  */
    3158       115119 :   for (i = 0; partitions.iterate (i, &into); ++i)
    3159        75630 :     if (partition_reduction_p (into))
    3160              :       break;
    3161        44220 :   for (i = i + 1; partitions.iterate (i, &partition); ++i)
    3162         2630 :     if (partition_reduction_p (partition))
    3163              :       {
    3164         2351 :         partition_merge_into (rdg, into, partition, FUSE_REDUCTION);
    3165         2351 :         partitions.unordered_remove (i);
    3166         2351 :         partition_free (partition);
    3167         2351 :         i--;
    3168              :       }
    3169              : 
    3170              :   /* Apply our simple cost model - fuse partitions with similar
    3171              :      memory accesses.  */
    3172       113947 :   for (i = 0; partitions.iterate (i, &into); ++i)
    3173              :     {
    3174        72357 :       bool changed = false;
    3175      1017754 :       for (int j = i + 1; partitions.iterate (j, &partition); ++j)
    3176              :         {
    3177       873040 :           if (share_memory_accesses (rdg, into, partition))
    3178              :             {
    3179         7214 :               partition_merge_into (rdg, into, partition, FUSE_SHARE_REF);
    3180         7214 :               partitions.unordered_remove (j);
    3181         7214 :               partition_free (partition);
    3182         7214 :               j--;
    3183         7214 :               changed = true;
    3184              :             }
    3185              :         }
    3186              :       /* If we fused 0 1 2 in step 1 to 0,2 1 as 0 and 2 have similar
    3187              :          accesses when 1 and 2 have similar accesses but not 0 and 1
    3188              :          then in the next iteration we will fail to consider merging
    3189              :          1 into 0,2.  So try again if we did any merging into 0.  */
    3190        72357 :       if (changed)
    3191         3662 :         i--;
    3192              :     }
    3193              : 
    3194              :   /* Put a non-builtin partition last if we need to preserve a reduction.
    3195              :      In most cases this helps to keep a normal partition last avoiding to
    3196              :      spill a reduction result across builtin calls.
    3197              :      ???  The proper way would be to use dependences to see whether we
    3198              :      can move builtin partitions earlier during merge_dep_scc_partitions
    3199              :      and its sort_partitions_by_post_order.  Especially when the
    3200              :      dependence graph is composed of multiple independent subgraphs the
    3201              :      heuristic does not work reliably.  */
    3202        41590 :   if (reduction_in_all
    3203        48785 :       && partition_builtin_p (partitions.last()))
    3204          140 :     FOR_EACH_VEC_ELT (partitions, i, partition)
    3205           76 :       if (!partition_builtin_p (partition))
    3206              :         {
    3207           11 :           partitions.unordered_remove (i);
    3208           11 :           partitions.quick_push (partition);
    3209           11 :           break;
    3210              :         }
    3211              : 
    3212              :   /* Build the partition dependency graph and fuse partitions in strong
    3213              :      connected component.  */
    3214        41590 :   if (partitions.length () > 1)
    3215              :     {
    3216              :       /* Don't support loop nest distribution under runtime alias check
    3217              :          since it's not likely to enable many vectorization opportunities.
    3218              :          Also if loop has any data reference which may be not addressable
    3219              :          since alias check needs to take, compare address of the object.  */
    3220         7112 :       if (loop->inner || has_nonaddressable_dataref_p)
    3221          379 :         merge_dep_scc_partitions (rdg, &partitions, false);
    3222              :       else
    3223              :         {
    3224         6733 :           merge_dep_scc_partitions (rdg, &partitions, true);
    3225         6733 :           if (partitions.length () > 1)
    3226         5962 :             break_alias_scc_partitions (rdg, &partitions, &alias_ddrs);
    3227              :         }
    3228              :     }
    3229              : 
    3230        41590 :   finalize_partitions (loop, &partitions, &alias_ddrs);
    3231              : 
    3232              :   /* If there is a reduction in all partitions make sure the last
    3233              :      non-builtin partition provides the LC PHI defs.  */
    3234        41590 :   if (reduction_in_all)
    3235              :     {
    3236        21633 :       FOR_EACH_VEC_ELT (partitions, i, partition)
    3237         7243 :         if (!partition_builtin_p (partition))
    3238         7167 :           reduction_partition_num = i;
    3239         7195 :       if (reduction_partition_num == -1)
    3240              :         {
    3241              :           /* If all partitions are builtin, force the last one to
    3242              :              be code generated as normal partition.  */
    3243           64 :           partition = partitions.last ();
    3244           64 :           partition->kind = PKIND_NORMAL;
    3245              :         }
    3246              :     }
    3247              : 
    3248        41590 :   nbp = partitions.length ();
    3249        41590 :   if (nbp == 0
    3250        80249 :       || (nbp == 1 && !partition_builtin_p (partitions[0]))
    3251        55071 :       || (nbp > 1 && partition_contains_all_rw (rdg, partitions)))
    3252              :     {
    3253        28226 :       nbp = 0;
    3254        28226 :       goto ldist_done;
    3255              :     }
    3256              : 
    3257        13440 :   if (version_for_distribution_p (&partitions, &alias_ddrs))
    3258           76 :     version_loop_by_alias_check (&partitions, loop, &alias_ddrs);
    3259              : 
    3260        13364 :   if (dump_file && (dump_flags & TDF_DETAILS))
    3261              :     {
    3262           42 :       fprintf (dump_file,
    3263              :                "distribute loop <%d> into partitions:\n", loop->num);
    3264           42 :       dump_rdg_partitions (dump_file, partitions);
    3265              :     }
    3266              : 
    3267        30120 :   FOR_EACH_VEC_ELT (partitions, i, partition)
    3268              :     {
    3269        16756 :       if (partition_builtin_p (partition))
    3270        13596 :         (*nb_calls)++;
    3271        16756 :       *destroy_p |= generate_code_for_partition (loop, partition, i < nbp - 1,
    3272              :                                                  i == reduction_partition_num);
    3273              :     }
    3274              : 
    3275       142585 :  ldist_done:
    3276       142585 :   loop_nest.release ();
    3277       142585 :   free_data_refs (datarefs_vec);
    3278       142585 :   for (hash_table<ddr_hasher>::iterator iter = ddrs_table->begin ();
    3279      1331299 :        iter != ddrs_table->end (); ++iter)
    3280              :     {
    3281      1188714 :       free_dependence_relation (*iter);
    3282      1188714 :       *iter = NULL;
    3283              :     }
    3284       142585 :   delete ddrs_table;
    3285              : 
    3286       504019 :   FOR_EACH_VEC_ELT (partitions, i, partition)
    3287       218849 :     partition_free (partition);
    3288              : 
    3289       142585 :   free_rdg (rdg, loop);
    3290       142585 :   return nbp - *nb_calls;
    3291       142585 : }
    3292              : 
    3293              : 
    3294       206788 : void loop_distribution::bb_top_order_init (void)
    3295              : {
    3296       206788 :   int rpo_num;
    3297       206788 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
    3298       206788 :   edge entry = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
    3299       206788 :   bitmap exit_bbs = BITMAP_ALLOC (NULL);
    3300              : 
    3301       206788 :   bb_top_order_index = XNEWVEC (int, last_basic_block_for_fn (cfun));
    3302       206788 :   bb_top_order_index_size = last_basic_block_for_fn (cfun);
    3303              : 
    3304       206788 :   entry->flags &= ~EDGE_DFS_BACK;
    3305       206788 :   bitmap_set_bit (exit_bbs, EXIT_BLOCK);
    3306       206788 :   rpo_num = rev_post_order_and_mark_dfs_back_seme (cfun, entry, exit_bbs, true,
    3307              :                                                    rpo, NULL);
    3308       206788 :   BITMAP_FREE (exit_bbs);
    3309              : 
    3310      7381220 :   for (int i = 0; i < rpo_num; i++)
    3311      6967644 :     bb_top_order_index[rpo[i]] = i;
    3312              : 
    3313       206788 :   free (rpo);
    3314       206788 : }
    3315              : 
    3316       206788 : void loop_distribution::bb_top_order_destroy ()
    3317              : {
    3318       206788 :   free (bb_top_order_index);
    3319       206788 :   bb_top_order_index = NULL;
    3320       206788 :   bb_top_order_index_size = 0;
    3321       206788 : }
    3322              : 
    3323              : 
    3324              : /* Given LOOP, this function records seed statements for distribution in
    3325              :    WORK_LIST.  Return false if there is nothing for distribution.  */
    3326              : 
    3327              : static bool
    3328       189323 : find_seed_stmts_for_distribution (class loop *loop, vec<gimple *> *work_list)
    3329              : {
    3330       189323 :   basic_block *bbs = get_loop_body_in_dom_order (loop);
    3331              : 
    3332              :   /* Initialize the worklist with stmts we seed the partitions with.  */
    3333       872543 :   for (unsigned i = 0; i < loop->num_nodes; ++i)
    3334              :     {
    3335              :       /* In irreducible sub-regions we don't know how to redirect
    3336              :          conditions, so fail.  See PR100492.  */
    3337       539550 :       if (bbs[i]->flags & BB_IRREDUCIBLE_LOOP)
    3338              :         {
    3339            4 :           if (dump_file && (dump_flags & TDF_DETAILS))
    3340            0 :             fprintf (dump_file, "loop %d contains an irreducible region.\n",
    3341              :                      loop->num);
    3342            4 :           work_list->truncate (0);
    3343            4 :           break;
    3344              :         }
    3345       539546 :       for (gphi_iterator gsi = gsi_start_phis (bbs[i]);
    3346      1272250 :            !gsi_end_p (gsi); gsi_next (&gsi))
    3347              :         {
    3348       732704 :           gphi *phi = gsi.phi ();
    3349      1465408 :           if (virtual_operand_p (gimple_phi_result (phi)))
    3350       195951 :             continue;
    3351              :           /* Distribute stmts which have defs that are used outside of
    3352              :              the loop.  */
    3353       536753 :           if (!stmt_has_scalar_dependences_outside_loop (loop, phi))
    3354       511602 :             continue;
    3355        25151 :           work_list->safe_push (phi);
    3356              :         }
    3357      1079092 :       for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]);
    3358      3813667 :            !gsi_end_p (gsi); gsi_next (&gsi))
    3359              :         {
    3360      3319770 :           gimple *stmt = gsi_stmt (gsi);
    3361              : 
    3362              :           /* Ignore clobbers, they do not have true side effects.  */
    3363      3319770 :           if (gimple_clobber_p (stmt))
    3364      2996341 :             continue;
    3365              : 
    3366              :           /* If there is a stmt with side-effects bail out - we
    3367              :              cannot and should not distribute this loop.  */
    3368      3311653 :           if (gimple_has_side_effects (stmt))
    3369              :             {
    3370        45649 :               free (bbs);
    3371        45649 :               return false;
    3372              :             }
    3373              : 
    3374              :           /* Distribute stmts which have defs that are used outside of
    3375              :              the loop.  */
    3376      3266004 :           if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
    3377              :             ;
    3378              :           /* Otherwise only distribute stores for now.  */
    3379      5034162 :           else if (!gimple_vdef (stmt))
    3380      2988224 :             continue;
    3381              : 
    3382       277780 :           work_list->safe_push (stmt);
    3383              :         }
    3384              :     }
    3385       143674 :   bool res = work_list->length () > 0;
    3386       143522 :   if (res && !can_copy_bbs_p (bbs, loop->num_nodes))
    3387              :     {
    3388            7 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3389            0 :         fprintf (dump_file, "cannot copy loop %d.\n", loop->num);
    3390              :       res = false;
    3391              :     }
    3392       143674 :   free (bbs);
    3393       143674 :   return res;
    3394              : }
    3395              : 
    3396              : /* A helper function for generate_{rawmemchr,strlen}_builtin functions in order
    3397              :    to place new statements SEQ before LOOP and replace the old reduction
    3398              :    variable with the new one.  */
    3399              : 
    3400              : static void
    3401           29 : generate_reduction_builtin_1 (loop_p loop, gimple_seq &seq,
    3402              :                               tree reduction_var_old, tree reduction_var_new,
    3403              :                               const char *info, machine_mode load_mode)
    3404              : {
    3405           29 :   gcc_assert (flag_tree_loop_distribute_patterns);
    3406              : 
    3407              :   /* Place new statements before LOOP.  */
    3408           29 :   gimple_stmt_iterator gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
    3409           29 :   gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
    3410              : 
    3411              :   /* Replace old reduction variable with new one.  */
    3412           29 :   imm_use_iterator iter;
    3413           29 :   gimple *stmt;
    3414           29 :   use_operand_p use_p;
    3415          115 :   FOR_EACH_IMM_USE_STMT (stmt, iter, reduction_var_old)
    3416              :     {
    3417          172 :       FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
    3418           86 :         SET_USE (use_p, reduction_var_new);
    3419              : 
    3420           86 :       update_stmt (stmt);
    3421           29 :     }
    3422              : 
    3423           29 :   if (dump_file && (dump_flags & TDF_DETAILS))
    3424            7 :     fprintf (dump_file, info, GET_MODE_NAME (load_mode));
    3425           29 : }
    3426              : 
    3427              : /* Generate a call to rawmemchr and place it before LOOP.  REDUCTION_VAR is
    3428              :    replaced with a fresh SSA name representing the result of the call.  */
    3429              : 
    3430              : static void
    3431            0 : generate_rawmemchr_builtin (loop_p loop, tree reduction_var,
    3432              :                             data_reference_p store_dr, tree base, tree pattern,
    3433              :                             location_t loc)
    3434              : {
    3435            0 :   gimple_seq seq = NULL;
    3436              : 
    3437            0 :   tree mem = force_gimple_operand (base, &seq, true, NULL_TREE);
    3438            0 :   gimple *fn_call = gimple_build_call_internal (IFN_RAWMEMCHR, 2, mem, pattern);
    3439            0 :   tree reduction_var_new = copy_ssa_name (reduction_var);
    3440            0 :   gimple_call_set_lhs (fn_call, reduction_var_new);
    3441            0 :   gimple_set_location (fn_call, loc);
    3442            0 :   gimple_seq_add_stmt (&seq, fn_call);
    3443              : 
    3444            0 :   if (store_dr)
    3445              :     {
    3446            0 :       gassign *g = gimple_build_assign (DR_REF (store_dr), reduction_var_new);
    3447            0 :       gimple_seq_add_stmt (&seq, g);
    3448              :     }
    3449              : 
    3450            0 :   generate_reduction_builtin_1 (loop, seq, reduction_var, reduction_var_new,
    3451              :                                 "generated rawmemchr%s\n",
    3452            0 :                                 TYPE_MODE (TREE_TYPE (TREE_TYPE (base))));
    3453            0 : }
    3454              : 
    3455              : /* Helper function for generate_strlen_builtin(,_using_rawmemchr)  */
    3456              : 
    3457              : static void
    3458           29 : generate_strlen_builtin_1 (loop_p loop, gimple_seq &seq,
    3459              :                            tree reduction_var_old, tree reduction_var_new,
    3460              :                            machine_mode mode, tree start_len)
    3461              : {
    3462              :   /* REDUCTION_VAR_NEW has either size type or ptrdiff type and must be
    3463              :      converted if types of old and new reduction variable are not compatible. */
    3464           29 :   reduction_var_new = gimple_convert (&seq, TREE_TYPE (reduction_var_old),
    3465              :                                       reduction_var_new);
    3466              : 
    3467              :   /* Loops of the form `for (i=42; s[i]; ++i);` have an additional start
    3468              :      length.  */
    3469           29 :   if (!integer_zerop (start_len))
    3470              :     {
    3471           25 :       tree lhs = make_ssa_name (TREE_TYPE (reduction_var_new));
    3472           25 :       gimple *g = gimple_build_assign (lhs, PLUS_EXPR, reduction_var_new,
    3473              :                                        start_len);
    3474           25 :       gimple_seq_add_stmt (&seq, g);
    3475           25 :       reduction_var_new = lhs;
    3476              :     }
    3477              : 
    3478           29 :   generate_reduction_builtin_1 (loop, seq, reduction_var_old, reduction_var_new,
    3479              :                                 "generated strlen%s\n", mode);
    3480           29 : }
    3481              : 
    3482              : /* Generate a call to strlen and place it before LOOP.  REDUCTION_VAR is
    3483              :    replaced with a fresh SSA name representing the result of the call.  */
    3484              : 
    3485              : static void
    3486           29 : generate_strlen_builtin (loop_p loop, tree reduction_var, tree base,
    3487              :                          tree start_len, location_t loc)
    3488              : {
    3489           29 :   gimple_seq seq = NULL;
    3490              : 
    3491           29 :   tree reduction_var_new = make_ssa_name (size_type_node);
    3492              : 
    3493           29 :   tree mem = force_gimple_operand (base, &seq, true, NULL_TREE);
    3494           58 :   tree fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_STRLEN));
    3495           29 :   gimple *fn_call = gimple_build_call (fn, 1, mem);
    3496           29 :   gimple_call_set_lhs (fn_call, reduction_var_new);
    3497           29 :   gimple_set_location (fn_call, loc);
    3498           29 :   gimple_seq_add_stmt (&seq, fn_call);
    3499              : 
    3500           29 :   generate_strlen_builtin_1 (loop, seq, reduction_var, reduction_var_new,
    3501              :                              QImode, start_len);
    3502           29 : }
    3503              : 
    3504              : /* Generate code in order to mimic the behaviour of strlen but this time over
    3505              :    an array of elements with mode different than QI.  REDUCTION_VAR is replaced
    3506              :    with a fresh SSA name representing the result, i.e., the length.  */
    3507              : 
    3508              : static void
    3509            0 : generate_strlen_builtin_using_rawmemchr (loop_p loop, tree reduction_var,
    3510              :                                          tree base, tree load_type,
    3511              :                                          tree start_len, location_t loc)
    3512              : {
    3513            0 :   gimple_seq seq = NULL;
    3514              : 
    3515            0 :   tree start = force_gimple_operand (base, &seq, true, NULL_TREE);
    3516            0 :   tree zero = build_zero_cst (load_type);
    3517            0 :   gimple *fn_call = gimple_build_call_internal (IFN_RAWMEMCHR, 2, start, zero);
    3518            0 :   tree end = make_ssa_name (TREE_TYPE (base));
    3519            0 :   gimple_call_set_lhs (fn_call, end);
    3520            0 :   gimple_set_location (fn_call, loc);
    3521            0 :   gimple_seq_add_stmt (&seq, fn_call);
    3522              : 
    3523              :   /* Determine the number of elements between START and END by
    3524              :      evaluating (END - START) / sizeof (*START).  */
    3525            0 :   tree diff = make_ssa_name (ptrdiff_type_node);
    3526            0 :   gimple *diff_stmt = gimple_build_assign (diff, POINTER_DIFF_EXPR, end, start);
    3527            0 :   gimple_seq_add_stmt (&seq, diff_stmt);
    3528              :   /* Let SIZE be the size of each character.  */
    3529            0 :   tree size = gimple_convert (&seq, ptrdiff_type_node,
    3530            0 :                               TYPE_SIZE_UNIT (load_type));
    3531            0 :   tree count = make_ssa_name (ptrdiff_type_node);
    3532            0 :   gimple *count_stmt = gimple_build_assign (count, TRUNC_DIV_EXPR, diff, size);
    3533            0 :   gimple_seq_add_stmt (&seq, count_stmt);
    3534              : 
    3535            0 :   generate_strlen_builtin_1 (loop, seq, reduction_var, count,
    3536            0 :                              TYPE_MODE (load_type),
    3537              :                              start_len);
    3538            0 : }
    3539              : 
    3540              : /* Return true if we can count at least as many characters by taking pointer
    3541              :    difference as we can count via reduction_var without an overflow.  Thus
    3542              :    compute 2^n < (2^(m-1) / s) where n = TYPE_PRECISION (reduction_var_type),
    3543              :    m = TYPE_PRECISION (ptrdiff_type_node), and s = size of each character.  */
    3544              : static bool
    3545            0 : reduction_var_overflows_first (tree reduction_var_type, tree load_type)
    3546              : {
    3547            0 :   widest_int n2 = wi::lshift (1, TYPE_PRECISION (reduction_var_type));;
    3548            0 :   widest_int m2 = wi::lshift (1, TYPE_PRECISION (ptrdiff_type_node) - 1);
    3549            0 :   widest_int s = wi::to_widest (TYPE_SIZE_UNIT (load_type));
    3550            0 :   return wi::ltu_p (n2, wi::udiv_trunc (m2, s));
    3551            0 : }
    3552              : 
    3553              : static gimple *
    3554        25374 : determine_reduction_stmt_1 (const loop_p loop, const basic_block *bbs)
    3555              : {
    3556        25374 :   gimple *reduction_stmt = NULL;
    3557              : 
    3558        92477 :   for (unsigned i = 0, ninsns = 0; i < loop->num_nodes; ++i)
    3559              :     {
    3560        72662 :       basic_block bb = bbs[i];
    3561              : 
    3562       139732 :       for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
    3563        67070 :            gsi_next (&bsi))
    3564              :         {
    3565        67806 :           gphi *phi = bsi.phi ();
    3566       135612 :           if (virtual_operand_p (gimple_phi_result (phi)))
    3567        21093 :             continue;
    3568        46713 :           if (stmt_has_scalar_dependences_outside_loop (loop, phi))
    3569              :             {
    3570         8197 :               if (reduction_stmt)
    3571          736 :                 return NULL;
    3572              :               reduction_stmt = phi;
    3573              :             }
    3574              :         }
    3575              : 
    3576        71926 :       for (gimple_stmt_iterator bsi = gsi_start_nondebug_bb (bb);
    3577       225009 :            !gsi_end_p (bsi); gsi_next_nondebug (&bsi), ++ninsns)
    3578              :         {
    3579              :           /* Bail out early for loops which are unlikely to match.  */
    3580       157906 :           if (ninsns > 16)
    3581         4823 :             return NULL;
    3582       154967 :           gimple *stmt = gsi_stmt (bsi);
    3583       154967 :           if (gimple_clobber_p (stmt))
    3584         5688 :             continue;
    3585       149279 :           if (gimple_code (stmt) == GIMPLE_LABEL)
    3586         1001 :             continue;
    3587       264370 :           if (gimple_has_volatile_ops (stmt))
    3588              :             return NULL;
    3589       148231 :           if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
    3590              :             {
    3591         6165 :               if (reduction_stmt)
    3592              :                 return NULL;
    3593              :               reduction_stmt = stmt;
    3594              :             }
    3595              :         }
    3596              :     }
    3597              : 
    3598              :   return reduction_stmt;
    3599              : }
    3600              : 
    3601              : /* If LOOP has a single non-volatile reduction statement, then return a pointer
    3602              :    to it.  Otherwise return NULL.  */
    3603              : static gimple *
    3604        25374 : determine_reduction_stmt (const loop_p loop)
    3605              : {
    3606        25374 :   basic_block *bbs = get_loop_body (loop);
    3607        25374 :   gimple *reduction_stmt = determine_reduction_stmt_1 (loop, bbs);
    3608        25374 :   XDELETEVEC (bbs);
    3609        25374 :   return reduction_stmt;
    3610              : }
    3611              : 
    3612              : /* Transform loops which mimic the effects of builtins rawmemchr or strlen and
    3613              :    replace them accordingly.  For example, a loop of the form
    3614              : 
    3615              :      for (; *p != 42; ++p);
    3616              : 
    3617              :    is replaced by
    3618              : 
    3619              :      p = rawmemchr<MODE> (p, 42);
    3620              : 
    3621              :    under the assumption that rawmemchr is available for a particular MODE.
    3622              :    Another example is
    3623              : 
    3624              :      int i;
    3625              :      for (i = 42; s[i]; ++i);
    3626              : 
    3627              :    which is replaced by
    3628              : 
    3629              :      i = (int)strlen (&s[42]) + 42;
    3630              : 
    3631              :    for some character array S.  In case array S is not of type character array
    3632              :    we end up with
    3633              : 
    3634              :      i = (int)(rawmemchr<MODE> (&s[42], 0) - &s[42]) + 42;
    3635              : 
    3636              :    assuming that rawmemchr is available for a particular MODE.  */
    3637              : 
    3638              : bool
    3639        85301 : loop_distribution::transform_reduction_loop (loop_p loop)
    3640              : {
    3641        85301 :   gimple *reduction_stmt;
    3642        85301 :   data_reference_p load_dr = NULL, store_dr = NULL;
    3643              : 
    3644        85301 :   edge e = single_exit (loop);
    3645       170602 :   gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (e->src));
    3646        67791 :   if (!cond)
    3647              :     return false;
    3648              :   /* Ensure loop condition is an (in)equality test and loop is exited either if
    3649              :      the inequality test fails or the equality test succeeds.  */
    3650        52076 :   if (!(e->flags & EDGE_FALSE_VALUE && gimple_cond_code (cond) == NE_EXPR)
    3651        89463 :       && !(e->flags & EDGE_TRUE_VALUE && gimple_cond_code (cond) == EQ_EXPR))
    3652              :     return false;
    3653              :   /* A limitation of the current implementation is that we only support
    3654              :      constant patterns in (in)equality tests.  */
    3655        33299 :   tree pattern = gimple_cond_rhs (cond);
    3656        33299 :   if (TREE_CODE (pattern) != INTEGER_CST)
    3657              :     return false;
    3658              : 
    3659        25374 :   reduction_stmt = determine_reduction_stmt (loop);
    3660              : 
    3661              :   /* A limitation of the current implementation is that we require a reduction
    3662              :      statement.  Therefore, loops without a reduction statement as in the
    3663              :      following are not recognized:
    3664              :      int *p;
    3665              :      void foo (void) { for (; *p; ++p); } */
    3666        25374 :   if (reduction_stmt == NULL)
    3667              :     return false;
    3668              : 
    3669              :   /* Reduction variables are guaranteed to be SSA names.  */
    3670         9089 :   tree reduction_var;
    3671         9089 :   switch (gimple_code (reduction_stmt))
    3672              :     {
    3673         8992 :     case GIMPLE_ASSIGN:
    3674         8992 :     case GIMPLE_PHI:
    3675         8992 :       reduction_var = gimple_get_lhs (reduction_stmt);
    3676         8992 :       break;
    3677              :     default:
    3678              :       /* Bail out e.g. for GIMPLE_CALL.  */
    3679              :       return false;
    3680              :     }
    3681              : 
    3682         8992 :   struct graph *rdg = build_rdg (loop, NULL);
    3683         8992 :   if (rdg == NULL)
    3684              :     {
    3685          699 :       if (dump_file && (dump_flags & TDF_DETAILS))
    3686            0 :         fprintf (dump_file,
    3687              :                  "Loop %d not transformed: failed to build the RDG.\n",
    3688              :                  loop->num);
    3689              : 
    3690              :       return false;
    3691              :     }
    3692        16586 :   auto_bitmap partition_stmts;
    3693         8293 :   bitmap_set_range (partition_stmts, 0, rdg->n_vertices);
    3694         8293 :   find_single_drs (loop, rdg, partition_stmts, &store_dr, &load_dr);
    3695         8293 :   free_rdg (rdg, loop);
    3696              : 
    3697              :   /* Bail out if there is no single load.  */
    3698         8293 :   if (load_dr == NULL)
    3699              :     return false;
    3700              : 
    3701              :   /* Reaching this point we have a loop with a single reduction variable,
    3702              :      a single load, and an optional single store.  */
    3703              : 
    3704         4433 :   tree load_ref = DR_REF (load_dr);
    3705         4433 :   tree load_type = TREE_TYPE (load_ref);
    3706         4433 :   tree load_access_base = build_fold_addr_expr (load_ref);
    3707         4433 :   tree load_access_size = TYPE_SIZE_UNIT (load_type);
    3708         4433 :   affine_iv load_iv, reduction_iv;
    3709              : 
    3710         4433 :   if (!INTEGRAL_TYPE_P (load_type)
    3711         4433 :       || !type_has_mode_precision_p (load_type))
    3712              :     return false;
    3713              : 
    3714              :   /* We already ensured that the loop condition tests for (in)equality where the
    3715              :      rhs is a constant pattern. Now ensure that the lhs is the result of the
    3716              :      load.  */
    3717         1693 :   if (gimple_cond_lhs (cond) != gimple_assign_lhs (DR_STMT (load_dr)))
    3718              :     return false;
    3719              : 
    3720              :   /* Bail out if no affine induction variable with constant step can be
    3721              :      determined.  */
    3722         1548 :   if (!simple_iv (loop, loop, load_access_base, &load_iv, false))
    3723              :     return false;
    3724              : 
    3725              :   /* Bail out if memory accesses are not consecutive or not growing.  */
    3726         1527 :   if (!operand_equal_p (load_iv.step, load_access_size, 0))
    3727              :     return false;
    3728              : 
    3729         1499 :   if (!simple_iv (loop, loop, reduction_var, &reduction_iv, false))
    3730              :     return false;
    3731              : 
    3732              :   /* Handle rawmemchr like loops.  */
    3733         1383 :   if (operand_equal_p (load_iv.base, reduction_iv.base)
    3734         1383 :       && operand_equal_p (load_iv.step, reduction_iv.step))
    3735              :     {
    3736          355 :       if (store_dr)
    3737              :         {
    3738              :           /* Ensure that we store to X and load from X+I where I>0.  */
    3739            0 :           if (TREE_CODE (load_iv.base) != POINTER_PLUS_EXPR
    3740            0 :               || !integer_onep (TREE_OPERAND (load_iv.base, 1)))
    3741              :             return false;
    3742            0 :           tree ptr_base = TREE_OPERAND (load_iv.base, 0);
    3743            0 :           if (TREE_CODE (ptr_base) != SSA_NAME)
    3744              :             return false;
    3745            0 :           gimple *def = SSA_NAME_DEF_STMT (ptr_base);
    3746            0 :           if (!gimple_assign_single_p (def)
    3747            0 :               || gimple_assign_rhs1 (def) != DR_REF (store_dr))
    3748              :             return false;
    3749              :           /* Ensure that the reduction value is stored.  */
    3750            0 :           if (gimple_assign_rhs1 (DR_STMT (store_dr)) != reduction_var)
    3751              :             return false;
    3752              :         }
    3753              :       /* Bail out if target does not provide rawmemchr for a certain mode.  */
    3754          355 :       machine_mode mode = TYPE_MODE (load_type);
    3755          355 :       if (direct_optab_handler (rawmemchr_optab, mode) == CODE_FOR_nothing)
    3756              :         return false;
    3757            0 :       location_t loc = gimple_location (DR_STMT (load_dr));
    3758            0 :       generate_rawmemchr_builtin (loop, reduction_var, store_dr, load_iv.base,
    3759              :                                   pattern, loc);
    3760            0 :       return true;
    3761              :     }
    3762              : 
    3763              :   /* Handle strlen like loops.  */
    3764         1028 :   if (store_dr == NULL
    3765         1018 :       && integer_zerop (pattern)
    3766         1018 :       && INTEGRAL_TYPE_P (TREE_TYPE (reduction_var))
    3767         1008 :       && TREE_CODE (reduction_iv.base) == INTEGER_CST
    3768         1004 :       && TREE_CODE (reduction_iv.step) == INTEGER_CST
    3769         2032 :       && integer_onep (reduction_iv.step))
    3770              :     {
    3771          948 :       location_t loc = gimple_location (DR_STMT (load_dr));
    3772          948 :       tree reduction_var_type = TREE_TYPE (reduction_var);
    3773              :       /* While determining the length of a string an overflow might occur.
    3774              :          If an overflow only occurs in the loop implementation and not in the
    3775              :          strlen implementation, then either the overflow is undefined or the
    3776              :          truncated result of strlen equals the one of the loop.  Otherwise if
    3777              :          an overflow may also occur in the strlen implementation, then
    3778              :          replacing a loop by a call to strlen is sound whenever we ensure that
    3779              :          if an overflow occurs in the strlen implementation, then also an
    3780              :          overflow occurs in the loop implementation which is undefined.  It
    3781              :          seems reasonable to relax this and assume that the strlen
    3782              :          implementation cannot overflow in case sizetype is big enough in the
    3783              :          sense that an overflow can only happen for string objects which are
    3784              :          bigger than half of the address space; at least for 32-bit targets and
    3785              :          up.
    3786              : 
    3787              :          For strlen which makes use of rawmemchr the maximal length of a string
    3788              :          which can be determined without an overflow is PTRDIFF_MAX / S where
    3789              :          each character has size S.  Since an overflow for ptrdiff type is
    3790              :          undefined we have to make sure that if an overflow occurs, then an
    3791              :          overflow occurs in the loop implementation, too, and this is
    3792              :          undefined, too.  Similar as before we relax this and assume that no
    3793              :          string object is larger than half of the address space; at least for
    3794              :          32-bit targets and up.  */
    3795          948 :       if (TYPE_MODE (load_type) == TYPE_MODE (char_type_node)
    3796          664 :           && TYPE_PRECISION (load_type) == TYPE_PRECISION (char_type_node)
    3797          664 :           && ((TYPE_PRECISION (sizetype) >= TYPE_PRECISION (ptr_type_node) - 1
    3798          664 :                && TYPE_PRECISION (ptr_type_node) >= 32)
    3799            0 :               || (TYPE_OVERFLOW_UNDEFINED (reduction_var_type)
    3800            0 :                   && TYPE_PRECISION (reduction_var_type) <= TYPE_PRECISION (sizetype)))
    3801          977 :           && builtin_decl_implicit (BUILT_IN_STRLEN))
    3802           29 :         generate_strlen_builtin (loop, reduction_var, load_iv.base,
    3803              :                                  reduction_iv.base, loc);
    3804          919 :       else if (direct_optab_handler (rawmemchr_optab, TYPE_MODE (load_type))
    3805              :                != CODE_FOR_nothing
    3806          919 :                && ((TYPE_PRECISION (ptrdiff_type_node) == TYPE_PRECISION (ptr_type_node)
    3807            0 :                     && TYPE_PRECISION (ptrdiff_type_node) >= 32)
    3808            0 :                    || (TYPE_OVERFLOW_UNDEFINED (reduction_var_type)
    3809            0 :                        && reduction_var_overflows_first (reduction_var_type, load_type))))
    3810            0 :         generate_strlen_builtin_using_rawmemchr (loop, reduction_var,
    3811              :                                                  load_iv.base,
    3812              :                                                  load_type,
    3813              :                                                  reduction_iv.base, loc);
    3814              :       else
    3815              :         return false;
    3816              :       return true;
    3817              :     }
    3818              : 
    3819              :   return false;
    3820              : }
    3821              : 
    3822              : /* Given innermost LOOP, return the outermost enclosing loop that forms a
    3823              :    perfect loop nest.  */
    3824              : 
    3825              : static class loop *
    3826       172160 : prepare_perfect_loop_nest (class loop *loop)
    3827              : {
    3828       172160 :   class loop *outer = loop_outer (loop);
    3829       172160 :   tree niters = number_of_latch_executions (loop);
    3830              : 
    3831              :   /* TODO: We only support the innermost 3-level loop nest distribution
    3832              :      because of compilation time issue for now.  This should be relaxed
    3833              :      in the future.  Note we only allow 3-level loop nest distribution
    3834              :      when parallelizing loops.  */
    3835       172160 :   while ((loop->inner == NULL
    3836        17676 :           || (loop->inner->inner == NULL && flag_tree_parallelize_loops > 1))
    3837       172220 :          && loop_outer (outer)
    3838        41871 :          && outer->inner == loop && loop->next == NULL
    3839        27116 :          && single_exit (outer)
    3840        25394 :          && !chrec_contains_symbols_defined_in_loop (niters, outer->num)
    3841        18612 :          && (niters = number_of_latch_executions (outer)) != NULL_TREE
    3842       208448 :          && niters != chrec_dont_know)
    3843              :     {
    3844        17676 :       loop = outer;
    3845        17676 :       outer = loop_outer (loop);
    3846              :     }
    3847              : 
    3848       172160 :   return loop;
    3849              : }
    3850              : 
    3851              : 
    3852              : unsigned int
    3853       206788 : loop_distribution::execute (function *fun)
    3854              : {
    3855       206788 :   bool changed = false;
    3856       206788 :   basic_block bb;
    3857       206788 :   control_dependences *cd = NULL;
    3858       206788 :   auto_vec<loop_p> loops_to_be_destroyed;
    3859              : 
    3860       620364 :   if (number_of_loops (fun) <= 1)
    3861              :     return 0;
    3862              : 
    3863       206788 :   bb_top_order_init ();
    3864              : 
    3865      7588008 :   FOR_ALL_BB_FN (bb, fun)
    3866              :     {
    3867      7381220 :       gimple_stmt_iterator gsi;
    3868     11443123 :       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    3869      4061903 :         gimple_set_uid (gsi_stmt (gsi), -1);
    3870     69456648 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    3871     54694208 :         gimple_set_uid (gsi_stmt (gsi), -1);
    3872              :     }
    3873              : 
    3874              :   /* We can at the moment only distribute non-nested loops, thus restrict
    3875              :      walking to innermost loops.  */
    3876      1051625 :   for (auto loop : loops_list (cfun, LI_ONLY_INNERMOST))
    3877              :     {
    3878              :       /* Don't distribute multiple exit edges loop, or cold loop when
    3879              :          not doing pattern detection.  */
    3880       431261 :       if (!single_exit (loop)
    3881       431261 :           || (!flag_tree_loop_distribute_patterns
    3882         1380 :               && !optimize_loop_for_speed_p (loop)))
    3883       173573 :         continue;
    3884              : 
    3885              :       /* If niters is unknown don't distribute loop but rather try to transform
    3886              :          it to a call to a builtin.  */
    3887       257688 :       tree niters = number_of_latch_executions (loop);
    3888       257688 :       if (niters == NULL_TREE || niters == chrec_dont_know)
    3889              :         {
    3890        85528 :           datarefs_vec.create (20);
    3891        85528 :           if (flag_tree_loop_distribute_patterns
    3892        85528 :               && transform_reduction_loop (loop))
    3893              :             {
    3894           29 :               changed = true;
    3895           29 :               loops_to_be_destroyed.safe_push (loop);
    3896           29 :               if (dump_enabled_p ())
    3897              :                 {
    3898            7 :                   dump_user_location_t loc = find_loop_location (loop);
    3899            7 :                   dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
    3900              :                                    loc, "Loop %d transformed into a builtin.\n",
    3901              :                                    loop->num);
    3902              :                 }
    3903              :             }
    3904        85528 :           free_data_refs (datarefs_vec);
    3905        85528 :           continue;
    3906        85528 :         }
    3907              : 
    3908              :       /* Get the perfect loop nest for distribution.  */
    3909       172160 :       loop = prepare_perfect_loop_nest (loop);
    3910       348119 :       for (; loop; loop = loop->inner)
    3911              :         {
    3912       189323 :           auto_vec<gimple *> work_list;
    3913       189323 :           if (!find_seed_stmts_for_distribution (loop, &work_list))
    3914        45809 :             continue;
    3915              : 
    3916       143514 :           const char *str = loop->inner ? " nest" : "";
    3917       143514 :           dump_user_location_t loc = find_loop_location (loop);
    3918       143514 :           if (!cd)
    3919              :             {
    3920        63606 :               calculate_dominance_info (CDI_DOMINATORS);
    3921        63606 :               calculate_dominance_info (CDI_POST_DOMINATORS);
    3922        63606 :               cd = new control_dependences ();
    3923        63606 :               free_dominance_info (CDI_POST_DOMINATORS);
    3924              :             }
    3925              : 
    3926       143514 :           bool destroy_p;
    3927       143514 :           int nb_generated_loops, nb_generated_calls;
    3928       143514 :           bool only_patterns = !optimize_loop_for_speed_p (loop)
    3929       143514 :                                || !flag_tree_loop_distribution;
    3930              :           /* do not try to distribute loops that are not expected to iterate.  */
    3931        31941 :           if (!only_patterns)
    3932              :             {
    3933        31941 :               HOST_WIDE_INT iterations = estimated_loop_iterations_int (loop);
    3934        31941 :               if (iterations < 0)
    3935        15321 :                 iterations = likely_max_loop_iterations_int (loop);
    3936        31941 :               if (!iterations)
    3937       111583 :                 only_patterns = true;
    3938              :             }
    3939       143514 :           nb_generated_loops
    3940       143514 :             = distribute_loop (loop, work_list, cd, &nb_generated_calls,
    3941              :                                &destroy_p, only_patterns);
    3942       143514 :           if (destroy_p)
    3943        11411 :             loops_to_be_destroyed.safe_push (loop);
    3944              : 
    3945       143514 :           if (nb_generated_loops + nb_generated_calls > 0)
    3946              :             {
    3947        13364 :               changed = true;
    3948        13364 :               if (dump_enabled_p ())
    3949           71 :                 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
    3950              :                                  loc, "Loop%s %d distributed: split to %d loops "
    3951              :                                  "and %d library calls.\n", str, loop->num,
    3952              :                                  nb_generated_loops, nb_generated_calls);
    3953              : 
    3954        13364 :               break;
    3955              :             }
    3956              : 
    3957       130150 :           if (dump_file && (dump_flags & TDF_DETAILS))
    3958           28 :             fprintf (dump_file, "Loop%s %d not distributed.\n", str, loop->num);
    3959       189323 :         }
    3960       206788 :     }
    3961              : 
    3962       206788 :   if (cd)
    3963        63606 :     delete cd;
    3964              : 
    3965       206788 :   if (bb_top_order_index != NULL)
    3966       206788 :     bb_top_order_destroy ();
    3967              : 
    3968       206788 :   if (changed)
    3969              :     {
    3970              :       /* Destroy loop bodies that could not be reused.  Do this late as we
    3971              :          otherwise can end up referring to stale data in control
    3972              :          dependences.  */
    3973              :       unsigned i;
    3974              :       class loop *loop;
    3975        19401 :       FOR_EACH_VEC_ELT (loops_to_be_destroyed, i, loop)
    3976        11440 :         destroy_loop (loop);
    3977              : 
    3978              :       /* Cached scalar evolutions now may refer to wrong or non-existing
    3979              :          loops.  */
    3980         7961 :       scev_reset ();
    3981         7961 :       mark_virtual_operands_for_renaming (fun);
    3982         7961 :       rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
    3983              :     }
    3984              : 
    3985       206788 :   checking_verify_loop_structure ();
    3986              : 
    3987       206788 :   return changed ? TODO_cleanup_cfg : 0;
    3988       206788 : }
    3989              : 
    3990              : 
    3991              : /* Distribute all loops in the current function.  */
    3992              : 
    3993              : namespace {
    3994              : 
    3995              : const pass_data pass_data_loop_distribution =
    3996              : {
    3997              :   GIMPLE_PASS, /* type */
    3998              :   "ldist", /* name */
    3999              :   OPTGROUP_LOOP, /* optinfo_flags */
    4000              :   TV_TREE_LOOP_DISTRIBUTION, /* tv_id */
    4001              :   ( PROP_cfg | PROP_ssa ), /* properties_required */
    4002              :   0, /* properties_provided */
    4003              :   0, /* properties_destroyed */
    4004              :   0, /* todo_flags_start */
    4005              :   0, /* todo_flags_finish */
    4006              : };
    4007              : 
    4008              : class pass_loop_distribution : public gimple_opt_pass
    4009              : {
    4010              : public:
    4011       294536 :   pass_loop_distribution (gcc::context *ctxt)
    4012       589072 :     : gimple_opt_pass (pass_data_loop_distribution, ctxt)
    4013              :   {}
    4014              : 
    4015              :   /* opt_pass methods: */
    4016       247693 :   bool gate (function *) final override
    4017              :     {
    4018       247693 :       return flag_tree_loop_distribution
    4019       247693 :         || flag_tree_loop_distribute_patterns;
    4020              :     }
    4021              : 
    4022              :   unsigned int execute (function *) final override;
    4023              : 
    4024              : }; // class pass_loop_distribution
    4025              : 
    4026              : unsigned int
    4027       206788 : pass_loop_distribution::execute (function *fun)
    4028              : {
    4029       206788 :   return loop_distribution ().execute (fun);
    4030              : }
    4031              : 
    4032              : } // anon namespace
    4033              : 
    4034              : gimple_opt_pass *
    4035       294536 : make_pass_loop_distribution (gcc::context *ctxt)
    4036              : {
    4037       294536 :   return new pass_loop_distribution (ctxt);
    4038              : }
        

Generated by: LCOV version 2.5.0-beta

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,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.