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