LCOV - code coverage report
Current view: top level - gcc - graphite-scop-detection.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 81.7 % 774 632
Test Date: 2026-02-28 14:20:25 Functions: 92.3 % 39 36
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Detection of Static Control Parts (SCoP) for Graphite.
       2              :    Copyright (C) 2009-2026 Free Software Foundation, Inc.
       3              :    Contributed by Sebastian Pop <sebastian.pop@amd.com> and
       4              :    Tobias Grosser <grosser@fim.uni-passau.de>.
       5              : 
       6              : This file is part of GCC.
       7              : 
       8              : GCC is free software; you can redistribute it and/or modify
       9              : it under the terms of the GNU General Public License as published by
      10              : the Free Software Foundation; either version 3, or (at your option)
      11              : any later version.
      12              : 
      13              : GCC is distributed in the hope that it will be useful,
      14              : but WITHOUT ANY WARRANTY; without even the implied warranty of
      15              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16              : GNU General Public License 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              : #define INCLUDE_ISL
      23              : 
      24              : #include "config.h"
      25              : 
      26              : #ifdef HAVE_isl
      27              : 
      28              : #include "system.h"
      29              : #include "coretypes.h"
      30              : #include "backend.h"
      31              : #include "cfghooks.h"
      32              : #include "domwalk.h"
      33              : #include "tree.h"
      34              : #include "gimple.h"
      35              : #include "ssa.h"
      36              : #include "fold-const.h"
      37              : #include "gimple-iterator.h"
      38              : #include "tree-cfg.h"
      39              : #include "tree-ssa-loop-manip.h"
      40              : #include "tree-ssa-loop-niter.h"
      41              : #include "tree-ssa-loop.h"
      42              : #include "tree-into-ssa.h"
      43              : #include "tree-ssa.h"
      44              : #include "cfgloop.h"
      45              : #include "tree-data-ref.h"
      46              : #include "tree-scalar-evolution.h"
      47              : #include "tree-pass.h"
      48              : #include "tree-ssa-propagate.h"
      49              : #include "gimple-pretty-print.h"
      50              : #include "cfganal.h"
      51              : #include "graphite.h"
      52              : 
      53              : class debug_printer
      54              : {
      55              : private:
      56              :   FILE *dump_file;
      57              : 
      58              : public:
      59              :   void
      60          190 :   set_dump_file (FILE *f)
      61              :   {
      62          190 :     gcc_assert (f);
      63          190 :     dump_file = f;
      64          190 :   }
      65              : 
      66              :   friend debug_printer &
      67         2559 :   operator<< (debug_printer &output, int i)
      68              :   {
      69            0 :     fprintf (output.dump_file, "%d", i);
      70          189 :     return output;
      71              :   }
      72              : 
      73              :   friend debug_printer &
      74         8699 :   operator<< (debug_printer &output, const char *s)
      75              :   {
      76         8699 :     fprintf (output.dump_file, "%s", s);
      77         2971 :     return output;
      78              :   }
      79              : 
      80              :   friend debug_printer &
      81              :   operator<< (debug_printer &output, gimple* stmt)
      82              :   {
      83              :     print_gimple_stmt (output.dump_file, stmt, 0, TDF_VOPS | TDF_MEMSYMS);
      84              :     return output;
      85              :   }
      86              : 
      87              :   friend debug_printer &
      88           49 :   operator<< (debug_printer &output, tree t)
      89              :   {
      90           49 :     print_generic_expr (output.dump_file, t, TDF_SLIM);
      91           49 :     return output;
      92              :   }
      93              : } dp;
      94              : 
      95              : #define DEBUG_PRINT(args) do \
      96              :     {                                                           \
      97              :       if (dump_file && (dump_flags & TDF_DETAILS)) { args; }        \
      98              :     } while (0)
      99              : 
     100              : /* Pretty print to FILE all the SCoPs in DOT format and mark them with
     101              :    different colors.  If there are not enough colors, paint the
     102              :    remaining SCoPs in gray.
     103              : 
     104              :    Special nodes:
     105              :    - "*" after the node number denotes the entry of a SCoP,
     106              :    - "#" after the node number denotes the exit of a SCoP,
     107              :    - "()" around the node number denotes the entry or the
     108              :      exit nodes of the SCOP.  These are not part of SCoP.  */
     109              : 
     110              : DEBUG_FUNCTION void
     111            0 : dot_all_sese (FILE *file, vec<sese_l>& scops)
     112              : {
     113              :   /* Disable debugging while printing graph.  */
     114            0 :   dump_flags_t tmp_dump_flags = dump_flags;
     115            0 :   dump_flags = TDF_NONE;
     116              : 
     117            0 :   fprintf (file, "digraph all {\n");
     118              : 
     119            0 :   basic_block bb;
     120            0 :   FOR_ALL_BB_FN (bb, cfun)
     121              :     {
     122            0 :       int part_of_scop = false;
     123              : 
     124              :       /* Use HTML for every bb label.  So we are able to print bbs
     125              :          which are part of two different SCoPs, with two different
     126              :          background colors.  */
     127            0 :       fprintf (file, "%d [label=<\n  <TABLE BORDER=\"0\" CELLBORDER=\"1\" ",
     128              :                bb->index);
     129            0 :       fprintf (file, "CELLSPACING=\"0\">\n");
     130              : 
     131              :       /* Select color for SCoP.  */
     132            0 :       sese_l *region;
     133            0 :       int i;
     134            0 :       FOR_EACH_VEC_ELT (scops, i, region)
     135              :         {
     136            0 :           bool sese_in_region = bb_in_sese_p (bb, *region);
     137            0 :           if (sese_in_region || (region->exit->dest == bb)
     138            0 :               || (region->entry->dest == bb))
     139              :             {
     140            0 :               const char *color;
     141            0 :               switch (i % 17)
     142              :                 {
     143              :                 case 0: /* red */
     144              :                   color = "#e41a1c";
     145              :                   break;
     146            0 :                 case 1: /* blue */
     147            0 :                   color = "#377eb8";
     148            0 :                   break;
     149            0 :                 case 2: /* green */
     150            0 :                   color = "#4daf4a";
     151            0 :                   break;
     152            0 :                 case 3: /* purple */
     153            0 :                   color = "#984ea3";
     154            0 :                   break;
     155            0 :                 case 4: /* orange */
     156            0 :                   color = "#ff7f00";
     157            0 :                   break;
     158            0 :                 case 5: /* yellow */
     159            0 :                   color = "#ffff33";
     160            0 :                   break;
     161            0 :                 case 6: /* brown */
     162            0 :                   color = "#a65628";
     163            0 :                   break;
     164            0 :                 case 7: /* rose */
     165            0 :                   color = "#f781bf";
     166            0 :                   break;
     167            0 :                 case 8:
     168            0 :                   color = "#8dd3c7";
     169            0 :                   break;
     170            0 :                 case 9:
     171            0 :                   color = "#ffffb3";
     172            0 :                   break;
     173            0 :                 case 10:
     174            0 :                   color = "#bebada";
     175            0 :                   break;
     176            0 :                 case 11:
     177            0 :                   color = "#fb8072";
     178            0 :                   break;
     179            0 :                 case 12:
     180            0 :                   color = "#80b1d3";
     181            0 :                   break;
     182            0 :                 case 13:
     183            0 :                   color = "#fdb462";
     184            0 :                   break;
     185            0 :                 case 14:
     186            0 :                   color = "#b3de69";
     187            0 :                   break;
     188            0 :                 case 15:
     189            0 :                   color = "#fccde5";
     190            0 :                   break;
     191            0 :                 case 16:
     192            0 :                   color = "#bc80bd";
     193            0 :                   break;
     194              :                 default: /* gray */
     195              :                   color = "#999999";
     196              :                 }
     197              : 
     198            0 :               fprintf (file, "    <TR><TD WIDTH=\"50\" BGCOLOR=\"%s\">",
     199              :                        color);
     200              : 
     201            0 :               if (!sese_in_region)
     202            0 :                 fprintf (file, " (");
     203              : 
     204            0 :               if (bb == region->entry->dest && bb == region->exit->dest)
     205            0 :                 fprintf (file, " %d*# ", bb->index);
     206            0 :               else if (bb == region->entry->dest)
     207            0 :                 fprintf (file, " %d* ", bb->index);
     208            0 :               else if (bb == region->exit->dest)
     209            0 :                 fprintf (file, " %d# ", bb->index);
     210              :               else
     211            0 :                 fprintf (file, " %d ", bb->index);
     212              : 
     213            0 :               fprintf (file, "{lp_%d}", bb->loop_father->num);
     214              : 
     215            0 :               if (!sese_in_region)
     216            0 :                 fprintf (file, ")");
     217              : 
     218            0 :               fprintf (file, "</TD></TR>\n");
     219            0 :               part_of_scop = true;
     220              :             }
     221              :         }
     222              : 
     223            0 :         if (!part_of_scop)
     224              :           {
     225            0 :             fprintf (file, "    <TR><TD WIDTH=\"50\" BGCOLOR=\"#ffffff\">");
     226            0 :             fprintf (file, " %d {lp_%d} </TD></TR>\n", bb->index,
     227            0 :                      bb->loop_father->num);
     228              :           }
     229            0 :         fprintf (file, "  </TABLE>>, shape=box, style=\"setlinewidth(0)\"]\n");
     230              :     }
     231              : 
     232            0 :     FOR_ALL_BB_FN (bb, cfun)
     233              :       {
     234            0 :         edge e;
     235            0 :         edge_iterator ei;
     236            0 :         FOR_EACH_EDGE (e, ei, bb->succs)
     237            0 :           fprintf (file, "%d -> %d;\n", bb->index, e->dest->index);
     238              :       }
     239              : 
     240            0 :   fputs ("}\n\n", file);
     241              : 
     242              :   /* Enable debugging again.  */
     243            0 :   dump_flags = tmp_dump_flags;
     244            0 : }
     245              : 
     246              : /* Display SCoP on stderr.  */
     247              : 
     248              : DEBUG_FUNCTION void
     249            0 : dot_sese (sese_l& scop)
     250              : {
     251            0 :   vec<sese_l> scops;
     252            0 :   scops.create (1);
     253              : 
     254            0 :   if (scop)
     255            0 :     scops.safe_push (scop);
     256              : 
     257            0 :   dot_all_sese (stderr, scops);
     258              : 
     259            0 :   scops.release ();
     260            0 : }
     261              : 
     262              : DEBUG_FUNCTION void
     263            0 : dot_cfg ()
     264              : {
     265            0 :   vec<sese_l> scops;
     266            0 :   scops.create (1);
     267            0 :   dot_all_sese (stderr, scops);
     268            0 :   scops.release ();
     269            0 : }
     270              : 
     271              : /* Returns a COND_EXPR statement when BB has a single predecessor, the
     272              :    edge between BB and its predecessor is not a loop exit edge, and
     273              :    the last statement of the single predecessor is a COND_EXPR.  */
     274              : 
     275              : static gcond *
     276         4342 : single_pred_cond_non_loop_exit (basic_block bb)
     277              : {
     278         4342 :   if (single_pred_p (bb))
     279              :     {
     280         3112 :       basic_block pred = single_pred (bb);
     281              : 
     282         8508 :       if (loop_depth (pred->loop_father) > loop_depth (bb->loop_father))
     283              :         return NULL;
     284              : 
     285         5976 :       return safe_dyn_cast <gcond *> (*gsi_last_bb (pred));
     286              :     }
     287              : 
     288              :   return NULL;
     289              : }
     290              : 
     291              : namespace
     292              : {
     293              : 
     294              : /* Build the maximal scop containing LOOPs and add it to SCOPS.  */
     295              : 
     296              : class scop_detection
     297              : {
     298              : public:
     299          556 :   scop_detection () : scops (vNULL) {}
     300              : 
     301          556 :   ~scop_detection ()
     302              :   {
     303          556 :     scops.release ();
     304          556 :   }
     305              : 
     306              :   /* A marker for invalid sese_l.  */
     307              :   static sese_l invalid_sese;
     308              : 
     309              :   /* Return the SCOPS in this SCOP_DETECTION.  */
     310              : 
     311              :   vec<sese_l>
     312          556 :   get_scops ()
     313              :   {
     314          556 :     return scops;
     315              :   }
     316              : 
     317              :   /* Return an sese_l around the LOOP.  */
     318              : 
     319              :   sese_l get_sese (loop_p loop);
     320              : 
     321              :   /* Merge scops at same loop depth and returns the new sese.
     322              :      Returns a new SESE when merge was successful, INVALID_SESE otherwise.  */
     323              : 
     324              :   sese_l merge_sese (sese_l first, sese_l second) const;
     325              : 
     326              :   /* Build scop outer->inner if possible.  */
     327              : 
     328              :   void build_scop_depth (loop_p loop);
     329              : 
     330              :   /* Return true when BEGIN is the preheader edge of a loop with a single exit
     331              :      END.  */
     332              : 
     333              :   static bool region_has_one_loop (sese_l s);
     334              : 
     335              :   /* Add to SCOPS a scop starting at SCOP_BEGIN and ending at SCOP_END.  */
     336              : 
     337              :   void add_scop (sese_l s);
     338              : 
     339              :   /* Returns true if S1 subsumes/surrounds S2.  */
     340              :   static bool subsumes (sese_l s1, sese_l s2);
     341              : 
     342              :   /* Remove a SCoP which is subsumed by S1.  */
     343              :   void remove_subscops (sese_l s1);
     344              : 
     345              :   /* Returns true if S1 intersects with S2.  Since we already know that S1 does
     346              :      not subsume S2 or vice-versa, we only check for entry bbs.  */
     347              : 
     348              :   static bool intersects (sese_l s1, sese_l s2);
     349              : 
     350              :   /* Remove one of the scops when it intersects with any other.  */
     351              : 
     352              :   void remove_intersecting_scops (sese_l s1);
     353              : 
     354              :   /* Return true when a statement in SCOP cannot be represented by Graphite.  */
     355              : 
     356              :   bool harmful_loop_in_region (sese_l scop) const;
     357              : 
     358              :   /* Return true only when STMT is simple enough for being handled by Graphite.
     359              :      This depends on SCOP, as the parameters are initialized relatively to
     360              :      this basic block, the linear functions are initialized based on the
     361              :      outermost loop containing STMT inside the SCOP.  BB is the place where we
     362              :      try to evaluate the STMT.  */
     363              : 
     364              :   bool stmt_simple_for_scop_p (sese_l scop, gimple *stmt,
     365              :                                basic_block bb) const;
     366              : 
     367              :   /* Something like "n * m" is not allowed.  */
     368              : 
     369              :   static bool graphite_can_represent_init (tree e);
     370              : 
     371              :   /* Return true when SCEV can be represented in the polyhedral model.
     372              : 
     373              :      An expression can be represented, if it can be expressed as an
     374              :      affine expression.  For loops (i, j) and parameters (m, n) all
     375              :      affine expressions are of the form:
     376              : 
     377              :      x1 * i + x2 * j + x3 * m + x4 * n + x5 * 1 where x1..x5 element of Z
     378              : 
     379              :      1 i + 20 j + (-2) m + 25
     380              : 
     381              :      Something like "i * n" or "n * m" is not allowed.  */
     382              : 
     383              :   static bool graphite_can_represent_scev (sese_l scop, tree scev);
     384              : 
     385              :   /* Return true when EXPR can be represented in the polyhedral model.
     386              : 
     387              :      This means an expression can be represented, if it is linear with respect
     388              :      to the loops and the strides are non parametric.  LOOP is the place where
     389              :      the expr will be evaluated.  SCOP defines the region we analyse.  */
     390              : 
     391              :   static bool graphite_can_represent_expr (sese_l scop, loop_p loop,
     392              :                                            tree expr);
     393              : 
     394              :   /* Return true if the data references of STMT can be represented by Graphite.
     395              :      We try to analyze the data references in a loop contained in the SCOP.  */
     396              : 
     397              :   static bool stmt_has_simple_data_refs_p (sese_l scop, gimple *stmt);
     398              : 
     399              :   /* Remove the close phi node at GSI and replace its rhs with the rhs
     400              :      of PHI.  */
     401              : 
     402              :   static void remove_duplicate_close_phi (gphi *phi, gphi_iterator *gsi);
     403              : 
     404              :   /* Returns true when Graphite can represent LOOP in SCOP.
     405              :      FIXME: For the moment, graphite cannot be used on loops that iterate using
     406              :      induction variables that wrap.  */
     407              : 
     408              :   static bool can_represent_loop (loop_p loop, sese_l scop);
     409              : 
     410              :   /* Returns the number of pbbs that are in loops contained in SCOP.  */
     411              : 
     412              :   static int nb_pbbs_in_loops (scop_p scop);
     413              : 
     414              : private:
     415              :   vec<sese_l> scops;
     416              : };
     417              : 
     418              : sese_l scop_detection::invalid_sese (NULL, NULL);
     419              : 
     420              : /* Return an sese_l around the LOOP.  */
     421              : 
     422              : sese_l
     423         1104 : scop_detection::get_sese (loop_p loop)
     424              : {
     425         1104 :   if (!loop)
     426            0 :     return invalid_sese;
     427              : 
     428         1104 :   edge scop_begin = loop_preheader_edge (loop);
     429         1104 :   edge scop_end = single_exit (loop);
     430         1104 :   if (!scop_end || (scop_end->flags & (EDGE_COMPLEX|EDGE_FAKE)))
     431          214 :     return invalid_sese;
     432              : 
     433          890 :   return sese_l (scop_begin, scop_end);
     434              : }
     435              : 
     436              : /* Merge scops at same loop depth and returns the new sese.
     437              :    Returns a new SESE when merge was successful, INVALID_SESE otherwise.  */
     438              : 
     439              : sese_l
     440          139 : scop_detection::merge_sese (sese_l first, sese_l second) const
     441              : {
     442              :   /* In the trivial case first/second may be NULL.  */
     443          139 :   if (!first)
     444            0 :     return second;
     445          139 :   if (!second)
     446            0 :     return first;
     447              : 
     448          139 :   DEBUG_PRINT (dp << "[scop-detection] try merging sese s1: ";
     449              :                print_sese (dump_file, first);
     450              :                dp << "[scop-detection] try merging sese s2: ";
     451              :                print_sese (dump_file, second));
     452              : 
     453          139 :   auto_bitmap worklist, in_sese_region;
     454          139 :   bitmap_set_bit (worklist, get_entry_bb (first)->index);
     455          139 :   bitmap_set_bit (worklist, get_exit_bb (first)->index);
     456          139 :   bitmap_set_bit (worklist, get_entry_bb (second)->index);
     457          139 :   bitmap_set_bit (worklist, get_exit_bb (second)->index);
     458          139 :   edge entry = NULL, exit = NULL;
     459              : 
     460              :   /* We can optimize the case of adding a loop entry dest or exit
     461              :      src to the worklist (for single-exit loops) by skipping
     462              :      directly to the exit dest / entry src.  in_sese_region
     463              :      doesn't have to cover all blocks in the region but merely
     464              :      its border it acts more like a visited bitmap.  */
     465         1733 :   do
     466              :     {
     467         1733 :       int index = bitmap_clear_first_set_bit (worklist);
     468         1733 :       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, index);
     469         1733 :       edge_iterator ei;
     470         1733 :       edge e;
     471              : 
     472              :       /* With fake exit edges we can end up with no possible exit.  */
     473         1733 :       if (index == EXIT_BLOCK)
     474              :         {
     475            2 :           DEBUG_PRINT (dp << "[scop-detection-fail] cannot merge seses.\n");
     476            2 :           return invalid_sese;
     477              :         }
     478              : 
     479         1731 :       bitmap_set_bit (in_sese_region, bb->index);
     480              : 
     481         1731 :       basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb);
     482         4004 :       FOR_EACH_EDGE (e, ei, bb->preds)
     483         2273 :         if (e->src == dom
     484         2273 :             && (! entry
     485         1544 :                 || dominated_by_p (CDI_DOMINATORS, entry->dest, bb)))
     486              :           {
     487          177 :             if (entry
     488          177 :                 && ! bitmap_bit_p (in_sese_region, entry->src->index))
     489           29 :               bitmap_set_bit (worklist, entry->src->index);
     490              :             entry = e;
     491              :           }
     492         2096 :         else if (! bitmap_bit_p (in_sese_region, e->src->index))
     493          897 :           bitmap_set_bit (worklist, e->src->index);
     494              : 
     495         1731 :       basic_block pdom = get_immediate_dominator (CDI_POST_DOMINATORS, bb);
     496         4004 :       FOR_EACH_EDGE (e, ei, bb->succs)
     497         2273 :         if (e->dest == pdom
     498         2273 :             && (! exit
     499         1531 :                 || dominated_by_p (CDI_POST_DOMINATORS, exit->src, bb)))
     500              :           {
     501          332 :             if (exit
     502          332 :                 && ! bitmap_bit_p (in_sese_region, exit->dest->index))
     503          171 :               bitmap_set_bit (worklist, exit->dest->index);
     504              :             exit = e;
     505              :           }
     506         1941 :         else if (! bitmap_bit_p (in_sese_region, e->dest->index))
     507         1019 :           bitmap_set_bit (worklist, e->dest->index);
     508              :     }
     509         1731 :   while (! bitmap_empty_p (worklist));
     510              : 
     511          137 :   sese_l combined (entry, exit);
     512              : 
     513          137 :   DEBUG_PRINT (dp << "[merged-sese] s1: "; print_sese (dump_file, combined));
     514              : 
     515          137 :   return combined;
     516          139 : }
     517              : 
     518              : /* Print the loop numbers of the loops contained in SESE to FILE. */
     519              : 
     520              : static void
     521          178 : print_sese_loop_numbers (FILE *file, sese_l sese)
     522              : {
     523          178 :   bool first_loop = true;
     524          397 :   for (loop_p nest = sese.entry->dest->loop_father; nest; nest = nest->next)
     525              :     {
     526          248 :       if (!loop_in_sese_p (nest, sese))
     527              :         break;
     528              : 
     529         1084 :       for (auto loop : loops_list (cfun, LI_INCLUDE_ROOT, nest))
     530              :         {
     531          427 :           gcc_assert (loop_in_sese_p (loop, sese));
     532              : 
     533          677 :           fprintf (file, "%s%d", first_loop ? "" : ", ", loop->num);
     534          427 :           first_loop = false;
     535          219 :         }
     536              :     }
     537          178 : }
     538              : 
     539              : /* Build scop outer->inner if possible.  */
     540              : 
     541              : void
     542         1183 : scop_detection::build_scop_depth (loop_p loop)
     543              : {
     544         1183 :   sese_l s = invalid_sese;
     545         1183 :   loop = loop->inner;
     546         2287 :   while (loop)
     547              :     {
     548         1104 :       sese_l next = get_sese (loop);
     549         1104 :       if (! next
     550          890 :           || harmful_loop_in_region (next))
     551              :         {
     552          627 :           if (next)
     553          413 :             DEBUG_PRINT (dp << "[scop-detection] Discarding SCoP on loops ";
     554              :                          print_sese_loop_numbers (dump_file, next);
     555              :                          dp << " because of harmful loops\n");
     556          627 :           if (s)
     557           56 :             add_scop (s);
     558          627 :           build_scop_depth (loop);
     559          627 :           s = invalid_sese;
     560              :         }
     561          477 :       else if (! s)
     562              :         s = next;
     563              :       else
     564              :         {
     565          139 :           sese_l combined = merge_sese (s, next);
     566          139 :           if (! combined
     567          137 :               || harmful_loop_in_region (combined))
     568              :             {
     569           59 :               add_scop (s);
     570           59 :               s = next;
     571              :             }
     572              :           else
     573              :             s = combined;
     574              :         }
     575         1104 :       loop = loop->next;
     576              :     }
     577         1183 :   if (s)
     578          282 :     add_scop (s);
     579         1183 : }
     580              : 
     581              : /* Returns true when Graphite can represent LOOP in SCOP.
     582              :    FIXME: For the moment, graphite cannot be used on loops that iterate using
     583              :    induction variables that wrap.  */
     584              : 
     585              : bool
     586         1119 : scop_detection::can_represent_loop (loop_p loop, sese_l scop)
     587              : {
     588         1119 :   tree niter;
     589         1119 :   struct tree_niter_desc niter_desc;
     590              : 
     591              :   /* We can only handle do {} while () style loops correctly.  */
     592         1119 :   edge exit = single_exit (loop);
     593         1119 :   if (!exit
     594         1118 :       || !single_pred_p (loop->latch)
     595         1118 :       || exit->src != single_pred (loop->latch)
     596         2232 :       || !empty_block_p (loop->latch))
     597              :     {
     598           23 :       DEBUG_PRINT (dp << "[can_represent_loop-fail] Loop shape unsupported.\n");
     599           23 :       return false;
     600              :     }
     601              : 
     602         1096 :   bool edge_irreducible = (loop_preheader_edge (loop)->flags
     603         1096 :                            & EDGE_IRREDUCIBLE_LOOP);
     604         1096 :   if (edge_irreducible)
     605              :     {
     606            1 :       DEBUG_PRINT (dp << "[can_represent_loop-fail] "
     607              :                          "Loop is not a natural loop.\n");
     608            1 :       return false;
     609              :     }
     610              : 
     611         1095 :   bool niter_is_unconditional = number_of_iterations_exit (loop,
     612              :                                                            single_exit (loop),
     613              :                                                            &niter_desc, false);
     614              : 
     615         1095 :   if (!niter_is_unconditional)
     616              :     {
     617            5 :       DEBUG_PRINT (dp << "[can_represent_loop-fail] "
     618              :                          "Loop niter not unconditional.\n"
     619              :                          "Condition: " << niter_desc.assumptions << "\n");
     620            5 :       return false;
     621              :     }
     622              : 
     623         1090 :   niter = number_of_latch_executions (loop);
     624         1090 :   if (!niter)
     625              :     {
     626            0 :       DEBUG_PRINT (dp << "[can_represent_loop-fail] Loop niter unknown.\n");
     627            0 :       return false;
     628              :     }
     629         1090 :   if (!niter_desc.control.no_overflow)
     630              :     {
     631            1 :       DEBUG_PRINT (dp << "[can_represent_loop-fail] Loop niter can overflow.\n");
     632            1 :       return false;
     633              :     }
     634              : 
     635         1089 :   bool undetermined_coefficients = chrec_contains_undetermined (niter);
     636         1089 :   if (undetermined_coefficients)
     637              :     {
     638            0 :       DEBUG_PRINT (dp << "[can_represent_loop-fail] "
     639              :                          "Loop niter chrec contains undetermined "
     640              :                          "coefficients.\n");
     641            0 :       return false;
     642              :     }
     643              : 
     644         1089 :   bool can_represent_expr = graphite_can_represent_expr (scop, loop, niter);
     645         1089 :   if (!can_represent_expr)
     646              :     {
     647            9 :       DEBUG_PRINT (dp << "[can_represent_loop-fail] "
     648              :                       << "Loop niter expression cannot be represented: "
     649              :                       << niter << "\n");
     650            9 :       return false;
     651              :     }
     652              : 
     653              :   return true;
     654         1119 : }
     655              : 
     656              : /* Return true when BEGIN is the preheader edge of a loop with a single exit
     657              :    END.  */
     658              : 
     659              : bool
     660          397 : scop_detection::region_has_one_loop (sese_l s)
     661              : {
     662          397 :   edge begin = s.entry;
     663          397 :   edge end = s.exit;
     664              :   /* Check for a single perfectly nested loop.  */
     665          397 :   if (begin->dest->loop_father->inner)
     666              :     return false;
     667              : 
     668              :   /* Otherwise, check whether we have adjacent loops.  */
     669          228 :   return (single_pred_p (end->src)
     670          228 :           && begin->dest->loop_father == single_pred (end->src)->loop_father);
     671              : }
     672              : 
     673              : /* Add to SCOPS a scop starting at SCOP_BEGIN and ending at SCOP_END.  */
     674              : 
     675              : void
     676          397 : scop_detection::add_scop (sese_l s)
     677              : {
     678          397 :   gcc_assert (s);
     679              : 
     680              :   /* If the exit edge is fake discard the SCoP for now as we're removing the
     681              :      fake edges again after analysis.  */
     682          397 :   if (s.exit->flags & EDGE_FAKE)
     683              :     {
     684            0 :       DEBUG_PRINT (dp << "[scop-detection-fail] Discarding infinite loop SCoP: ";
     685              :                    print_sese (dump_file, s));
     686            0 :       return;
     687              :     }
     688              : 
     689              :   /* Include the BB with the loop-closed SSA PHI nodes, we need this
     690              :      block in the region for code-generating out-of-SSA copies.
     691              :      canonicalize_loop_closed_ssa makes sure that is in proper shape.  */
     692          397 :   if (s.exit->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
     693          397 :       && loop_exit_edge_p (s.exit->src->loop_father, s.exit))
     694              :     {
     695          396 :       gcc_assert (single_pred_p (s.exit->dest)
     696              :                   && single_succ_p (s.exit->dest)
     697              :                   && sese_trivially_empty_bb_p (s.exit->dest));
     698          396 :       s.exit = single_succ_edge (s.exit->dest);
     699              :     }
     700              : 
     701              :   /* Do not add scops with only one loop.  */
     702          397 :   if (region_has_one_loop (s))
     703              :     {
     704          186 :       DEBUG_PRINT (dp << "[scop-detection-fail] Discarding one loop SCoP: ";
     705              :                    print_sese (dump_file, s));
     706          186 :       return;
     707              :     }
     708              : 
     709          211 :   if (get_exit_bb (s) == EXIT_BLOCK_PTR_FOR_FN (cfun))
     710              :     {
     711            0 :       DEBUG_PRINT (dp << "[scop-detection-fail] "
     712              :                       << "Discarding SCoP exiting to return: ";
     713              :                    print_sese (dump_file, s));
     714            0 :       return;
     715              :     }
     716              : 
     717              :   /* Remove all the scops which are subsumed by s.  */
     718          211 :   remove_subscops (s);
     719              : 
     720              :   /* Remove intersecting scops. FIXME: It will be a good idea to keep
     721              :      the non-intersecting part of the scop already in the list.  */
     722          211 :   remove_intersecting_scops (s);
     723              : 
     724          211 :   scops.safe_push (s);
     725          211 :   DEBUG_PRINT (dp << "[scop-detection] Adding SCoP: "; print_sese (dump_file, s));
     726              : 
     727          211 :   if (dump_file && dump_flags & TDF_DETAILS)
     728              :     {
     729          102 :       fprintf (dump_file, "Loops in SCoP: ");
     730          102 :       print_sese_loop_numbers (dump_file, s);
     731          102 :       fprintf (dump_file, "\n");
     732              :     }
     733              : }
     734              : 
     735              : /* Return true when a statement in SCOP cannot be represented by Graphite.  */
     736              : 
     737              : bool
     738         1027 : scop_detection::harmful_loop_in_region (sese_l scop) const
     739              : {
     740         1027 :   basic_block exit_bb = get_exit_bb (scop);
     741         1027 :   basic_block entry_bb = get_entry_bb (scop);
     742              : 
     743         1027 :   DEBUG_PRINT (dp << "[checking-harmful-bbs] ";
     744              :                print_sese (dump_file, scop));
     745         1027 :   gcc_assert (dominated_by_p (CDI_DOMINATORS, exit_bb, entry_bb));
     746              : 
     747         1027 :   auto_vec<basic_block> worklist;
     748         1027 :   auto_bitmap loops;
     749              : 
     750         1027 :   worklist.safe_push (entry_bb);
     751         6059 :   while (! worklist.is_empty ())
     752              :     {
     753         4353 :       basic_block bb = worklist.pop ();
     754         4353 :       DEBUG_PRINT (dp << "Visiting bb_" << bb->index << "\n");
     755              : 
     756              :       /* The basic block should not be part of an irreducible loop.  */
     757         4353 :       if (bb->flags & BB_IRREDUCIBLE_LOOP)
     758              :         {
     759            2 :           DEBUG_PRINT (dp << "[scop-detection-fail] Found bb in irreducible "
     760              :                              "loop.\n");
     761              : 
     762            2 :           return true;
     763              :         }
     764              : 
     765              :       /* Check for unstructured control flow: CFG not generated by structured
     766              :          if-then-else.  */
     767         4351 :       if (bb->succs->length () > 1)
     768              :         {
     769         1745 :           edge e;
     770         1745 :           edge_iterator ei;
     771         5252 :           FOR_EACH_EDGE (e, ei, bb->succs)
     772         3510 :             if (!dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest)
     773         3510 :                 && !dominated_by_p (CDI_DOMINATORS, e->dest, bb))
     774              :               {
     775            3 :                 DEBUG_PRINT (dp << "[scop-detection-fail] Found unstructured "
     776              :                                    "control flow.\n");
     777            3 :                 return true;
     778              :               }
     779              :         }
     780              : 
     781              :       /* Collect all loops in the current region.  */
     782         4348 :       loop_p loop = bb->loop_father;
     783         4348 :       if (loop_in_sese_p (loop, scop))
     784         3983 :         bitmap_set_bit (loops, loop->num);
     785              : 
     786              :       /* Check for harmful statements in basic blocks part of the region.  */
     787         8696 :       for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
     788        14763 :            !gsi_end_p (gsi); gsi_next (&gsi))
     789        10758 :         if (!stmt_simple_for_scop_p (scop, gsi_stmt (gsi), bb))
     790              :           {
     791          343 :             DEBUG_PRINT (dp << "[scop-detection-fail] "
     792              :                                "Found harmful statement.\n");
     793          343 :             return true;
     794              :           }
     795              : 
     796         4005 :       for (basic_block dom = first_dom_son (CDI_DOMINATORS, bb);
     797         8201 :            dom;
     798         4196 :            dom = next_dom_son (CDI_DOMINATORS, dom))
     799         4196 :         if (dom != scop.exit->dest)
     800         3493 :           worklist.safe_push (dom);
     801              :     }
     802              : 
     803              :   /* Go through all loops and check that they are still valid in the combined
     804              :      scop.  */
     805          679 :   unsigned j;
     806          679 :   bitmap_iterator bi;
     807         1689 :   EXECUTE_IF_SET_IN_BITMAP (loops, 0, j, bi)
     808              :     {
     809         1132 :       loop_p loop = (*current_loops->larray)[j];
     810         1132 :       gcc_assert (loop->num == (int) j);
     811              : 
     812              :       /* Check if the loop nests are to be optimized for speed.  */
     813         1132 :       if (! loop->inner
     814         1132 :           && ! optimize_loop_for_speed_p (loop))
     815              :         {
     816           13 :           DEBUG_PRINT (dp << "[scop-detection-fail] loop_"
     817              :                        << loop->num << " is not on a hot path.\n");
     818           13 :           return true;
     819              :         }
     820              : 
     821         1119 :       if (! can_represent_loop (loop, scop))
     822              :         {
     823           39 :           DEBUG_PRINT (dp << "[scop-detection-fail] cannot represent loop_"
     824              :                        << loop->num << "\n");
     825           39 :           return true;
     826              :         }
     827              : 
     828              :       /* Check if all loop nests have at least one data reference.
     829              :          ???  This check is expensive and loops premature at this point.
     830              :          If important to retain we can pre-compute this for all innermost
     831              :          loops and reject those when we build a SESE region for a loop
     832              :          during SESE discovery.  */
     833         1080 :       if (! loop->inner
     834         1080 :           && ! loop_nest_has_data_refs (loop))
     835              :         {
     836           70 :           DEBUG_PRINT (dp << "[scop-detection-fail] loop_" << loop->num
     837              :                        << " does not have any data reference.\n");
     838           70 :           return true;
     839              :         }
     840         1491 :       DEBUG_PRINT (dp << "[scop-detection] loop_" << loop->num << " is harmless.\n");
     841              :     }
     842              : 
     843              :   return false;
     844         1027 : }
     845              : 
     846              : /* Returns true if S1 subsumes/surrounds S2.  */
     847              : bool
     848           18 : scop_detection::subsumes (sese_l s1, sese_l s2)
     849              : {
     850           18 :   if (dominated_by_p (CDI_DOMINATORS, get_entry_bb (s2),
     851           18 :                       get_entry_bb (s1))
     852           18 :       && dominated_by_p (CDI_POST_DOMINATORS, s2.exit->dest,
     853            0 :                          s1.exit->dest))
     854              :     return true;
     855              :   return false;
     856              : }
     857              : 
     858              : /* Remove a SCoP which is subsumed by S1.  */
     859              : void
     860          211 : scop_detection::remove_subscops (sese_l s1)
     861              : {
     862          211 :   int j;
     863          211 :   sese_l *s2;
     864          244 :   FOR_EACH_VEC_ELT_REVERSE (scops, j, s2)
     865              :     {
     866           18 :       if (subsumes (s1, *s2))
     867              :         {
     868            0 :           DEBUG_PRINT (dp << "Removing sub-SCoP";
     869              :                        print_sese (dump_file, *s2));
     870            0 :           scops.unordered_remove (j);
     871              :         }
     872              :     }
     873          211 : }
     874              : 
     875              : /* Returns true if S1 intersects with S2.  Since we already know that S1 does
     876              :    not subsume S2 or vice-versa, we only check for entry bbs.  */
     877              : 
     878              : bool
     879           18 : scop_detection::intersects (sese_l s1, sese_l s2)
     880              : {
     881           18 :   if (dominated_by_p (CDI_DOMINATORS, get_entry_bb (s2),
     882           18 :                       get_entry_bb (s1))
     883           18 :       && !dominated_by_p (CDI_DOMINATORS, get_entry_bb (s2),
     884            0 :                           get_exit_bb (s1)))
     885              :     return true;
     886           18 :   if ((s1.exit == s2.entry) || (s2.exit == s1.entry))
     887              :     return true;
     888              : 
     889              :   return false;
     890              : }
     891              : 
     892              : /* Remove one of the scops when it intersects with any other.  */
     893              : 
     894              : void
     895          211 : scop_detection::remove_intersecting_scops (sese_l s1)
     896              : {
     897          211 :   int j;
     898          211 :   sese_l *s2;
     899          244 :   FOR_EACH_VEC_ELT_REVERSE (scops, j, s2)
     900              :     {
     901           18 :       if (intersects (s1, *s2))
     902              :         {
     903            0 :           DEBUG_PRINT (dp << "Removing intersecting SCoP";
     904              :                        print_sese (dump_file, *s2);
     905              :                        dp << "Intersects with:";
     906              :                        print_sese (dump_file, s1));
     907            0 :           scops.unordered_remove (j);
     908              :         }
     909              :     }
     910          211 : }
     911              : 
     912              : /* Something like "n * m" is not allowed.  */
     913              : 
     914              : bool
     915        13124 : scop_detection::graphite_can_represent_init (tree e)
     916              : {
     917        13326 :   switch (TREE_CODE (e))
     918              :     {
     919         4261 :     case POLYNOMIAL_CHREC:
     920         4261 :       return graphite_can_represent_init (CHREC_LEFT (e))
     921         8505 :         && graphite_can_represent_init (CHREC_RIGHT (e));
     922              : 
     923           43 :     case MULT_EXPR:
     924           43 :       if (chrec_contains_symbols (TREE_OPERAND (e, 0)))
     925           43 :         return graphite_can_represent_init (TREE_OPERAND (e, 0))
     926           43 :           && tree_fits_shwi_p (TREE_OPERAND (e, 1));
     927              :       else
     928            0 :         return graphite_can_represent_init (TREE_OPERAND (e, 1))
     929            0 :           && tree_fits_shwi_p (TREE_OPERAND (e, 0));
     930              : 
     931          402 :     case PLUS_EXPR:
     932          402 :     case POINTER_PLUS_EXPR:
     933          402 :     case MINUS_EXPR:
     934          402 :       return graphite_can_represent_init (TREE_OPERAND (e, 0))
     935          402 :         && graphite_can_represent_init (TREE_OPERAND (e, 1));
     936              : 
     937          202 :     case NEGATE_EXPR:
     938          202 :     case BIT_NOT_EXPR:
     939          202 :     CASE_CONVERT:
     940          202 :     case NON_LVALUE_EXPR:
     941          202 :       return graphite_can_represent_init (TREE_OPERAND (e, 0));
     942              : 
     943              :     default:
     944              :       break;
     945              :     }
     946              : 
     947              :   return true;
     948              : }
     949              : 
     950              : /* Return true when SCEV can be represented in the polyhedral model.
     951              : 
     952              :    An expression can be represented, if it can be expressed as an
     953              :    affine expression.  For loops (i, j) and parameters (m, n) all
     954              :    affine expressions are of the form:
     955              : 
     956              :    x1 * i + x2 * j + x3 * m + x4 * n + x5 * 1 where x1..x5 element of Z
     957              : 
     958              :    1 i + 20 j + (-2) m + 25
     959              : 
     960              :    Something like "i * n" or "n * m" is not allowed.  */
     961              : 
     962              : bool
     963         8007 : scop_detection::graphite_can_represent_scev (sese_l scop, tree scev)
     964              : {
     965        12256 :   if (chrec_contains_undetermined (scev))
     966              :     return false;
     967              : 
     968        12103 :   switch (TREE_CODE (scev))
     969              :     {
     970          483 :     case NEGATE_EXPR:
     971          483 :     case BIT_NOT_EXPR:
     972          483 :     CASE_CONVERT:
     973          483 :     case NON_LVALUE_EXPR:
     974          483 :       return graphite_can_represent_scev (scop, TREE_OPERAND (scev, 0));
     975              : 
     976          592 :     case PLUS_EXPR:
     977          592 :     case POINTER_PLUS_EXPR:
     978          592 :     case MINUS_EXPR:
     979          592 :       return graphite_can_represent_scev (scop, TREE_OPERAND (scev, 0))
     980          592 :         && graphite_can_represent_scev (scop, TREE_OPERAND (scev, 1));
     981              : 
     982           27 :     case MULT_EXPR:
     983           43 :       return !CONVERT_EXPR_P (TREE_OPERAND (scev, 0))
     984           16 :         && !CONVERT_EXPR_P (TREE_OPERAND (scev, 1))
     985           32 :         && !(chrec_contains_symbols (TREE_OPERAND (scev, 0))
     986           16 :              && chrec_contains_symbols (TREE_OPERAND (scev, 1)))
     987           16 :         && graphite_can_represent_init (scev)
     988           16 :         && graphite_can_represent_scev (scop, TREE_OPERAND (scev, 0))
     989           43 :         && graphite_can_represent_scev (scop, TREE_OPERAND (scev, 1));
     990              : 
     991         3846 :     case POLYNOMIAL_CHREC:
     992              :       /* Check for constant strides.  With a non constant stride of
     993              :          'n' we would have a value of 'iv * n'.  Also check that the
     994              :          initial value can represented: for example 'n * m' cannot be
     995              :          represented.  */
     996         3846 :       gcc_assert (loop_in_sese_p (get_loop (cfun,
     997              :                                             CHREC_VARIABLE (scev)), scop));
     998         3846 :       if (!evolution_function_right_is_integer_cst (scev)
     999         3846 :           || !graphite_can_represent_init (scev))
    1000           80 :         return false;
    1001         3766 :       return graphite_can_represent_scev (scop, CHREC_LEFT (scev));
    1002              : 
    1003              :     case ADDR_EXPR:
    1004              :       /* We cannot encode addresses for ISL.  */
    1005              :       return false;
    1006              : 
    1007         7155 :     default:
    1008         7155 :       break;
    1009              :     }
    1010              : 
    1011              :   /* Only affine functions can be represented.  */
    1012         7155 :   if (tree_contains_chrecs (scev, NULL) || !scev_is_linear_expression (scev))
    1013            3 :     return false;
    1014              : 
    1015              :   return true;
    1016              : }
    1017              : 
    1018              : /* Return true when EXPR can be represented in the polyhedral model.
    1019              : 
    1020              :    This means an expression can be represented, if it is linear with respect to
    1021              :    the loops and the strides are non parametric.  LOOP is the place where the
    1022              :    expr will be evaluated.  SCOP defines the region we analyse.  */
    1023              : 
    1024              : bool
    1025         4129 : scop_detection::graphite_can_represent_expr (sese_l scop, loop_p loop,
    1026              :                                              tree expr)
    1027              : {
    1028         4129 :   tree scev = cached_scalar_evolution_in_region (scop, loop, expr);
    1029         4129 :   bool can_represent = graphite_can_represent_scev (scop, scev);
    1030              : 
    1031         4129 :   if (!can_represent)
    1032              :     {
    1033          134 :       if (dump_file)
    1034              :         {
    1035           19 :           fprintf (dump_file,
    1036              :                    "[graphite_can_represent_expr] Cannot represent scev \"");
    1037           19 :           print_generic_expr (dump_file, scev, TDF_SLIM);
    1038           19 :           fprintf (dump_file, "\" of expression ");
    1039           19 :           print_generic_expr (dump_file, expr, TDF_SLIM);
    1040           19 :           fprintf (dump_file, " in loop %d\n", loop->num);
    1041              :         }
    1042              :     }
    1043         4129 :   return can_represent;
    1044              : }
    1045              : 
    1046              : /* Return true if the data references of STMT can be represented by Graphite.
    1047              :    We try to analyze the data references in a loop contained in the SCOP.  */
    1048              : 
    1049              : bool
    1050        10536 : scop_detection::stmt_has_simple_data_refs_p (sese_l scop, gimple *stmt)
    1051              : {
    1052        10536 :   edge nest = scop.entry;
    1053        10536 :   loop_p loop = loop_containing_stmt (stmt);
    1054        10536 :   if (!loop_in_sese_p (loop, scop))
    1055          173 :     loop = NULL;
    1056              : 
    1057        10536 :   auto_vec<data_reference_p> drs;
    1058        10536 :   if (! graphite_find_data_references_in_stmt (nest, loop, stmt, &drs))
    1059              :     {
    1060            4 :       DEBUG_PRINT (dp << "[stmt_has_simple_data_refs_p] "
    1061              :                          "Unanalyzable statement.\n");
    1062            4 :       return false;
    1063              :     }
    1064              : 
    1065              :   int j;
    1066              :   data_reference_p dr;
    1067        16779 :   FOR_EACH_VEC_ELT (drs, j, dr)
    1068              :     {
    1069         4683 :       for (unsigned i = 0; i < DR_NUM_DIMENSIONS (dr); ++i)
    1070         2676 :         if (! graphite_can_represent_scev (scop, DR_ACCESS_FN (dr, i)))
    1071              :           {
    1072          113 :             DEBUG_PRINT (dp << "[stmt_has_simple_data_refs_p] "
    1073              :                                "Cannot represent access function SCEV: "
    1074              :                             << DR_ACCESS_FN (dr, i) << "\n");
    1075          113 :             return false;
    1076              :           }
    1077              :     }
    1078              : 
    1079              :   return true;
    1080        10536 : }
    1081              : 
    1082              : /* GIMPLE_ASM and GIMPLE_CALL may embed arbitrary side effects.
    1083              :    Calls have side-effects, except those to const or pure
    1084              :    functions.  */
    1085              : 
    1086              : static bool
    1087        10622 : stmt_has_side_effects (gimple *stmt)
    1088              : {
    1089        10622 :   if (gimple_has_volatile_ops (stmt)
    1090        10607 :       || (gimple_code (stmt) == GIMPLE_CALL
    1091          107 :           && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
    1092        19561 :       || (gimple_code (stmt) == GIMPLE_ASM))
    1093              :     {
    1094           86 :       DEBUG_PRINT (dp << "[scop-detection-fail] "
    1095              :                       << "Statement has side-effects:\n";
    1096              :         print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS | TDF_MEMSYMS));
    1097           86 :       return true;
    1098              :     }
    1099              :   return false;
    1100              : }
    1101              : 
    1102              : /* Return true only when STMT is simple enough for being handled by Graphite.
    1103              :    This depends on SCOP, as the parameters are initialized relatively to
    1104              :    this basic block, the linear functions are initialized based on the outermost
    1105              :    loop containing STMT inside the SCOP.  BB is the place where we try to
    1106              :    evaluate the STMT.  */
    1107              : 
    1108              : bool
    1109        10758 : scop_detection::stmt_simple_for_scop_p (sese_l scop, gimple *stmt,
    1110              :                                         basic_block bb) const
    1111              : {
    1112        10758 :   gcc_assert (scop);
    1113              : 
    1114        10758 :   if (is_gimple_debug (stmt))
    1115              :     return true;
    1116              : 
    1117        10622 :   if (stmt_has_side_effects (stmt))
    1118              :     return false;
    1119              : 
    1120        10536 :   if (!stmt_has_simple_data_refs_p (scop, stmt))
    1121              :     {
    1122          117 :       DEBUG_PRINT (dp << "[scop-detection-fail] "
    1123              :                       << "Graphite cannot handle data-refs in stmt:\n";
    1124              :         print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS););
    1125          117 :       return false;
    1126              :     }
    1127              : 
    1128        10419 :   switch (gimple_code (stmt))
    1129              :     {
    1130              :     case GIMPLE_LABEL:
    1131              :       return true;
    1132              : 
    1133         1582 :     case GIMPLE_COND:
    1134         1582 :       {
    1135              :         /* We can handle all binary comparisons.  Inequalities are
    1136              :            also supported as they can be represented with union of
    1137              :            polyhedra.  */
    1138         1582 :         enum tree_code code = gimple_cond_code (stmt);
    1139         1046 :         if (!(code == LT_EXPR
    1140         1582 :               || code == GT_EXPR
    1141         1177 :               || code == LE_EXPR
    1142         1177 :               || code == GE_EXPR
    1143              :               || code == EQ_EXPR
    1144              :               || code == NE_EXPR))
    1145              :           {
    1146            0 :             DEBUG_PRINT (dp << "[scop-detection-fail] "
    1147              :                             << "Graphite cannot handle cond stmt:\n";
    1148              :                          print_gimple_stmt (dump_file, stmt, 0,
    1149              :                                             TDF_VOPS | TDF_MEMSYMS));
    1150            0 :             return false;
    1151              :           }
    1152              : 
    1153         1582 :         loop_p loop = bb->loop_father;
    1154         4491 :         for (unsigned i = 0; i < 2; ++i)
    1155              :           {
    1156         3040 :             tree op = gimple_op (stmt, i);
    1157         3040 :             if (!graphite_can_represent_expr (scop, loop, op))
    1158              :               {
    1159          125 :                 DEBUG_PRINT (dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmt,
    1160              :                                               "[scop-detection-fail] "
    1161              :                                               "Graphite cannot represent cond "
    1162              :                                               "stmt operator expression.\n"));
    1163          125 :                 DEBUG_PRINT (dp << op << "\n");
    1164          125 :                 return false;
    1165              :               }
    1166              : 
    1167         2915 :             if (! INTEGRAL_TYPE_P (TREE_TYPE (op)))
    1168              :               {
    1169            6 :                 DEBUG_PRINT (dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmt,
    1170              :                                               "[scop-detection-fail] "
    1171              :                                               "Graphite cannot represent cond "
    1172              :                                               "statement operator. "
    1173              :                                               "Type must be integral.\n"));
    1174            6 :                 return false;
    1175              :               }
    1176              :           }
    1177              : 
    1178              :         return true;
    1179              :       }
    1180              : 
    1181         8820 :     case GIMPLE_ASSIGN:
    1182         8820 :     case GIMPLE_CALL:
    1183         8820 :       {
    1184         8820 :         tree op, lhs = gimple_get_lhs (stmt);
    1185         8820 :         ssa_op_iter i;
    1186              :         /* If we are not going to instantiate the stmt do not require
    1187              :            its operands to be instantiatable at this point.  */
    1188         8820 :         if (lhs
    1189         8820 :             && TREE_CODE (lhs) == SSA_NAME
    1190        16741 :             && scev_analyzable_p (lhs, scop))
    1191              :           return true;
    1192              :         /* Verify that if we can analyze operands at their def site we
    1193              :            also can represent them when analyzed at their uses.  */
    1194         9925 :         FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
    1195         6214 :           if (scev_analyzable_p (op, scop)
    1196         9438 :               && chrec_contains_undetermined
    1197         3224 :                    (cached_scalar_evolution_in_region (scop,
    1198         3224 :                                                        bb->loop_father, op)))
    1199              :             {
    1200            2 :               DEBUG_PRINT (dp << "[scop-detection-fail] "
    1201              :                            << "Graphite cannot code-gen stmt:\n";
    1202              :                            print_gimple_stmt (dump_file, stmt, 0,
    1203              :                                               TDF_VOPS | TDF_MEMSYMS));
    1204            2 :               return false;
    1205              :             }
    1206              :         return true;
    1207              :       }
    1208              : 
    1209            7 :     default:
    1210              :       /* These nodes cut a new scope.  */
    1211            7 :       DEBUG_PRINT (
    1212              :           dp << "[scop-detection-fail] "
    1213              :              << "Gimple stmt not handled in Graphite:\n";
    1214              :           print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS | TDF_MEMSYMS));
    1215              :       return false;
    1216              :     }
    1217              : }
    1218              : 
    1219              : /* Returns the number of pbbs that are in loops contained in SCOP.  */
    1220              : 
    1221              : int
    1222          201 : scop_detection::nb_pbbs_in_loops (scop_p scop)
    1223              : {
    1224          201 :   int i;
    1225          201 :   poly_bb_p pbb;
    1226          201 :   int res = 0;
    1227              : 
    1228          869 :   FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
    1229          668 :     if (loop_in_sese_p (gbb_loop (PBB_BLACK_BOX (pbb)), scop->scop_info->region))
    1230          568 :       res++;
    1231              : 
    1232          201 :   return res;
    1233              : }
    1234              : 
    1235              : /* Assigns the parameter NAME an index in REGION.  */
    1236              : 
    1237              : static void
    1238          318 : assign_parameter_index_in_region (tree name, sese_info_p region)
    1239              : {
    1240          318 :   gcc_assert (TREE_CODE (name) == SSA_NAME
    1241              :               && ! defined_in_sese_p (name, region->region));
    1242              :   int i;
    1243              :   tree p;
    1244          512 :   FOR_EACH_VEC_ELT (region->params, i, p)
    1245          373 :     if (p == name)
    1246          318 :       return;
    1247              : 
    1248          139 :   region->params.safe_push (name);
    1249              : }
    1250              : 
    1251              : /* In the context of sese S, scan the expression E and translate it to
    1252              :    a linear expression C.  When parsing a symbolic multiplication, K
    1253              :    represents the constant multiplier of an expression containing
    1254              :    parameters.  */
    1255              : 
    1256              : static void
    1257         1502 : scan_tree_for_params (sese_info_p s, tree e)
    1258              : {
    1259         3035 :   if (e == chrec_dont_know)
    1260              :     return;
    1261              : 
    1262         3035 :   switch (TREE_CODE (e))
    1263              :     {
    1264         1202 :     case POLYNOMIAL_CHREC:
    1265         1202 :       scan_tree_for_params (s, CHREC_LEFT (e));
    1266         1202 :       break;
    1267              : 
    1268            3 :     case MULT_EXPR:
    1269            3 :       if (chrec_contains_symbols (TREE_OPERAND (e, 0)))
    1270            3 :         scan_tree_for_params (s, TREE_OPERAND (e, 0));
    1271              :       else
    1272            0 :         scan_tree_for_params (s, TREE_OPERAND (e, 1));
    1273              :       break;
    1274              : 
    1275          170 :     case PLUS_EXPR:
    1276          170 :     case POINTER_PLUS_EXPR:
    1277          170 :     case MINUS_EXPR:
    1278          170 :       scan_tree_for_params (s, TREE_OPERAND (e, 0));
    1279          170 :       scan_tree_for_params (s, TREE_OPERAND (e, 1));
    1280          170 :       break;
    1281              : 
    1282          158 :     case NEGATE_EXPR:
    1283          158 :     case BIT_NOT_EXPR:
    1284          158 :     CASE_CONVERT:
    1285          158 :     case NON_LVALUE_EXPR:
    1286          158 :       scan_tree_for_params (s, TREE_OPERAND (e, 0));
    1287          158 :       break;
    1288              : 
    1289          318 :     case SSA_NAME:
    1290          318 :       assign_parameter_index_in_region (e, s);
    1291          318 :       break;
    1292              : 
    1293              :     case INTEGER_CST:
    1294              :     case ADDR_EXPR:
    1295              :     case REAL_CST:
    1296              :     case COMPLEX_CST:
    1297              :     case VECTOR_CST:
    1298              :       break;
    1299              : 
    1300            0 :    default:
    1301            0 :       gcc_unreachable ();
    1302         1502 :       break;
    1303              :     }
    1304              : }
    1305              : 
    1306              : /* Find parameters with respect to REGION in BB. We are looking in memory
    1307              :    access functions, conditions and loop bounds.  */
    1308              : 
    1309              : static void
    1310          668 : find_params_in_bb (sese_info_p region, gimple_poly_bb_p gbb)
    1311              : {
    1312              :   /* Find parameters in the access functions of data references.  */
    1313          668 :   int i;
    1314          668 :   data_reference_p dr;
    1315         2535 :   FOR_EACH_VEC_ELT (GBB_DATA_REFS (gbb), i, dr)
    1316         1731 :     for (unsigned j = 0; j < DR_NUM_DIMENSIONS (dr); j++)
    1317          999 :       scan_tree_for_params (region, DR_ACCESS_FN (dr, j));
    1318              : 
    1319              :   /* Find parameters in conditional statements.  */
    1320              :   gimple *stmt;
    1321          763 :   FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
    1322              :     {
    1323           95 :       loop_p loop = gimple_bb (stmt)->loop_father;
    1324           95 :       tree lhs = cached_scalar_evolution_in_region (region->region, loop,
    1325              :                                                     gimple_cond_lhs (stmt));
    1326           95 :       tree rhs = cached_scalar_evolution_in_region (region->region, loop,
    1327              :                                                     gimple_cond_rhs (stmt));
    1328           95 :       gcc_assert (!chrec_contains_undetermined (lhs)
    1329              :                   && !chrec_contains_undetermined (rhs));
    1330              : 
    1331           95 :       scan_tree_for_params (region, lhs);
    1332           95 :       scan_tree_for_params (region, rhs);
    1333              :     }
    1334          668 : }
    1335              : 
    1336              : /* Record the parameters used in the SCOP BBs.  A variable is a parameter
    1337              :    in a scop if it does not vary during the execution of that scop.  */
    1338              : 
    1339              : static void
    1340          201 : find_scop_parameters (scop_p scop)
    1341              : {
    1342          201 :   unsigned i;
    1343          201 :   sese_info_p region = scop->scop_info;
    1344              : 
    1345              :   /* Parameters used in loop bounds are processed during gather_bbs.  */
    1346              : 
    1347              :   /* Find the parameters used in data accesses.  */
    1348          201 :   poly_bb_p pbb;
    1349          869 :   FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
    1350          668 :     find_params_in_bb (region, PBB_BLACK_BOX (pbb));
    1351              : 
    1352          201 :   int nbp = sese_nb_params (region);
    1353          201 :   scop_set_nb_params (scop, nbp);
    1354          201 : }
    1355              : 
    1356              : static void
    1357          858 : add_write (vec<tree> *writes, tree def)
    1358              : {
    1359          858 :   writes->safe_push (def);
    1360          858 :   DEBUG_PRINT (dp << "Adding scalar write: ";
    1361              :                print_generic_expr (dump_file, def);
    1362              :                dp << "\nFrom stmt: ";
    1363              :                print_gimple_stmt (dump_file,
    1364              :                                   SSA_NAME_DEF_STMT (def), 0));
    1365          858 : }
    1366              : 
    1367              : static void
    1368          681 : add_read (vec<scalar_use> *reads, tree use, gimple *use_stmt)
    1369              : {
    1370          681 :   DEBUG_PRINT (dp << "Adding scalar read: ";
    1371              :                print_generic_expr (dump_file, use);
    1372              :                dp << "\nFrom stmt: ";
    1373              :                print_gimple_stmt (dump_file, use_stmt, 0));
    1374          681 :   reads->safe_push (std::make_pair (use_stmt, use));
    1375          681 : }
    1376              : 
    1377              : 
    1378              : /* Record DEF if it is used in other bbs different than DEF_BB in the SCOP.  */
    1379              : 
    1380              : static void
    1381         3181 : build_cross_bb_scalars_def (scop_p scop, tree def, basic_block def_bb,
    1382              :                              vec<tree> *writes)
    1383              : {
    1384         3181 :   if (!is_gimple_reg (def))
    1385          388 :     return;
    1386              : 
    1387         2793 :   bool scev_analyzable = scev_analyzable_p (def, scop->scop_info->region);
    1388              : 
    1389         2793 :   gimple *use_stmt;
    1390         2793 :   imm_use_iterator imm_iter;
    1391         9143 :   FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def)
    1392              :     /* Do not gather scalar variables that can be analyzed by SCEV as they can
    1393              :        be generated out of the induction variables.  */
    1394         3717 :     if ((! scev_analyzable
    1395              :          /* But gather SESE liveouts as we otherwise fail to rewrite their
    1396              :             exit PHIs.  */
    1397         2793 :          || ! bb_in_sese_p (gimple_bb (use_stmt), scop->scop_info->region))
    1398         3718 :         && (def_bb != gimple_bb (use_stmt) && !is_gimple_debug (use_stmt)))
    1399              :       {
    1400          160 :         add_write (writes, def);
    1401          160 :         break;
    1402         2793 :       }
    1403              : }
    1404              : 
    1405              : /* Record USE if it is defined in other bbs different than USE_STMT
    1406              :    in the SCOP.  */
    1407              : 
    1408              : static void
    1409         5173 : build_cross_bb_scalars_use (scop_p scop, tree use, gimple *use_stmt,
    1410              :                             vec<scalar_use> *reads)
    1411              : {
    1412         5173 :   if (!is_gimple_reg (use))
    1413              :     return;
    1414              : 
    1415              :   /* Do not gather scalar variables that can be analyzed by SCEV as they can be
    1416              :      generated out of the induction variables.  */
    1417         5173 :   if (scev_analyzable_p (use, scop->scop_info->region))
    1418              :     return;
    1419              : 
    1420          988 :   gimple *def_stmt = SSA_NAME_DEF_STMT (use);
    1421          988 :   if (gimple_bb (def_stmt) != gimple_bb (use_stmt))
    1422          120 :     add_read (reads, use, use_stmt);
    1423              : }
    1424              : 
    1425              : /* Generates a polyhedral black box only if the bb contains interesting
    1426              :    information.  */
    1427              : 
    1428              : static gimple_poly_bb_p
    1429         2171 : try_generate_gimple_bb (scop_p scop, basic_block bb)
    1430              : {
    1431         2171 :   vec<data_reference_p> drs = vNULL;
    1432         2171 :   vec<tree> writes = vNULL;
    1433         2171 :   vec<scalar_use> reads = vNULL;
    1434              : 
    1435         2171 :   sese_l region = scop->scop_info->region;
    1436         2171 :   edge nest = region.entry;
    1437         2171 :   loop_p loop = bb->loop_father;
    1438         2171 :   if (!loop_in_sese_p (loop, region))
    1439          392 :     loop = NULL;
    1440              : 
    1441         8187 :   for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
    1442         3845 :        gsi_next (&gsi))
    1443              :     {
    1444         3845 :       gimple *stmt = gsi_stmt (gsi);
    1445         3845 :       if (is_gimple_debug (stmt))
    1446           48 :         continue;
    1447              : 
    1448         3797 :       graphite_find_data_references_in_stmt (nest, loop, stmt, &drs);
    1449              : 
    1450         3797 :       tree def = gimple_get_lhs (stmt);
    1451         3797 :       if (def)
    1452         3181 :         build_cross_bb_scalars_def (scop, def, gimple_bb (stmt), &writes);
    1453              : 
    1454         3797 :       ssa_op_iter iter;
    1455         3797 :       tree use;
    1456         8970 :       FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
    1457         5173 :         build_cross_bb_scalars_use (scop, use, stmt, &reads);
    1458              :     }
    1459              : 
    1460              :   /* Handle defs and uses in PHIs.  Those need special treatment given
    1461              :      that we have to present ISL with sth that looks like we've rewritten
    1462              :      the IL out-of-SSA.  */
    1463         4516 :   for (gphi_iterator psi = gsi_start_phis (bb); !gsi_end_p (psi);
    1464         2345 :        gsi_next (&psi))
    1465              :     {
    1466         2345 :       gphi *phi = psi.phi ();
    1467         2345 :       tree res = gimple_phi_result (phi);
    1468         2345 :       if (virtual_operand_p (res)
    1469         2345 :           || scev_analyzable_p (res, scop->scop_info->region))
    1470         2048 :         continue;
    1471              :       /* To simulate out-of-SSA the block containing the PHI node has
    1472              :          reads of the PHI destination.  And to preserve SSA dependences
    1473              :          we also write to it (the out-of-SSA decl and the SSA result
    1474              :          are coalesced for dependence purposes which is good enough).  */
    1475          297 :       add_read (&reads, res, phi);
    1476          297 :       add_write (&writes, res);
    1477              :     }
    1478         2171 :   basic_block bb_for_succs = bb;
    1479         2171 :   if (bb_for_succs == bb_for_succs->loop_father->latch
    1480          560 :       && bb_in_sese_p (bb_for_succs, scop->scop_info->region)
    1481         2731 :       && sese_trivially_empty_bb_p (bb_for_succs))
    1482              :     bb_for_succs = NULL;
    1483         4342 :   while (bb_for_succs)
    1484              :     {
    1485         2171 :       basic_block latch = NULL;
    1486         2171 :       edge_iterator ei;
    1487         2171 :       edge e;
    1488         4958 :       FOR_EACH_EDGE (e, ei, bb_for_succs->succs)
    1489              :         {
    1490         6230 :           for (gphi_iterator psi = gsi_start_phis (e->dest); !gsi_end_p (psi);
    1491         3443 :                gsi_next (&psi))
    1492              :             {
    1493         3443 :               gphi *phi = psi.phi ();
    1494         3443 :               tree res = gimple_phi_result (phi);
    1495         6886 :               if (virtual_operand_p (res))
    1496         1405 :                 continue;
    1497              :               /* To simulate out-of-SSA the predecessor of edges into PHI nodes
    1498              :                  has a copy from the PHI argument to the PHI destination.  */
    1499         2038 :               if (! scev_analyzable_p (res, scop->scop_info->region))
    1500          401 :                 add_write (&writes, res);
    1501         2038 :               tree use = PHI_ARG_DEF_FROM_EDGE (phi, e);
    1502         2038 :               if (TREE_CODE (use) == SSA_NAME
    1503         1402 :                   && ! SSA_NAME_IS_DEFAULT_DEF (use)
    1504         1401 :                   && gimple_bb (SSA_NAME_DEF_STMT (use)) != bb_for_succs
    1505         3262 :                   && ! scev_analyzable_p (use, scop->scop_info->region))
    1506          199 :                 add_read (&reads, use, phi);
    1507              :             }
    1508         2787 :           if (e->dest == bb_for_succs->loop_father->latch
    1509          560 :               && bb_in_sese_p (e->dest, scop->scop_info->region)
    1510         3347 :               && sese_trivially_empty_bb_p (e->dest))
    1511          560 :             latch = e->dest;
    1512              :         }
    1513              :       /* Handle empty latch block PHIs here, otherwise we confuse ISL
    1514              :          with extra conditional code where it then peels off the last
    1515              :          iteration just because of that.  It would be simplest if we
    1516              :          just didn't force simple latches (thus remove the forwarder).  */
    1517         2171 :       bb_for_succs = latch;
    1518              :     }
    1519              : 
    1520              :   /* For the region exit block add reads for all live-out vars.  */
    1521         2171 :   if (bb == scop->scop_info->region.exit->src)
    1522              :     {
    1523          211 :       sese_build_liveouts (scop->scop_info);
    1524          211 :       unsigned i;
    1525          211 :       bitmap_iterator bi;
    1526          276 :       EXECUTE_IF_SET_IN_BITMAP (scop->scop_info->liveout, 0, i, bi)
    1527              :         {
    1528           65 :           tree use = ssa_name (i);
    1529           65 :           add_read (&reads, use, NULL);
    1530              :         }
    1531              :     }
    1532              : 
    1533         2171 :   if (drs.is_empty () && writes.is_empty () && reads.is_empty ())
    1534              :     return NULL;
    1535              : 
    1536          704 :   return new_gimple_poly_bb (bb, drs, reads, writes);
    1537              : }
    1538              : 
    1539              : /* Compute alias-sets for all data references in DRS.  */
    1540              : 
    1541              : static bool
    1542          211 : build_alias_set (scop_p scop)
    1543              : {
    1544          211 :   int num_vertices = scop->drs.length ();
    1545          211 :   struct graph *g = new_graph (num_vertices);
    1546          211 :   dr_info *dr1, *dr2;
    1547          211 :   int i, j;
    1548          211 :   int *all_vertices;
    1549              : 
    1550          211 :   struct loop *nest
    1551          211 :     = find_common_loop (scop->scop_info->region.entry->dest->loop_father,
    1552          211 :                         scop->scop_info->region.exit->src->loop_father);
    1553              : 
    1554          211 :   FOR_EACH_VEC_ELT (scop->drs, i, dr1)
    1555         4195 :     for (j = i+1; scop->drs.iterate (j, &dr2); j++)
    1556         2518 :       if (dr_may_alias_p (dr1->dr, dr2->dr, nest))
    1557              :         {
    1558              :           /* Dependences in the same alias set need to be handled
    1559              :              by just looking at DR_ACCESS_FNs.  */
    1560         1615 :           if (DR_NUM_DIMENSIONS (dr1->dr) == 0
    1561         3228 :               || DR_NUM_DIMENSIONS (dr1->dr) != DR_NUM_DIMENSIONS (dr2->dr)
    1562         1612 :               || ! operand_equal_p (DR_BASE_OBJECT (dr1->dr),
    1563         1612 :                                     DR_BASE_OBJECT (dr2->dr),
    1564              :                                     OEP_ADDRESS_OF)
    1565         3219 :               || ! types_compatible_p (TREE_TYPE (DR_BASE_OBJECT (dr1->dr)),
    1566         1605 :                                        TREE_TYPE (DR_BASE_OBJECT (dr2->dr))))
    1567              :             {
    1568           10 :               free_graph (g);
    1569           10 :               return false;
    1570              :             }
    1571         1605 :           add_edge (g, i, j);
    1572         1605 :           add_edge (g, j, i);
    1573              :         }
    1574              : 
    1575          201 :   all_vertices = XNEWVEC (int, num_vertices);
    1576         1134 :   for (i = 0; i < num_vertices; i++)
    1577          732 :     all_vertices[i] = i;
    1578              : 
    1579          201 :   scop->max_alias_set
    1580          201 :     = graphds_dfs (g, all_vertices, num_vertices, NULL, true, NULL) + 1;
    1581          201 :   free (all_vertices);
    1582              : 
    1583          933 :   for (i = 0; i < g->n_vertices; i++)
    1584          732 :     scop->drs[i].alias_set = g->vertices[i].component + 1;
    1585              : 
    1586          201 :   free_graph (g);
    1587          201 :   return true;
    1588              : }
    1589              : 
    1590              : /* Gather BBs and conditions for a SCOP.  */
    1591              : class gather_bbs : public dom_walker
    1592              : {
    1593              : public:
    1594              :   gather_bbs (cdi_direction, scop_p, int *);
    1595              : 
    1596              :   virtual edge before_dom_children (basic_block);
    1597              :   virtual void after_dom_children (basic_block);
    1598              : 
    1599              : private:
    1600              :   auto_vec<gimple *, 3> conditions, cases;
    1601              :   scop_p scop;
    1602              : };
    1603              : }
    1604          211 : gather_bbs::gather_bbs (cdi_direction direction, scop_p scop, int *bb_to_rpo)
    1605          211 :   : dom_walker (direction, ALL_BLOCKS, bb_to_rpo), scop (scop)
    1606              : {
    1607          211 : }
    1608              : 
    1609              : /* Call-back for dom_walk executed before visiting the dominated
    1610              :    blocks.  */
    1611              : 
    1612              : edge
    1613         2377 : gather_bbs::before_dom_children (basic_block bb)
    1614              : {
    1615         2377 :   sese_info_p region = scop->scop_info;
    1616         2377 :   if (!bb_in_sese_p (bb, region->region))
    1617          206 :     return dom_walker::STOP;
    1618              : 
    1619              :   /* For loops fully contained in the region record parameters in the
    1620              :      loop bounds.  */
    1621         2171 :   loop_p loop = bb->loop_father;
    1622         2171 :   if (loop->header == bb
    1623         2171 :       && loop_in_sese_p (loop, region->region))
    1624              :     {
    1625          560 :       tree nb_iters = number_of_latch_executions (loop);
    1626          560 :       if (chrec_contains_symbols (nb_iters))
    1627              :         {
    1628          143 :           nb_iters = cached_scalar_evolution_in_region (region->region,
    1629              :                                                         loop, nb_iters);
    1630          143 :           scan_tree_for_params (region, nb_iters);
    1631              :         }
    1632              :     }
    1633              : 
    1634         2171 :   if (gcond *stmt = single_pred_cond_non_loop_exit (bb))
    1635              :     {
    1636          647 :       edge e = single_pred_edge (bb);
    1637              :       /* Make sure the condition is in the region and thus was verified
    1638              :          to be handled.  */
    1639          647 :       if (e != region->region.entry)
    1640              :         {
    1641          647 :           conditions.safe_push (stmt);
    1642          647 :           if (e->flags & EDGE_TRUE_VALUE)
    1643          465 :             cases.safe_push (stmt);
    1644              :           else
    1645          182 :             cases.safe_push (NULL);
    1646              :         }
    1647              :     }
    1648              : 
    1649         2171 :   scop->scop_info->bbs.safe_push (bb);
    1650              : 
    1651         2171 :   gimple_poly_bb_p gbb = try_generate_gimple_bb (scop, bb);
    1652         2171 :   if (!gbb)
    1653              :     return NULL;
    1654              : 
    1655          704 :   GBB_CONDITIONS (gbb) = conditions.copy ();
    1656          704 :   GBB_CONDITION_CASES (gbb) = cases.copy ();
    1657              : 
    1658          704 :   poly_bb_p pbb = new_poly_bb (scop, gbb);
    1659          704 :   scop->pbbs.safe_push (pbb);
    1660              : 
    1661          704 :   int i;
    1662          704 :   data_reference_p dr;
    1663         2206 :   FOR_EACH_VEC_ELT (gbb->data_refs, i, dr)
    1664              :     {
    1665         1183 :       DEBUG_PRINT (dp << "Adding memory ";
    1666              :                    if (dr->is_read)
    1667              :                      dp << "read: ";
    1668              :                    else
    1669              :                      dp << "write: ";
    1670              :                    print_generic_expr (dump_file, dr->ref);
    1671              :                    dp << "\nFrom stmt: ";
    1672              :                    print_gimple_stmt (dump_file, dr->stmt, 0));
    1673              : 
    1674          798 :       scop->drs.safe_push (dr_info (dr, pbb));
    1675              :     }
    1676              : 
    1677              :   return NULL;
    1678              : }
    1679              : 
    1680              : /* Call-back for dom_walk executed after visiting the dominated
    1681              :    blocks.  */
    1682              : 
    1683              : void
    1684         2377 : gather_bbs::after_dom_children (basic_block bb)
    1685              : {
    1686         2377 :   if (!bb_in_sese_p (bb, scop->scop_info->region))
    1687              :     return;
    1688              : 
    1689         2171 :   if (single_pred_cond_non_loop_exit (bb))
    1690              :     {
    1691          647 :       edge e = single_pred_edge (bb);
    1692          647 :       if (e != scop->scop_info->region.entry)
    1693              :         {
    1694          647 :           conditions.pop ();
    1695          647 :           cases.pop ();
    1696              :         }
    1697              :     }
    1698              : }
    1699              : 
    1700              : 
    1701              : /* Compute sth like an execution order, dominator order with first executing
    1702              :    edges that stay inside the current loop, delaying processing exit edges.  */
    1703              : 
    1704              : static int *bb_to_rpo;
    1705              : 
    1706              : /* Helper for qsort, sorting after order above.  */
    1707              : 
    1708              : static int
    1709         4250 : cmp_pbbs (const void *pa, const void *pb)
    1710              : {
    1711         4250 :   poly_bb_p bb1 = *((const poly_bb_p *)pa);
    1712         4250 :   poly_bb_p bb2 = *((const poly_bb_p *)pb);
    1713         4250 :   if (bb_to_rpo[bb1->black_box->bb->index]
    1714         4250 :       < bb_to_rpo[bb2->black_box->bb->index])
    1715              :     return -1;
    1716         2293 :   else if (bb_to_rpo[bb1->black_box->bb->index]
    1717              :            > bb_to_rpo[bb2->black_box->bb->index])
    1718              :     return 1;
    1719              :   else
    1720            0 :     return 0;
    1721              : }
    1722              : 
    1723              : /* Find Static Control Parts (SCoP) in the current function and pushes
    1724              :    them to SCOPS.  */
    1725              : 
    1726              : void
    1727          556 : build_scops (vec<scop_p> *scops)
    1728              : {
    1729          556 :   if (dump_file)
    1730          190 :     dp.set_dump_file (dump_file);
    1731              : 
    1732          556 :   scop_detection sb;
    1733          556 :   sb.build_scop_depth (current_loops->tree_root);
    1734              : 
    1735              :   /* Now create scops from the lightweight SESEs.  */
    1736          556 :   vec<sese_l> scops_l = sb.get_scops ();
    1737              : 
    1738              :   /* Domwalk needs a bb to RPO mapping.  Compute it once here.  */
    1739          556 :   int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
    1740          556 :   int postorder_num = pre_and_rev_post_order_compute (NULL, postorder, true);
    1741          556 :   bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (cfun));
    1742         9841 :   for (int i = 0; i < postorder_num; ++i)
    1743         9285 :     bb_to_rpo[postorder[i]] = i;
    1744          556 :   free (postorder);
    1745              : 
    1746          556 :   int i;
    1747          556 :   sese_l *s;
    1748          767 :   FOR_EACH_VEC_ELT (scops_l, i, s)
    1749              :     {
    1750          211 :       scop_p scop = new_scop (s->entry, s->exit);
    1751              : 
    1752              :       /* Record all basic blocks and their conditions in REGION.  */
    1753          211 :       gather_bbs (CDI_DOMINATORS, scop, bb_to_rpo).walk (s->entry->dest);
    1754              : 
    1755              :       /* Sort pbbs after execution order for initial schedule generation.  */
    1756          211 :       scop->pbbs.qsort (cmp_pbbs);
    1757              : 
    1758          211 :       if (! build_alias_set (scop))
    1759              :         {
    1760           10 :           DEBUG_PRINT (dp << "[scop-detection-fail] cannot handle dependences\n");
    1761           10 :           free_scop (scop);
    1762           10 :           continue;
    1763              :         }
    1764              : 
    1765              :       /* Do not optimize a scop containing only PBBs that do not belong
    1766              :          to any loops.  */
    1767          201 :       if (sb.nb_pbbs_in_loops (scop) == 0)
    1768              :         {
    1769            0 :           DEBUG_PRINT (dp << "[scop-detection-fail] no data references.\n");
    1770            0 :           free_scop (scop);
    1771            0 :           continue;
    1772              :         }
    1773              : 
    1774          201 :       unsigned max_arrays = param_graphite_max_arrays_per_scop;
    1775          201 :       if (max_arrays > 0
    1776          402 :           && scop->drs.length () >= max_arrays)
    1777              :         {
    1778            0 :           DEBUG_PRINT (dp << "[scop-detection-fail] too many data references: "
    1779              :                        << scop->drs.length ()
    1780              :                        << " is larger than --param graphite-max-arrays-per-scop="
    1781              :                        << max_arrays << ".\n");
    1782            0 :           free_scop (scop);
    1783            0 :           continue;
    1784              :         }
    1785              : 
    1786          201 :       find_scop_parameters (scop);
    1787          201 :       graphite_dim_t max_dim = param_graphite_max_nb_scop_params;
    1788          201 :       if (max_dim > 0
    1789          201 :           && scop_nb_params (scop) > max_dim)
    1790              :         {
    1791            0 :           DEBUG_PRINT (dp << "[scop-detection-fail] too many parameters: "
    1792              :                           << scop_nb_params (scop)
    1793              :                           << " larger than --param graphite-max-nb-scop-params="
    1794              :                           << max_dim << ".\n");
    1795            0 :           free_scop (scop);
    1796            0 :           continue;
    1797              :         }
    1798              : 
    1799          201 :       scops->safe_push (scop);
    1800              :     }
    1801              : 
    1802          556 :   free (bb_to_rpo);
    1803          556 :   bb_to_rpo = NULL;
    1804          934 :   DEBUG_PRINT (dp << "number of SCoPs: " << (scops ? scops->length () : 0););
    1805          556 : }
    1806              : 
    1807              : #endif /* HAVE_isl */
        

Generated by: LCOV version 2.4-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.