annotate gcc/tree-switch-conversion.c @ 137:d22083d7f10b

merge
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 08 Nov 2018 14:16:42 +0900
parents 84e7813d76e9
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents: 67
diff changeset
1 /* Lower GIMPLE_SWITCH expressions to something more efficient than
kono
parents: 67
diff changeset
2 a jump table.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3 Copyright (C) 2006-2018 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 under the terms of the GNU General Public License as published by the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 Free Software Foundation; either version 3, or (at your option) any
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 later version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not, write to the Free
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 02110-1301, USA. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21
111
kono
parents: 67
diff changeset
22 /* This file handles the lowering of GIMPLE_SWITCH to an indexed
kono
parents: 67
diff changeset
23 load, or a series of bit-test-and-branch expressions. */
kono
parents: 67
diff changeset
24
kono
parents: 67
diff changeset
25 #include "config.h"
kono
parents: 67
diff changeset
26 #include "system.h"
kono
parents: 67
diff changeset
27 #include "coretypes.h"
kono
parents: 67
diff changeset
28 #include "backend.h"
kono
parents: 67
diff changeset
29 #include "insn-codes.h"
kono
parents: 67
diff changeset
30 #include "rtl.h"
kono
parents: 67
diff changeset
31 #include "tree.h"
kono
parents: 67
diff changeset
32 #include "gimple.h"
kono
parents: 67
diff changeset
33 #include "cfghooks.h"
kono
parents: 67
diff changeset
34 #include "tree-pass.h"
kono
parents: 67
diff changeset
35 #include "ssa.h"
kono
parents: 67
diff changeset
36 #include "optabs-tree.h"
kono
parents: 67
diff changeset
37 #include "cgraph.h"
kono
parents: 67
diff changeset
38 #include "gimple-pretty-print.h"
kono
parents: 67
diff changeset
39 #include "params.h"
kono
parents: 67
diff changeset
40 #include "fold-const.h"
kono
parents: 67
diff changeset
41 #include "varasm.h"
kono
parents: 67
diff changeset
42 #include "stor-layout.h"
kono
parents: 67
diff changeset
43 #include "cfganal.h"
kono
parents: 67
diff changeset
44 #include "gimplify.h"
kono
parents: 67
diff changeset
45 #include "gimple-iterator.h"
kono
parents: 67
diff changeset
46 #include "gimplify-me.h"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
47 #include "gimple-fold.h"
111
kono
parents: 67
diff changeset
48 #include "tree-cfg.h"
kono
parents: 67
diff changeset
49 #include "cfgloop.h"
kono
parents: 67
diff changeset
50 #include "alloc-pool.h"
kono
parents: 67
diff changeset
51 #include "target.h"
kono
parents: 67
diff changeset
52 #include "tree-into-ssa.h"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
53 #include "omp-general.h"
111
kono
parents: 67
diff changeset
54
kono
parents: 67
diff changeset
55 /* ??? For lang_hooks.types.type_for_mode, but is there a word_mode
kono
parents: 67
diff changeset
56 type in the GIMPLE type system that is language-independent? */
kono
parents: 67
diff changeset
57 #include "langhooks.h"
kono
parents: 67
diff changeset
58
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
59 #include "tree-switch-conversion.h"
111
kono
parents: 67
diff changeset
60
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
61 using namespace tree_switch_conversion;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
62
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
63 /* Constructor. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
64
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
65 switch_conversion::switch_conversion (): m_final_bb (NULL), m_other_count (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
66 m_constructors (NULL), m_default_values (NULL),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
67 m_arr_ref_first (NULL), m_arr_ref_last (NULL),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
68 m_reason (NULL), m_default_case_nonstandard (false), m_cfg_altered (false)
111
kono
parents: 67
diff changeset
69 {
kono
parents: 67
diff changeset
70 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
71
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
72 /* Collection information about SWTCH statement. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
73
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
74 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
75 switch_conversion::collect (gswitch *swtch)
111
kono
parents: 67
diff changeset
76 {
kono
parents: 67
diff changeset
77 unsigned int branch_num = gimple_switch_num_labels (swtch);
kono
parents: 67
diff changeset
78 tree min_case, max_case;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
79 unsigned int i;
111
kono
parents: 67
diff changeset
80 edge e, e_default, e_first;
kono
parents: 67
diff changeset
81 edge_iterator ei;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
82
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
83 m_switch = swtch;
111
kono
parents: 67
diff changeset
84
kono
parents: 67
diff changeset
85 /* The gimplifier has already sorted the cases by CASE_LOW and ensured there
kono
parents: 67
diff changeset
86 is a default label which is the first in the vector.
kono
parents: 67
diff changeset
87 Collect the bits we can deduce from the CFG. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
88 m_index_expr = gimple_switch_index (swtch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
89 m_switch_bb = gimple_bb (swtch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
90 e_default = gimple_switch_default_edge (cfun, swtch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
91 m_default_bb = e_default->dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
92 m_default_prob = e_default->probability;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
93 m_default_count = e_default->count ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
94 FOR_EACH_EDGE (e, ei, m_switch_bb->succs)
111
kono
parents: 67
diff changeset
95 if (e != e_default)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
96 m_other_count += e->count ();
111
kono
parents: 67
diff changeset
97
kono
parents: 67
diff changeset
98 /* Get upper and lower bounds of case values, and the covered range. */
kono
parents: 67
diff changeset
99 min_case = gimple_switch_label (swtch, 1);
kono
parents: 67
diff changeset
100 max_case = gimple_switch_label (swtch, branch_num - 1);
kono
parents: 67
diff changeset
101
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
102 m_range_min = CASE_LOW (min_case);
111
kono
parents: 67
diff changeset
103 if (CASE_HIGH (max_case) != NULL_TREE)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
104 m_range_max = CASE_HIGH (max_case);
111
kono
parents: 67
diff changeset
105 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
106 m_range_max = CASE_LOW (max_case);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
107
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
108 m_contiguous_range = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
109 tree last = CASE_HIGH (min_case) ? CASE_HIGH (min_case) : m_range_min;
111
kono
parents: 67
diff changeset
110 for (i = 2; i < branch_num; i++)
kono
parents: 67
diff changeset
111 {
kono
parents: 67
diff changeset
112 tree elt = gimple_switch_label (swtch, i);
kono
parents: 67
diff changeset
113 if (wi::to_wide (last) + 1 != wi::to_wide (CASE_LOW (elt)))
kono
parents: 67
diff changeset
114 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
115 m_contiguous_range = false;
111
kono
parents: 67
diff changeset
116 break;
kono
parents: 67
diff changeset
117 }
kono
parents: 67
diff changeset
118 last = CASE_HIGH (elt) ? CASE_HIGH (elt) : CASE_LOW (elt);
kono
parents: 67
diff changeset
119 }
kono
parents: 67
diff changeset
120
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
121 if (m_contiguous_range)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
122 e_first = gimple_switch_edge (cfun, swtch, 1);
111
kono
parents: 67
diff changeset
123 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
124 e_first = e_default;
111
kono
parents: 67
diff changeset
125
kono
parents: 67
diff changeset
126 /* See if there is one common successor block for all branch
kono
parents: 67
diff changeset
127 targets. If it exists, record it in FINAL_BB.
kono
parents: 67
diff changeset
128 Start with the destination of the first non-default case
kono
parents: 67
diff changeset
129 if the range is contiguous and default case otherwise as
kono
parents: 67
diff changeset
130 guess or its destination in case it is a forwarder block. */
kono
parents: 67
diff changeset
131 if (! single_pred_p (e_first->dest))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
132 m_final_bb = e_first->dest;
111
kono
parents: 67
diff changeset
133 else if (single_succ_p (e_first->dest)
kono
parents: 67
diff changeset
134 && ! single_pred_p (single_succ (e_first->dest)))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
135 m_final_bb = single_succ (e_first->dest);
111
kono
parents: 67
diff changeset
136 /* Require that all switch destinations are either that common
kono
parents: 67
diff changeset
137 FINAL_BB or a forwarder to it, except for the default
kono
parents: 67
diff changeset
138 case if contiguous range. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
139 if (m_final_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
140 FOR_EACH_EDGE (e, ei, m_switch_bb->succs)
111
kono
parents: 67
diff changeset
141 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
142 if (e->dest == m_final_bb)
111
kono
parents: 67
diff changeset
143 continue;
kono
parents: 67
diff changeset
144
kono
parents: 67
diff changeset
145 if (single_pred_p (e->dest)
kono
parents: 67
diff changeset
146 && single_succ_p (e->dest)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
147 && single_succ (e->dest) == m_final_bb)
111
kono
parents: 67
diff changeset
148 continue;
kono
parents: 67
diff changeset
149
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
150 if (e == e_default && m_contiguous_range)
111
kono
parents: 67
diff changeset
151 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
152 m_default_case_nonstandard = true;
111
kono
parents: 67
diff changeset
153 continue;
kono
parents: 67
diff changeset
154 }
kono
parents: 67
diff changeset
155
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
156 m_final_bb = NULL;
111
kono
parents: 67
diff changeset
157 break;
kono
parents: 67
diff changeset
158 }
kono
parents: 67
diff changeset
159
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
160 m_range_size
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
161 = int_const_binop (MINUS_EXPR, m_range_max, m_range_min);
111
kono
parents: 67
diff changeset
162
kono
parents: 67
diff changeset
163 /* Get a count of the number of case labels. Single-valued case labels
kono
parents: 67
diff changeset
164 simply count as one, but a case range counts double, since it may
kono
parents: 67
diff changeset
165 require two compares if it gets lowered as a branching tree. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
166 m_count = 0;
111
kono
parents: 67
diff changeset
167 for (i = 1; i < branch_num; i++)
kono
parents: 67
diff changeset
168 {
kono
parents: 67
diff changeset
169 tree elt = gimple_switch_label (swtch, i);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
170 m_count++;
111
kono
parents: 67
diff changeset
171 if (CASE_HIGH (elt)
kono
parents: 67
diff changeset
172 && ! tree_int_cst_equal (CASE_LOW (elt), CASE_HIGH (elt)))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
173 m_count++;
111
kono
parents: 67
diff changeset
174 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
175
111
kono
parents: 67
diff changeset
176 /* Get the number of unique non-default targets out of the GIMPLE_SWITCH
kono
parents: 67
diff changeset
177 block. Assume a CFG cleanup would have already removed degenerate
kono
parents: 67
diff changeset
178 switch statements, this allows us to just use EDGE_COUNT. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
179 m_uniq = EDGE_COUNT (gimple_bb (swtch)->succs) - 1;
111
kono
parents: 67
diff changeset
180 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
181
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
182 /* Checks whether the range given by individual case statements of the switch
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 switch statement isn't too big and whether the number of branches actually
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 satisfies the size of the new array. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
186 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
187 switch_conversion::check_range ()
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
189 gcc_assert (m_range_size);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
190 if (!tree_fits_uhwi_p (m_range_size))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
192 m_reason = "index range way too large or otherwise unusable";
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
196 if (tree_to_uhwi (m_range_size)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
197 > ((unsigned) m_count * SWITCH_CONVERSION_BRANCH_RATIO))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
199 m_reason = "the maximum range-branch ratio exceeded";
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
206 /* Checks whether all but the final BB basic blocks are empty. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
207
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
208 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
209 switch_conversion::check_all_empty_except_final ()
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
211 edge e, e_default = find_edge (m_switch_bb, m_default_bb);
111
kono
parents: 67
diff changeset
212 edge_iterator ei;
kono
parents: 67
diff changeset
213
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
214 FOR_EACH_EDGE (e, ei, m_switch_bb->succs)
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
215 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
216 if (e->dest == m_final_bb)
111
kono
parents: 67
diff changeset
217 continue;
kono
parents: 67
diff changeset
218
kono
parents: 67
diff changeset
219 if (!empty_block_p (e->dest))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
221 if (m_contiguous_range && e == e_default)
111
kono
parents: 67
diff changeset
222 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
223 m_default_case_nonstandard = true;
111
kono
parents: 67
diff changeset
224 continue;
kono
parents: 67
diff changeset
225 }
kono
parents: 67
diff changeset
226
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
227 m_reason = "bad case - a non-final BB not empty";
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 /* This function checks whether all required values in phi nodes in final_bb
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 are constants. Required values are those that correspond to a basic block
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 which is a part of the examined switch statement. It returns true if the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 phi nodes are OK, otherwise false. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
240 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
241 switch_conversion::check_final_bb ()
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 {
111
kono
parents: 67
diff changeset
243 gphi_iterator gsi;
kono
parents: 67
diff changeset
244
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
245 m_phi_count = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
246 for (gsi = gsi_start_phis (m_final_bb); !gsi_end_p (gsi); gsi_next (&gsi))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 {
111
kono
parents: 67
diff changeset
248 gphi *phi = gsi.phi ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 unsigned int i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250
111
kono
parents: 67
diff changeset
251 if (virtual_operand_p (gimple_phi_result (phi)))
kono
parents: 67
diff changeset
252 continue;
kono
parents: 67
diff changeset
253
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
254 m_phi_count++;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 for (i = 0; i < gimple_phi_num_args (phi); i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 basic_block bb = gimple_phi_arg_edge (phi, i)->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
260 if (bb == m_switch_bb
111
kono
parents: 67
diff changeset
261 || (single_pred_p (bb)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
262 && single_pred (bb) == m_switch_bb
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
263 && (!m_default_case_nonstandard
111
kono
parents: 67
diff changeset
264 || empty_block_p (bb))))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 tree reloc, val;
111
kono
parents: 67
diff changeset
267 const char *reason = NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 val = gimple_phi_arg_def (phi, i);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 if (!is_gimple_ip_invariant (val))
111
kono
parents: 67
diff changeset
271 reason = "non-invariant value from a case";
kono
parents: 67
diff changeset
272 else
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 {
111
kono
parents: 67
diff changeset
274 reloc = initializer_constant_valid_p (val, TREE_TYPE (val));
kono
parents: 67
diff changeset
275 if ((flag_pic && reloc != null_pointer_node)
kono
parents: 67
diff changeset
276 || (!flag_pic && reloc == NULL_TREE))
kono
parents: 67
diff changeset
277 {
kono
parents: 67
diff changeset
278 if (reloc)
kono
parents: 67
diff changeset
279 reason
kono
parents: 67
diff changeset
280 = "value from a case would need runtime relocations";
kono
parents: 67
diff changeset
281 else
kono
parents: 67
diff changeset
282 reason
kono
parents: 67
diff changeset
283 = "value from a case is not a valid initializer";
kono
parents: 67
diff changeset
284 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 }
111
kono
parents: 67
diff changeset
286 if (reason)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 {
111
kono
parents: 67
diff changeset
288 /* For contiguous range, we can allow non-constant
kono
parents: 67
diff changeset
289 or one that needs relocation, as long as it is
kono
parents: 67
diff changeset
290 only reachable from the default case. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
291 if (bb == m_switch_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
292 bb = m_final_bb;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
293 if (!m_contiguous_range || bb != m_default_bb)
111
kono
parents: 67
diff changeset
294 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
295 m_reason = reason;
111
kono
parents: 67
diff changeset
296 return false;
kono
parents: 67
diff changeset
297 }
kono
parents: 67
diff changeset
298
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
299 unsigned int branch_num = gimple_switch_num_labels (m_switch);
111
kono
parents: 67
diff changeset
300 for (unsigned int i = 1; i < branch_num; i++)
kono
parents: 67
diff changeset
301 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
302 if (gimple_switch_label_bb (cfun, m_switch, i) == bb)
111
kono
parents: 67
diff changeset
303 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
304 m_reason = reason;
111
kono
parents: 67
diff changeset
305 return false;
kono
parents: 67
diff changeset
306 }
kono
parents: 67
diff changeset
307 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
308 m_default_case_nonstandard = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
310 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 /* The following function allocates default_values, target_{in,out}_names and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 constructors arrays. The last one is also populated with pointers to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 vectors that will become constructors of new arrays. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
320
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
321 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
322 switch_conversion::create_temp_arrays ()
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 int i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
325
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
326 m_default_values = XCNEWVEC (tree, m_phi_count * 3);
111
kono
parents: 67
diff changeset
327 /* ??? Macros do not support multi argument templates in their
kono
parents: 67
diff changeset
328 argument list. We create a typedef to work around that problem. */
kono
parents: 67
diff changeset
329 typedef vec<constructor_elt, va_gc> *vec_constructor_elt_gc;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
330 m_constructors = XCNEWVEC (vec_constructor_elt_gc, m_phi_count);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
331 m_target_inbound_names = m_default_values + m_phi_count;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
332 m_target_outbound_names = m_target_inbound_names + m_phi_count;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
333 for (i = 0; i < m_phi_count; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
334 vec_alloc (m_constructors[i], tree_to_uhwi (m_range_size) + 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 /* Populate the array of default values in the order of phi nodes.
111
kono
parents: 67
diff changeset
338 DEFAULT_CASE is the CASE_LABEL_EXPR for the default switch branch
kono
parents: 67
diff changeset
339 if the range is non-contiguous or the default case has standard
kono
parents: 67
diff changeset
340 structure, otherwise it is the first non-default case instead. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
341
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
342 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
343 switch_conversion::gather_default_values (tree default_case)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 {
111
kono
parents: 67
diff changeset
345 gphi_iterator gsi;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
346 basic_block bb = label_to_block (cfun, CASE_LABEL (default_case));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 int i = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349
111
kono
parents: 67
diff changeset
350 gcc_assert (CASE_LOW (default_case) == NULL_TREE
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
351 || m_default_case_nonstandard);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
352
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
353 if (bb == m_final_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
354 e = find_edge (m_switch_bb, bb);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 e = single_succ_edge (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
357
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
358 for (gsi = gsi_start_phis (m_final_bb); !gsi_end_p (gsi); gsi_next (&gsi))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 {
111
kono
parents: 67
diff changeset
360 gphi *phi = gsi.phi ();
kono
parents: 67
diff changeset
361 if (virtual_operand_p (gimple_phi_result (phi)))
kono
parents: 67
diff changeset
362 continue;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363 tree val = PHI_ARG_DEF_FROM_EDGE (phi, e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
364 gcc_assert (val);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
365 m_default_values[i++] = val;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
366 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369 /* The following function populates the vectors in the constructors array with
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 future contents of the static arrays. The vectors are populated in the
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
371 order of phi nodes. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
372
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
373 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
374 switch_conversion::build_constructors ()
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
375 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
376 unsigned i, branch_num = gimple_switch_num_labels (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
377 tree pos = m_range_min;
111
kono
parents: 67
diff changeset
378 tree pos_one = build_int_cst (TREE_TYPE (pos), 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
379
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 for (i = 1; i < branch_num; i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
381 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
382 tree cs = gimple_switch_label (m_switch, i);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
383 basic_block bb = label_to_block (cfun, CASE_LABEL (cs));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385 tree high;
111
kono
parents: 67
diff changeset
386 gphi_iterator gsi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 int j;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
389 if (bb == m_final_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
390 e = find_edge (m_switch_bb, bb);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392 e = single_succ_edge (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393 gcc_assert (e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 while (tree_int_cst_lt (pos, CASE_LOW (cs)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 int k;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
398 for (k = 0; k < m_phi_count; k++)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 {
111
kono
parents: 67
diff changeset
400 constructor_elt elt;
kono
parents: 67
diff changeset
401
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
402 elt.index = int_const_binop (MINUS_EXPR, pos, m_range_min);
111
kono
parents: 67
diff changeset
403 elt.value
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
404 = unshare_expr_without_location (m_default_values[k]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
405 m_constructors[k]->quick_push (elt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
406 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
407
111
kono
parents: 67
diff changeset
408 pos = int_const_binop (PLUS_EXPR, pos, pos_one);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410 gcc_assert (tree_int_cst_equal (pos, CASE_LOW (cs)));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 j = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
413 if (CASE_HIGH (cs))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414 high = CASE_HIGH (cs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
415 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
416 high = CASE_LOW (cs);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
417 for (gsi = gsi_start_phis (m_final_bb);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
418 !gsi_end_p (gsi); gsi_next (&gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
419 {
111
kono
parents: 67
diff changeset
420 gphi *phi = gsi.phi ();
kono
parents: 67
diff changeset
421 if (virtual_operand_p (gimple_phi_result (phi)))
kono
parents: 67
diff changeset
422 continue;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423 tree val = PHI_ARG_DEF_FROM_EDGE (phi, e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
424 tree low = CASE_LOW (cs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
425 pos = CASE_LOW (cs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
426
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
427 do
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
428 {
111
kono
parents: 67
diff changeset
429 constructor_elt elt;
kono
parents: 67
diff changeset
430
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
431 elt.index = int_const_binop (MINUS_EXPR, pos, m_range_min);
111
kono
parents: 67
diff changeset
432 elt.value = unshare_expr_without_location (val);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
433 m_constructors[j]->quick_push (elt);
111
kono
parents: 67
diff changeset
434
kono
parents: 67
diff changeset
435 pos = int_const_binop (PLUS_EXPR, pos, pos_one);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
436 } while (!tree_int_cst_lt (high, pos)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
437 && tree_int_cst_lt (low, pos));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
438 j++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
439 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
440 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
441 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
442
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
443 /* If all values in the constructor vector are products of a linear function
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
444 a * x + b, then return true. When true, COEFF_A and COEFF_B and
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
445 coefficients of the linear function. Note that equal values are special
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
446 case of a linear function with a and b equal to zero. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
447
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
448 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
449 switch_conversion::contains_linear_function_p (vec<constructor_elt, va_gc> *vec,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
450 wide_int *coeff_a,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
451 wide_int *coeff_b)
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
452 {
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
453 unsigned int i;
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
454 constructor_elt *elt;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
455
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
456 gcc_assert (vec->length () >= 2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
457
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
458 /* Let's try to find any linear function a * x + y that can apply to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
459 given values. 'a' can be calculated as follows:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
460
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
461 a = (y2 - y1) / (x2 - x1) where x2 - x1 = 1 (consecutive case indices)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
462 a = y2 - y1
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
463
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
464 and
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
465
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
466 b = y2 - a * x2
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
467
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
468 */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
469
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
470 tree elt0 = (*vec)[0].value;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
471 tree elt1 = (*vec)[1].value;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
472
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
473 if (TREE_CODE (elt0) != INTEGER_CST || TREE_CODE (elt1) != INTEGER_CST)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
474 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
475
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
476 wide_int range_min = wi::to_wide (fold_convert (TREE_TYPE (elt0),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
477 m_range_min));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
478 wide_int y1 = wi::to_wide (elt0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
479 wide_int y2 = wi::to_wide (elt1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
480 wide_int a = y2 - y1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
481 wide_int b = y2 - a * (range_min + 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
482
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
483 /* Verify that all values fulfill the linear function. */
111
kono
parents: 67
diff changeset
484 FOR_EACH_VEC_SAFE_ELT (vec, i, elt)
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
485 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
486 if (TREE_CODE (elt->value) != INTEGER_CST)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
487 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
488
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
489 wide_int value = wi::to_wide (elt->value);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
490 if (a * range_min + b != value)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
491 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
492
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
493 ++range_min;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
494 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
495
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
496 *coeff_a = a;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
497 *coeff_b = b;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
498
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
499 return true;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
500 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
501
111
kono
parents: 67
diff changeset
502 /* Return type which should be used for array elements, either TYPE's
kono
parents: 67
diff changeset
503 main variant or, for integral types, some smaller integral type
kono
parents: 67
diff changeset
504 that can still hold all the constants. */
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
505
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
506 tree
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
507 switch_conversion::array_value_type (tree type, int num)
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
508 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
509 unsigned int i, len = vec_safe_length (m_constructors[num]);
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
510 constructor_elt *elt;
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
511 int sign = 0;
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
512 tree smaller_type;
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
513
111
kono
parents: 67
diff changeset
514 /* Types with alignments greater than their size can reach here, e.g. out of
kono
parents: 67
diff changeset
515 SRA. We couldn't use these as an array component type so get back to the
kono
parents: 67
diff changeset
516 main variant first, which, for our purposes, is fine for other types as
kono
parents: 67
diff changeset
517 well. */
kono
parents: 67
diff changeset
518
kono
parents: 67
diff changeset
519 type = TYPE_MAIN_VARIANT (type);
kono
parents: 67
diff changeset
520
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
521 if (!INTEGRAL_TYPE_P (type))
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
522 return type;
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
523
111
kono
parents: 67
diff changeset
524 scalar_int_mode type_mode = SCALAR_INT_TYPE_MODE (type);
kono
parents: 67
diff changeset
525 scalar_int_mode mode = get_narrowest_mode (type_mode);
kono
parents: 67
diff changeset
526 if (GET_MODE_SIZE (type_mode) <= GET_MODE_SIZE (mode))
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
527 return type;
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
528
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
529 if (len < (optimize_bb_for_size_p (gimple_bb (m_switch)) ? 2 : 32))
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
530 return type;
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
531
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
532 FOR_EACH_VEC_SAFE_ELT (m_constructors[num], i, elt)
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
533 {
111
kono
parents: 67
diff changeset
534 wide_int cst;
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
535
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
536 if (TREE_CODE (elt->value) != INTEGER_CST)
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
537 return type;
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
538
111
kono
parents: 67
diff changeset
539 cst = wi::to_wide (elt->value);
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
540 while (1)
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
541 {
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
542 unsigned int prec = GET_MODE_BITSIZE (mode);
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
543 if (prec > HOST_BITS_PER_WIDE_INT)
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
544 return type;
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
545
111
kono
parents: 67
diff changeset
546 if (sign >= 0 && cst == wi::zext (cst, prec))
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
547 {
111
kono
parents: 67
diff changeset
548 if (sign == 0 && cst == wi::sext (cst, prec))
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
549 break;
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
550 sign = 1;
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
551 break;
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
552 }
111
kono
parents: 67
diff changeset
553 if (sign <= 0 && cst == wi::sext (cst, prec))
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
554 {
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
555 sign = -1;
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
556 break;
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
557 }
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
558
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
559 if (sign == 1)
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
560 sign = 0;
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
561
111
kono
parents: 67
diff changeset
562 if (!GET_MODE_WIDER_MODE (mode).exists (&mode)
kono
parents: 67
diff changeset
563 || GET_MODE_SIZE (mode) >= GET_MODE_SIZE (type_mode))
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
564 return type;
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
565 }
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
566 }
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
567
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
568 if (sign == 0)
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
569 sign = TYPE_UNSIGNED (type) ? 1 : -1;
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
570 smaller_type = lang_hooks.types.type_for_mode (mode, sign >= 0);
111
kono
parents: 67
diff changeset
571 if (GET_MODE_SIZE (type_mode)
kono
parents: 67
diff changeset
572 <= GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (smaller_type)))
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
573 return type;
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
574
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
575 return smaller_type;
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
576 }
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
577
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
578 /* Create an appropriate array type and declaration and assemble a static
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
579 array variable. Also create a load statement that initializes
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
580 the variable in question with a value from the static array. SWTCH is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
581 the switch statement being converted, NUM is the index to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
582 arrays of constructors, default values and target SSA names
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
583 for this particular array. ARR_INDEX_TYPE is the type of the index
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
584 of the new array, PHI is the phi node of the final BB that corresponds
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
585 to the value that will be loaded from the created array. TIDX
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
586 is an ssa name of a temporary variable holding the index for loads from the
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
587 new array. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
588
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
589 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
590 switch_conversion::build_one_array (int num, tree arr_index_type,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
591 gphi *phi, tree tidx)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
593 tree name;
111
kono
parents: 67
diff changeset
594 gimple *load;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
595 gimple_stmt_iterator gsi = gsi_for_stmt (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
596 location_t loc = gimple_location (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
597
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
598 gcc_assert (m_default_values[num]);
111
kono
parents: 67
diff changeset
599
kono
parents: 67
diff changeset
600 name = copy_ssa_name (PHI_RESULT (phi));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
601 m_target_inbound_names[num] = name;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
602
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
603 wide_int coeff_a, coeff_b;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
604 bool linear_p = contains_linear_function_p (m_constructors[num], &coeff_a,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
605 &coeff_b);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
606 if (linear_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
607 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
608 if (dump_file && coeff_a.to_uhwi () > 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
609 fprintf (dump_file, "Linear transformation with A = %" PRId64
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
610 " and B = %" PRId64 "\n", coeff_a.to_shwi (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
611 coeff_b.to_shwi ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
612
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
613 tree t = unsigned_type_for (TREE_TYPE (m_index_expr));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
614 gimple_seq seq = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
615 tree tmp = gimple_convert (&seq, t, m_index_expr);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
616 tree tmp2 = gimple_build (&seq, MULT_EXPR, t,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
617 wide_int_to_tree (t, coeff_a), tmp);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
618 tree tmp3 = gimple_build (&seq, PLUS_EXPR, t, tmp2,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
619 wide_int_to_tree (t, coeff_b));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
620 tree tmp4 = gimple_convert (&seq, TREE_TYPE (name), tmp3);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
621 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
622 load = gimple_build_assign (name, tmp4);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
623 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
624 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
625 {
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
626 tree array_type, ctor, decl, value_type, fetch, default_type;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
627
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
628 default_type = TREE_TYPE (m_default_values[num]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
629 value_type = array_value_type (default_type, num);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
630 array_type = build_array_type (value_type, arr_index_type);
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
631 if (default_type != value_type)
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
632 {
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
633 unsigned int i;
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
634 constructor_elt *elt;
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
635
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
636 FOR_EACH_VEC_SAFE_ELT (m_constructors[num], i, elt)
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
637 elt->value = fold_convert (value_type, elt->value);
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
638 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
639 ctor = build_constructor (array_type, m_constructors[num]);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
640 TREE_CONSTANT (ctor) = true;
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
641 TREE_STATIC (ctor) = true;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
642
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
643 decl = build_decl (loc, VAR_DECL, NULL_TREE, array_type);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
644 TREE_STATIC (decl) = 1;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
645 DECL_INITIAL (decl) = ctor;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
646
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
647 DECL_NAME (decl) = create_tmp_var_name ("CSWTCH");
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
648 DECL_ARTIFICIAL (decl) = 1;
111
kono
parents: 67
diff changeset
649 DECL_IGNORED_P (decl) = 1;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
650 TREE_CONSTANT (decl) = 1;
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
651 TREE_READONLY (decl) = 1;
111
kono
parents: 67
diff changeset
652 DECL_IGNORED_P (decl) = 1;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
653 if (offloading_function_p (cfun->decl))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
654 DECL_ATTRIBUTES (decl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
655 = tree_cons (get_identifier ("omp declare target"), NULL_TREE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
656 NULL_TREE);
111
kono
parents: 67
diff changeset
657 varpool_node::finalize_decl (decl);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
658
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
659 fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
660 NULL_TREE);
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
661 if (default_type != value_type)
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
662 {
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
663 fetch = fold_convert (default_type, fetch);
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
664 fetch = force_gimple_operand_gsi (&gsi, fetch, true, NULL_TREE,
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
665 true, GSI_SAME_STMT);
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
666 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
667 load = gimple_build_assign (name, fetch);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
668 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
669
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
670 gsi_insert_before (&gsi, load, GSI_SAME_STMT);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
671 update_stmt (load);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
672 m_arr_ref_last = load;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
673 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
674
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
675 /* Builds and initializes static arrays initialized with values gathered from
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
676 the switch statement. Also creates statements that load values from
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
677 them. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
678
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
679 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
680 switch_conversion::build_arrays ()
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
681 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
682 tree arr_index_type;
111
kono
parents: 67
diff changeset
683 tree tidx, sub, utype;
kono
parents: 67
diff changeset
684 gimple *stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
685 gimple_stmt_iterator gsi;
111
kono
parents: 67
diff changeset
686 gphi_iterator gpi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
687 int i;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
688 location_t loc = gimple_location (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
689
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
690 gsi = gsi_for_stmt (m_switch);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
691
111
kono
parents: 67
diff changeset
692 /* Make sure we do not generate arithmetics in a subrange. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
693 utype = TREE_TYPE (m_index_expr);
111
kono
parents: 67
diff changeset
694 if (TREE_TYPE (utype))
kono
parents: 67
diff changeset
695 utype = lang_hooks.types.type_for_mode (TYPE_MODE (TREE_TYPE (utype)), 1);
kono
parents: 67
diff changeset
696 else
kono
parents: 67
diff changeset
697 utype = lang_hooks.types.type_for_mode (TYPE_MODE (utype), 1);
kono
parents: 67
diff changeset
698
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
699 arr_index_type = build_index_type (m_range_size);
111
kono
parents: 67
diff changeset
700 tidx = make_ssa_name (utype);
kono
parents: 67
diff changeset
701 sub = fold_build2_loc (loc, MINUS_EXPR, utype,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
702 fold_convert_loc (loc, utype, m_index_expr),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
703 fold_convert_loc (loc, utype, m_range_min));
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
704 sub = force_gimple_operand_gsi (&gsi, sub,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
705 false, NULL, true, GSI_SAME_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
706 stmt = gimple_build_assign (tidx, sub);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
707
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
708 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
709 update_stmt (stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
710 m_arr_ref_first = stmt;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
711
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
712 for (gpi = gsi_start_phis (m_final_bb), i = 0;
111
kono
parents: 67
diff changeset
713 !gsi_end_p (gpi); gsi_next (&gpi))
kono
parents: 67
diff changeset
714 {
kono
parents: 67
diff changeset
715 gphi *phi = gpi.phi ();
kono
parents: 67
diff changeset
716 if (!virtual_operand_p (gimple_phi_result (phi)))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
717 build_one_array (i++, arr_index_type, phi, tidx);
111
kono
parents: 67
diff changeset
718 else
kono
parents: 67
diff changeset
719 {
kono
parents: 67
diff changeset
720 edge e;
kono
parents: 67
diff changeset
721 edge_iterator ei;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
722 FOR_EACH_EDGE (e, ei, m_switch_bb->succs)
111
kono
parents: 67
diff changeset
723 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
724 if (e->dest == m_final_bb)
111
kono
parents: 67
diff changeset
725 break;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
726 if (!m_default_case_nonstandard
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
727 || e->dest != m_default_bb)
111
kono
parents: 67
diff changeset
728 {
kono
parents: 67
diff changeset
729 e = single_succ_edge (e->dest);
kono
parents: 67
diff changeset
730 break;
kono
parents: 67
diff changeset
731 }
kono
parents: 67
diff changeset
732 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
733 gcc_assert (e && e->dest == m_final_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
734 m_target_vop = PHI_ARG_DEF_FROM_EDGE (phi, e);
111
kono
parents: 67
diff changeset
735 }
kono
parents: 67
diff changeset
736 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
737 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
738
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
739 /* Generates and appropriately inserts loads of default values at the position
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
740 given by GSI. Returns the last inserted statement. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
741
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
742 gassign *
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
743 switch_conversion::gen_def_assigns (gimple_stmt_iterator *gsi)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
744 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
745 int i;
111
kono
parents: 67
diff changeset
746 gassign *assign = NULL;
kono
parents: 67
diff changeset
747
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
748 for (i = 0; i < m_phi_count; i++)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
749 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
750 tree name = copy_ssa_name (m_target_inbound_names[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
751 m_target_outbound_names[i] = name;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
752 assign = gimple_build_assign (name, m_default_values[i]);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
753 gsi_insert_before (gsi, assign, GSI_SAME_STMT);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
754 update_stmt (assign);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
755 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
756 return assign;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
757 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
758
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
759 /* Deletes the unused bbs and edges that now contain the switch statement and
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
760 its empty branch bbs. BBD is the now dead BB containing
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
761 the original switch statement, FINAL is the last BB of the converted
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
762 switch statement (in terms of succession). */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
763
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
764 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
765 switch_conversion::prune_bbs (basic_block bbd, basic_block final,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
766 basic_block default_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
767 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
768 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
769 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
770
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
771 for (ei = ei_start (bbd->succs); (e = ei_safe_edge (ei)); )
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
772 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
773 basic_block bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
774 bb = e->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
775 remove_edge (e);
111
kono
parents: 67
diff changeset
776 if (bb != final && bb != default_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
777 delete_basic_block (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
778 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
779 delete_basic_block (bbd);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
780 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
781
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
782 /* Add values to phi nodes in final_bb for the two new edges. E1F is the edge
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
783 from the basic block loading values from an array and E2F from the basic
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
784 block loading default values. BBF is the last switch basic block (see the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
785 bbf description in the comment below). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
786
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
787 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
788 switch_conversion::fix_phi_nodes (edge e1f, edge e2f, basic_block bbf)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
789 {
111
kono
parents: 67
diff changeset
790 gphi_iterator gsi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
791 int i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
792
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
793 for (gsi = gsi_start_phis (bbf), i = 0;
111
kono
parents: 67
diff changeset
794 !gsi_end_p (gsi); gsi_next (&gsi))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
795 {
111
kono
parents: 67
diff changeset
796 gphi *phi = gsi.phi ();
kono
parents: 67
diff changeset
797 tree inbound, outbound;
kono
parents: 67
diff changeset
798 if (virtual_operand_p (gimple_phi_result (phi)))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
799 inbound = outbound = m_target_vop;
111
kono
parents: 67
diff changeset
800 else
kono
parents: 67
diff changeset
801 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
802 inbound = m_target_inbound_names[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
803 outbound = m_target_outbound_names[i++];
111
kono
parents: 67
diff changeset
804 }
kono
parents: 67
diff changeset
805 add_phi_arg (phi, inbound, e1f, UNKNOWN_LOCATION);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
806 if (!m_default_case_nonstandard)
111
kono
parents: 67
diff changeset
807 add_phi_arg (phi, outbound, e2f, UNKNOWN_LOCATION);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
808 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
809 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
810
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
811 /* Creates a check whether the switch expression value actually falls into the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
812 range given by all the cases. If it does not, the temporaries are loaded
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
813 with default values instead. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
814
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
815 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
816 switch_conversion::gen_inbound_check ()
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
817 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
818 tree label_decl1 = create_artificial_label (UNKNOWN_LOCATION);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
819 tree label_decl2 = create_artificial_label (UNKNOWN_LOCATION);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
820 tree label_decl3 = create_artificial_label (UNKNOWN_LOCATION);
111
kono
parents: 67
diff changeset
821 glabel *label1, *label2, *label3;
kono
parents: 67
diff changeset
822 tree utype, tidx;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
823 tree bound;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
824
111
kono
parents: 67
diff changeset
825 gcond *cond_stmt;
kono
parents: 67
diff changeset
826
kono
parents: 67
diff changeset
827 gassign *last_assign = NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
828 gimple_stmt_iterator gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
829 basic_block bb0, bb1, bb2, bbf, bbd;
111
kono
parents: 67
diff changeset
830 edge e01 = NULL, e02, e21, e1d, e1f, e2f;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
831 location_t loc = gimple_location (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
832
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
833 gcc_assert (m_default_values);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
834
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
835 bb0 = gimple_bb (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
836
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
837 tidx = gimple_assign_lhs (m_arr_ref_first);
111
kono
parents: 67
diff changeset
838 utype = TREE_TYPE (tidx);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
839
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
840 /* (end of) block 0 */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
841 gsi = gsi_for_stmt (m_arr_ref_first);
111
kono
parents: 67
diff changeset
842 gsi_next (&gsi);
kono
parents: 67
diff changeset
843
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
844 bound = fold_convert_loc (loc, utype, m_range_size);
111
kono
parents: 67
diff changeset
845 cond_stmt = gimple_build_cond (LE_EXPR, tidx, bound, NULL_TREE, NULL_TREE);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
846 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
847 update_stmt (cond_stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
848
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
849 /* block 2 */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
850 if (!m_default_case_nonstandard)
111
kono
parents: 67
diff changeset
851 {
kono
parents: 67
diff changeset
852 label2 = gimple_build_label (label_decl2);
kono
parents: 67
diff changeset
853 gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
854 last_assign = gen_def_assigns (&gsi);
111
kono
parents: 67
diff changeset
855 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
856
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
857 /* block 1 */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
858 label1 = gimple_build_label (label_decl1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
859 gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
860
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
861 /* block F */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
862 gsi = gsi_start_bb (m_final_bb);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
863 label3 = gimple_build_label (label_decl3);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
864 gsi_insert_before (&gsi, label3, GSI_SAME_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
865
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
866 /* cfg fix */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
867 e02 = split_block (bb0, cond_stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
868 bb2 = e02->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
869
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
870 if (m_default_case_nonstandard)
111
kono
parents: 67
diff changeset
871 {
kono
parents: 67
diff changeset
872 bb1 = bb2;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
873 bb2 = m_default_bb;
111
kono
parents: 67
diff changeset
874 e01 = e02;
kono
parents: 67
diff changeset
875 e01->flags = EDGE_TRUE_VALUE;
kono
parents: 67
diff changeset
876 e02 = make_edge (bb0, bb2, EDGE_FALSE_VALUE);
kono
parents: 67
diff changeset
877 edge e_default = find_edge (bb1, bb2);
kono
parents: 67
diff changeset
878 for (gphi_iterator gsi = gsi_start_phis (bb2);
kono
parents: 67
diff changeset
879 !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
880 {
kono
parents: 67
diff changeset
881 gphi *phi = gsi.phi ();
kono
parents: 67
diff changeset
882 tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e_default);
kono
parents: 67
diff changeset
883 add_phi_arg (phi, arg, e02,
kono
parents: 67
diff changeset
884 gimple_phi_arg_location_from_edge (phi, e_default));
kono
parents: 67
diff changeset
885 }
kono
parents: 67
diff changeset
886 /* Partially fix the dominator tree, if it is available. */
kono
parents: 67
diff changeset
887 if (dom_info_available_p (CDI_DOMINATORS))
kono
parents: 67
diff changeset
888 redirect_immediate_dominators (CDI_DOMINATORS, bb1, bb0);
kono
parents: 67
diff changeset
889 }
kono
parents: 67
diff changeset
890 else
kono
parents: 67
diff changeset
891 {
kono
parents: 67
diff changeset
892 e21 = split_block (bb2, last_assign);
kono
parents: 67
diff changeset
893 bb1 = e21->dest;
kono
parents: 67
diff changeset
894 remove_edge (e21);
kono
parents: 67
diff changeset
895 }
kono
parents: 67
diff changeset
896
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
897 e1d = split_block (bb1, m_arr_ref_last);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
898 bbd = e1d->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
899 remove_edge (e1d);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
900
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
901 /* Flags and profiles of the edge for in-range values. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
902 if (!m_default_case_nonstandard)
111
kono
parents: 67
diff changeset
903 e01 = make_edge (bb0, bb1, EDGE_TRUE_VALUE);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
904 e01->probability = m_default_prob.invert ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
905
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
906 /* Flags and profiles of the edge taking care of out-of-range values. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
907 e02->flags &= ~EDGE_FALLTHRU;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
908 e02->flags |= EDGE_FALSE_VALUE;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
909 e02->probability = m_default_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
910
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
911 bbf = m_final_bb;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
912
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
913 e1f = make_edge (bb1, bbf, EDGE_FALLTHRU);
111
kono
parents: 67
diff changeset
914 e1f->probability = profile_probability::always ();
kono
parents: 67
diff changeset
915
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
916 if (m_default_case_nonstandard)
111
kono
parents: 67
diff changeset
917 e2f = NULL;
kono
parents: 67
diff changeset
918 else
kono
parents: 67
diff changeset
919 {
kono
parents: 67
diff changeset
920 e2f = make_edge (bb2, bbf, EDGE_FALLTHRU);
kono
parents: 67
diff changeset
921 e2f->probability = profile_probability::always ();
kono
parents: 67
diff changeset
922 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
923
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
924 /* frequencies of the new BBs */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
925 bb1->count = e01->count ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
926 bb2->count = e02->count ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
927 if (!m_default_case_nonstandard)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
928 bbf->count = e1f->count () + e2f->count ();
111
kono
parents: 67
diff changeset
929
kono
parents: 67
diff changeset
930 /* Tidy blocks that have become unreachable. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
931 prune_bbs (bbd, m_final_bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
932 m_default_case_nonstandard ? m_default_bb : NULL);
111
kono
parents: 67
diff changeset
933
kono
parents: 67
diff changeset
934 /* Fixup the PHI nodes in bbF. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
935 fix_phi_nodes (e1f, e2f, bbf);
111
kono
parents: 67
diff changeset
936
kono
parents: 67
diff changeset
937 /* Fix the dominator tree, if it is available. */
kono
parents: 67
diff changeset
938 if (dom_info_available_p (CDI_DOMINATORS))
kono
parents: 67
diff changeset
939 {
kono
parents: 67
diff changeset
940 vec<basic_block> bbs_to_fix_dom;
kono
parents: 67
diff changeset
941
kono
parents: 67
diff changeset
942 set_immediate_dominator (CDI_DOMINATORS, bb1, bb0);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
943 if (!m_default_case_nonstandard)
111
kono
parents: 67
diff changeset
944 set_immediate_dominator (CDI_DOMINATORS, bb2, bb0);
kono
parents: 67
diff changeset
945 if (! get_immediate_dominator (CDI_DOMINATORS, bbf))
kono
parents: 67
diff changeset
946 /* If bbD was the immediate dominator ... */
kono
parents: 67
diff changeset
947 set_immediate_dominator (CDI_DOMINATORS, bbf, bb0);
kono
parents: 67
diff changeset
948
kono
parents: 67
diff changeset
949 bbs_to_fix_dom.create (3 + (bb2 != bbf));
kono
parents: 67
diff changeset
950 bbs_to_fix_dom.quick_push (bb0);
kono
parents: 67
diff changeset
951 bbs_to_fix_dom.quick_push (bb1);
kono
parents: 67
diff changeset
952 if (bb2 != bbf)
kono
parents: 67
diff changeset
953 bbs_to_fix_dom.quick_push (bb2);
kono
parents: 67
diff changeset
954 bbs_to_fix_dom.quick_push (bbf);
kono
parents: 67
diff changeset
955
kono
parents: 67
diff changeset
956 iterate_fix_dominators (CDI_DOMINATORS, bbs_to_fix_dom, true);
kono
parents: 67
diff changeset
957 bbs_to_fix_dom.release ();
kono
parents: 67
diff changeset
958 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
959 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
960
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
961 /* The following function is invoked on every switch statement (the current
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
962 one is given in SWTCH) and runs the individual phases of switch
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
963 conversion on it one after another until one fails or the conversion
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
964 is completed. On success, NULL is in m_reason, otherwise points
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
965 to a string with the reason why the conversion failed. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
966
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
967 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
968 switch_conversion::expand (gswitch *swtch)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
969 {
111
kono
parents: 67
diff changeset
970 /* Group case labels so that we get the right results from the heuristics
kono
parents: 67
diff changeset
971 that decide on the code generation approach for this switch. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
972 m_cfg_altered |= group_case_labels_stmt (swtch);
111
kono
parents: 67
diff changeset
973
kono
parents: 67
diff changeset
974 /* If this switch is now a degenerate case with only a default label,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
975 there is nothing left for us to do. */
111
kono
parents: 67
diff changeset
976 if (gimple_switch_num_labels (swtch) < 2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
977 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
978 m_reason = "switch is a degenerate case";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
979 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
980 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
981
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
982 collect (swtch);
111
kono
parents: 67
diff changeset
983
kono
parents: 67
diff changeset
984 /* No error markers should reach here (they should be filtered out
kono
parents: 67
diff changeset
985 during gimplification). */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
986 gcc_checking_assert (TREE_TYPE (m_index_expr) != error_mark_node);
111
kono
parents: 67
diff changeset
987
kono
parents: 67
diff changeset
988 /* A switch on a constant should have been optimized in tree-cfg-cleanup. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
989 gcc_checking_assert (!TREE_CONSTANT (m_index_expr));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
990
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
991 /* Prefer bit test if possible. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
992 if (tree_fits_uhwi_p (m_range_size)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
993 && bit_test_cluster::can_be_handled (tree_to_uhwi (m_range_size), m_uniq)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
994 && bit_test_cluster::is_beneficial (m_count, m_uniq))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
995 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
996 m_reason = "expanding as bit test is preferable";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
997 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
998 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
999
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1000 if (m_uniq <= 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1001 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1002 /* This will be expanded as a decision tree . */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1003 m_reason = "expanding as jumps is preferable";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1004 return;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1005 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1006
111
kono
parents: 67
diff changeset
1007 /* If there is no common successor, we cannot do the transformation. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1008 if (!m_final_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1009 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1010 m_reason = "no common successor to all case label target blocks found";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1011 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1012 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1013
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1014 /* Check the case label values are within reasonable range: */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1015 if (!check_range ())
111
kono
parents: 67
diff changeset
1016 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1017 gcc_assert (m_reason);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1018 return;
111
kono
parents: 67
diff changeset
1019 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1020
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1021 /* For all the cases, see whether they are empty, the assignments they
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1022 represent constant and so on... */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1023 if (!check_all_empty_except_final ())
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
1024 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1025 gcc_assert (m_reason);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1026 return;
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
1027 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1028 if (!check_final_bb ())
111
kono
parents: 67
diff changeset
1029 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1030 gcc_assert (m_reason);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1031 return;
111
kono
parents: 67
diff changeset
1032 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1033
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1034 /* At this point all checks have passed and we can proceed with the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1035 transformation. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1036
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1037 create_temp_arrays ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1038 gather_default_values (m_default_case_nonstandard
111
kono
parents: 67
diff changeset
1039 ? gimple_switch_label (swtch, 1)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1040 : gimple_switch_default_label (swtch));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1041 build_constructors ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1042
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1043 build_arrays (); /* Build the static arrays and assignments. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1044 gen_inbound_check (); /* Build the bounds check. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1045
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1046 m_cfg_altered = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1047 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1048
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1049 /* Destructor. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1050
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1051 switch_conversion::~switch_conversion ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1052 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1053 XDELETEVEC (m_constructors);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1054 XDELETEVEC (m_default_values);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1055 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1056
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1057 /* Constructor. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1058
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1059 group_cluster::group_cluster (vec<cluster *> &clusters,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1060 unsigned start, unsigned end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1061 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1062 gcc_checking_assert (end - start + 1 >= 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1063 m_prob = profile_probability::never ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1064 m_cases.create (end - start + 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1065 for (unsigned i = start; i <= end; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1066 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1067 m_cases.quick_push (static_cast<simple_cluster *> (clusters[i]));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1068 m_prob += clusters[i]->m_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1069 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1070 m_subtree_prob = m_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1071 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1072
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1073 /* Destructor. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1074
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1075 group_cluster::~group_cluster ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1076 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1077 for (unsigned i = 0; i < m_cases.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1078 delete m_cases[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1079
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1080 m_cases.release ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1081 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1082
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1083 /* Dump content of a cluster. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1084
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1085 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1086 group_cluster::dump (FILE *f, bool details)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1087 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1088 unsigned total_values = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1089 for (unsigned i = 0; i < m_cases.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1090 total_values += m_cases[i]->get_range (m_cases[i]->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1091 m_cases[i]->get_high ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1092
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1093 unsigned comparison_count = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1094 for (unsigned i = 0; i < m_cases.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1095 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1096 simple_cluster *sc = static_cast<simple_cluster *> (m_cases[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1097 comparison_count += sc->m_range_p ? 2 : 1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1098 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1099
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1100 unsigned HOST_WIDE_INT range = get_range (get_low (), get_high ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1101 fprintf (f, "%s", get_type () == JUMP_TABLE ? "JT" : "BT");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1102
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1103 if (details)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1104 fprintf (f, "(values:%d comparisons:%d range:" HOST_WIDE_INT_PRINT_DEC
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1105 " density: %.2f%%)", total_values, comparison_count, range,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1106 100.0f * comparison_count / range);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1107
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1108 fprintf (f, ":");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1109 PRINT_CASE (f, get_low ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1110 fprintf (f, "-");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1111 PRINT_CASE (f, get_high ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1112 fprintf (f, " ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1113 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1114
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1115 /* Emit GIMPLE code to handle the cluster. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1116
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1117 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1118 jump_table_cluster::emit (tree index_expr, tree,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1119 tree default_label_expr, basic_block default_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1120 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1121 unsigned HOST_WIDE_INT range = get_range (get_low (), get_high ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1122 unsigned HOST_WIDE_INT nondefault_range = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1123
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1124 /* For jump table we just emit a new gswitch statement that will
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1125 be latter lowered to jump table. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1126 auto_vec <tree> labels;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1127 labels.create (m_cases.length ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1128
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1129 make_edge (m_case_bb, default_bb, 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1130 for (unsigned i = 0; i < m_cases.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1131 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1132 labels.quick_push (unshare_expr (m_cases[i]->m_case_label_expr));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1133 make_edge (m_case_bb, m_cases[i]->m_case_bb, 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1134 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1135
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1136 gswitch *s = gimple_build_switch (index_expr,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1137 unshare_expr (default_label_expr), labels);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1138 gimple_stmt_iterator gsi = gsi_start_bb (m_case_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1139 gsi_insert_after (&gsi, s, GSI_NEW_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1140
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1141 /* Set up even probabilities for all cases. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1142 for (unsigned i = 0; i < m_cases.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1143 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1144 simple_cluster *sc = static_cast<simple_cluster *> (m_cases[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1145 edge case_edge = find_edge (m_case_bb, sc->m_case_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1146 unsigned HOST_WIDE_INT case_range
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1147 = sc->get_range (sc->get_low (), sc->get_high ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1148 nondefault_range += case_range;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1149
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1150 /* case_edge->aux is number of values in a jump-table that are covered
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1151 by the case_edge. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1152 case_edge->aux = (void *) ((intptr_t) (case_edge->aux) + case_range);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1153 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1154
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1155 edge default_edge = gimple_switch_default_edge (cfun, s);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1156 default_edge->probability = profile_probability::never ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1157
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1158 for (unsigned i = 0; i < m_cases.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1159 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1160 simple_cluster *sc = static_cast<simple_cluster *> (m_cases[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1161 edge case_edge = find_edge (m_case_bb, sc->m_case_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1162 case_edge->probability
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1163 = profile_probability::always ().apply_scale ((intptr_t)case_edge->aux,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1164 range);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1165 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1166
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1167 /* Number of non-default values is probability of default edge. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1168 default_edge->probability
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1169 += profile_probability::always ().apply_scale (nondefault_range,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1170 range).invert ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1171
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1172 switch_decision_tree::reset_out_edges_aux (s);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1173 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1174
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1175 /* Find jump tables of given CLUSTERS, where all members of the vector
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1176 are of type simple_cluster. New clusters are returned. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1177
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1178 vec<cluster *>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1179 jump_table_cluster::find_jump_tables (vec<cluster *> &clusters)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1180 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1181 if (!is_enabled ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1182 return clusters.copy ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1183
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1184 unsigned l = clusters.length ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1185 auto_vec<min_cluster_item> min;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1186 min.reserve (l + 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1187
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1188 min.quick_push (min_cluster_item (0, 0, 0));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1189
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1190 for (unsigned i = 1; i <= l; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1191 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1192 /* Set minimal # of clusters with i-th item to infinite. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1193 min.quick_push (min_cluster_item (INT_MAX, INT_MAX, INT_MAX));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1194
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1195 for (unsigned j = 0; j < i; j++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1196 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1197 unsigned HOST_WIDE_INT s = min[j].m_non_jt_cases;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1198 if (i - j < case_values_threshold ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1199 s += i - j;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1200
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1201 /* Prefer clusters with smaller number of numbers covered. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1202 if ((min[j].m_count + 1 < min[i].m_count
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1203 || (min[j].m_count + 1 == min[i].m_count
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1204 && s < min[i].m_non_jt_cases))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1205 && can_be_handled (clusters, j, i - 1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1206 min[i] = min_cluster_item (min[j].m_count + 1, j, s);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1207 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1208
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1209 gcc_checking_assert (min[i].m_count != INT_MAX);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1210 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1211
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1212 /* No result. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1213 if (min[l].m_count == INT_MAX)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1214 return clusters.copy ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1215
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1216 vec<cluster *> output;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1217 output.create (4);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1218
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1219 /* Find and build the clusters. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1220 for (int end = l;;)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1221 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1222 int start = min[end].m_start;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1223
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1224 /* Do not allow clusters with small number of cases. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1225 if (is_beneficial (clusters, start, end - 1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1226 output.safe_push (new jump_table_cluster (clusters, start, end - 1));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1227 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1228 for (int i = end - 1; i >= start; i--)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1229 output.safe_push (clusters[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1230
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1231 end = start;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1232
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1233 if (start <= 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1234 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1235 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1236
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1237 output.reverse ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1238 return output;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1239 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1240
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1241 /* Return true when cluster starting at START and ending at END (inclusive)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1242 can build a jump-table. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1243
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1244 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1245 jump_table_cluster::can_be_handled (const vec<cluster *> &clusters,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1246 unsigned start, unsigned end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1247 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1248 /* If the switch is relatively small such that the cost of one
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1249 indirect jump on the target are higher than the cost of a
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1250 decision tree, go with the decision tree.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1251
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1252 If range of values is much bigger than number of values,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1253 or if it is too large to represent in a HOST_WIDE_INT,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1254 make a sequence of conditional branches instead of a dispatch.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1255
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1256 The definition of "much bigger" depends on whether we are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1257 optimizing for size or for speed. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1258 if (!flag_jump_tables)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1259 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1260
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1261 /* For algorithm correctness, jump table for a single case must return
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1262 true. We bail out in is_beneficial if it's called just for
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1263 a single case. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1264 if (start == end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1265 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1266
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1267 unsigned HOST_WIDE_INT max_ratio
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1268 = optimize_insn_for_size_p () ? max_ratio_for_size : max_ratio_for_speed;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1269 unsigned HOST_WIDE_INT range = get_range (clusters[start]->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1270 clusters[end]->get_high ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1271 /* Check overflow. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1272 if (range == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1273 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1274
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1275 unsigned HOST_WIDE_INT comparison_count = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1276 for (unsigned i = start; i <= end; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1277 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1278 simple_cluster *sc = static_cast<simple_cluster *> (clusters[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1279 comparison_count += sc->m_range_p ? 2 : 1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1280 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1281
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1282 return range <= max_ratio * comparison_count;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1283 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1284
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1285 /* Return true if cluster starting at START and ending at END (inclusive)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1286 is profitable transformation. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1287
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1288 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1289 jump_table_cluster::is_beneficial (const vec<cluster *> &,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1290 unsigned start, unsigned end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1291 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1292 /* Single case bail out. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1293 if (start == end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1294 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1295
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1296 return end - start + 1 >= case_values_threshold ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1297 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1298
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1299 /* Definition of jump_table_cluster constants. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1300
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1301 const unsigned HOST_WIDE_INT jump_table_cluster::max_ratio_for_size;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1302 const unsigned HOST_WIDE_INT jump_table_cluster::max_ratio_for_speed;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1303
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1304 /* Find bit tests of given CLUSTERS, where all members of the vector
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1305 are of type simple_cluster. New clusters are returned. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1306
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1307 vec<cluster *>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1308 bit_test_cluster::find_bit_tests (vec<cluster *> &clusters)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1309 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1310 vec<cluster *> output;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1311 output.create (4);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1312
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1313 unsigned l = clusters.length ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1314 auto_vec<min_cluster_item> min;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1315 min.reserve (l + 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1316
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1317 min.quick_push (min_cluster_item (0, 0, 0));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1318
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1319 for (unsigned i = 1; i <= l; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1320 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1321 /* Set minimal # of clusters with i-th item to infinite. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1322 min.quick_push (min_cluster_item (INT_MAX, INT_MAX, INT_MAX));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1323
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1324 for (unsigned j = 0; j < i; j++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1325 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1326 if (min[j].m_count + 1 < min[i].m_count
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1327 && can_be_handled (clusters, j, i - 1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1328 min[i] = min_cluster_item (min[j].m_count + 1, j, INT_MAX);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1329 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1330
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1331 gcc_checking_assert (min[i].m_count != INT_MAX);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1332 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1333
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1334 /* No result. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1335 if (min[l].m_count == INT_MAX)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1336 return clusters.copy ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1337
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1338 /* Find and build the clusters. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1339 for (unsigned end = l;;)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1340 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1341 int start = min[end].m_start;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1342
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1343 if (is_beneficial (clusters, start, end - 1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1344 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1345 bool entire = start == 0 && end == clusters.length ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1346 output.safe_push (new bit_test_cluster (clusters, start, end - 1,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1347 entire));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1348 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1349 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1350 for (int i = end - 1; i >= start; i--)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1351 output.safe_push (clusters[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1352
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1353 end = start;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1354
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1355 if (start <= 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1356 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1357 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1358
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1359 output.reverse ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1360 return output;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1361 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1362
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1363 /* Return true when RANGE of case values with UNIQ labels
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1364 can build a bit test. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1365
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1366 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1367 bit_test_cluster::can_be_handled (unsigned HOST_WIDE_INT range,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1368 unsigned int uniq)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1369 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1370 /* Check overflow. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1371 if (range == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1372 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1373
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1374 if (range >= GET_MODE_BITSIZE (word_mode))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1375 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1376
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1377 return uniq <= 3;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1378 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1379
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1380 /* Return true when cluster starting at START and ending at END (inclusive)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1381 can build a bit test. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1382
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1383 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1384 bit_test_cluster::can_be_handled (const vec<cluster *> &clusters,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1385 unsigned start, unsigned end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1386 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1387 /* For algorithm correctness, bit test for a single case must return
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1388 true. We bail out in is_beneficial if it's called just for
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1389 a single case. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1390 if (start == end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1391 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1392
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1393 unsigned HOST_WIDE_INT range = get_range (clusters[start]->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1394 clusters[end]->get_high ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1395 auto_bitmap dest_bbs;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1396
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1397 for (unsigned i = start; i <= end; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1398 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1399 simple_cluster *sc = static_cast<simple_cluster *> (clusters[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1400 bitmap_set_bit (dest_bbs, sc->m_case_bb->index);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1401 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1402
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1403 return can_be_handled (range, bitmap_count_bits (dest_bbs));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1404 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1405
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1406 /* Return true when COUNT of cases of UNIQ labels is beneficial for bit test
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1407 transformation. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1408
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1409 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1410 bit_test_cluster::is_beneficial (unsigned count, unsigned uniq)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1411 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1412 return (((uniq == 1 && count >= 3)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1413 || (uniq == 2 && count >= 5)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1414 || (uniq == 3 && count >= 6)));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1415 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1416
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1417 /* Return true if cluster starting at START and ending at END (inclusive)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1418 is profitable transformation. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1419
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1420 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1421 bit_test_cluster::is_beneficial (const vec<cluster *> &clusters,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1422 unsigned start, unsigned end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1423 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1424 /* Single case bail out. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1425 if (start == end)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1426 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1427
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1428 auto_bitmap dest_bbs;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1429
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1430 for (unsigned i = start; i <= end; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1431 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1432 simple_cluster *sc = static_cast<simple_cluster *> (clusters[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1433 bitmap_set_bit (dest_bbs, sc->m_case_bb->index);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1434 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1435
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1436 unsigned uniq = bitmap_count_bits (dest_bbs);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1437 unsigned count = end - start + 1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1438 return is_beneficial (count, uniq);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1439 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1440
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1441 /* Comparison function for qsort to order bit tests by decreasing
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1442 probability of execution. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1443
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1444 int
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1445 case_bit_test::cmp (const void *p1, const void *p2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1446 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1447 const struct case_bit_test *const d1 = (const struct case_bit_test *) p1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1448 const struct case_bit_test *const d2 = (const struct case_bit_test *) p2;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1449
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1450 if (d2->bits != d1->bits)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1451 return d2->bits - d1->bits;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1452
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1453 /* Stabilize the sort. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1454 return (LABEL_DECL_UID (CASE_LABEL (d2->label))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1455 - LABEL_DECL_UID (CASE_LABEL (d1->label)));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1456 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1457
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1458 /* Expand a switch statement by a short sequence of bit-wise
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1459 comparisons. "switch(x)" is effectively converted into
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1460 "if ((1 << (x-MINVAL)) & CST)" where CST and MINVAL are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1461 integer constants.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1462
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1463 INDEX_EXPR is the value being switched on.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1464
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1465 MINVAL is the lowest case value of in the case nodes,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1466 and RANGE is highest value minus MINVAL. MINVAL and RANGE
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1467 are not guaranteed to be of the same type as INDEX_EXPR
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1468 (the gimplifier doesn't change the type of case label values,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1469 and MINVAL and RANGE are derived from those values).
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1470 MAXVAL is MINVAL + RANGE.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1471
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1472 There *MUST* be max_case_bit_tests or less unique case
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1473 node targets. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1474
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1475 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1476 bit_test_cluster::emit (tree index_expr, tree index_type,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1477 tree, basic_block default_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1478 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1479 struct case_bit_test test[m_max_case_bit_tests] = { {} };
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1480 unsigned int i, j, k;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1481 unsigned int count;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1482
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1483 tree unsigned_index_type = unsigned_type_for (index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1484
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1485 gimple_stmt_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1486 gassign *shift_stmt;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1487
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1488 tree idx, tmp, csui;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1489 tree word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1490 tree word_mode_zero = fold_convert (word_type_node, integer_zero_node);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1491 tree word_mode_one = fold_convert (word_type_node, integer_one_node);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1492 int prec = TYPE_PRECISION (word_type_node);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1493 wide_int wone = wi::one (prec);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1494
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1495 tree minval = get_low ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1496 tree maxval = get_high ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1497 tree range = int_const_binop (MINUS_EXPR, maxval, minval);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1498 unsigned HOST_WIDE_INT bt_range = get_range (minval, maxval);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1499
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1500 /* Go through all case labels, and collect the case labels, profile
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1501 counts, and other information we need to build the branch tests. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1502 count = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1503 for (i = 0; i < m_cases.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1504 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1505 unsigned int lo, hi;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1506 simple_cluster *n = static_cast<simple_cluster *> (m_cases[i]);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1507 for (k = 0; k < count; k++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1508 if (n->m_case_bb == test[k].target_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1509 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1510
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1511 if (k == count)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1512 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1513 gcc_checking_assert (count < m_max_case_bit_tests);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1514 test[k].mask = wi::zero (prec);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1515 test[k].target_bb = n->m_case_bb;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1516 test[k].label = n->m_case_label_expr;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1517 test[k].bits = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1518 count++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1519 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1520
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1521 test[k].bits += n->get_range (n->get_low (), n->get_high ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1522
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1523 lo = tree_to_uhwi (int_const_binop (MINUS_EXPR, n->get_low (), minval));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1524 if (n->get_high () == NULL_TREE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1525 hi = lo;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1526 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1527 hi = tree_to_uhwi (int_const_binop (MINUS_EXPR, n->get_high (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1528 minval));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1529
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1530 for (j = lo; j <= hi; j++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1531 test[k].mask |= wi::lshift (wone, j);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1532 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1533
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1534 qsort (test, count, sizeof (*test), case_bit_test::cmp);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1535
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1536 /* If all values are in the 0 .. BITS_PER_WORD-1 range, we can get rid of
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1537 the minval subtractions, but it might make the mask constants more
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1538 expensive. So, compare the costs. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1539 if (compare_tree_int (minval, 0) > 0
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1540 && compare_tree_int (maxval, GET_MODE_BITSIZE (word_mode)) < 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1541 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1542 int cost_diff;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1543 HOST_WIDE_INT m = tree_to_uhwi (minval);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1544 rtx reg = gen_raw_REG (word_mode, 10000);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1545 bool speed_p = optimize_insn_for_speed_p ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1546 cost_diff = set_rtx_cost (gen_rtx_PLUS (word_mode, reg,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1547 GEN_INT (-m)), speed_p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1548 for (i = 0; i < count; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1549 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1550 rtx r = immed_wide_int_const (test[i].mask, word_mode);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1551 cost_diff += set_src_cost (gen_rtx_AND (word_mode, reg, r),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1552 word_mode, speed_p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1553 r = immed_wide_int_const (wi::lshift (test[i].mask, m), word_mode);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1554 cost_diff -= set_src_cost (gen_rtx_AND (word_mode, reg, r),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1555 word_mode, speed_p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1556 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1557 if (cost_diff > 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1558 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1559 for (i = 0; i < count; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1560 test[i].mask = wi::lshift (test[i].mask, m);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1561 minval = build_zero_cst (TREE_TYPE (minval));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1562 range = maxval;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1563 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1564 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1565
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1566 /* Now build the test-and-branch code. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1567
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1568 gsi = gsi_last_bb (m_case_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1569
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1570 /* idx = (unsigned)x - minval. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1571 idx = fold_convert (unsigned_index_type, index_expr);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1572 idx = fold_build2 (MINUS_EXPR, unsigned_index_type, idx,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1573 fold_convert (unsigned_index_type, minval));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1574 idx = force_gimple_operand_gsi (&gsi, idx,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1575 /*simple=*/true, NULL_TREE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1576 /*before=*/true, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1577
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1578 if (m_handles_entire_switch)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1579 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1580 /* if (idx > range) goto default */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1581 range
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1582 = force_gimple_operand_gsi (&gsi,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1583 fold_convert (unsigned_index_type, range),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1584 /*simple=*/true, NULL_TREE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1585 /*before=*/true, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1586 tmp = fold_build2 (GT_EXPR, boolean_type_node, idx, range);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1587 basic_block new_bb
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1588 = hoist_edge_and_branch_if_true (&gsi, tmp, default_bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1589 profile_probability::unlikely ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1590 gsi = gsi_last_bb (new_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1591 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1592
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1593 /* csui = (1 << (word_mode) idx) */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1594 csui = make_ssa_name (word_type_node);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1595 tmp = fold_build2 (LSHIFT_EXPR, word_type_node, word_mode_one,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1596 fold_convert (word_type_node, idx));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1597 tmp = force_gimple_operand_gsi (&gsi, tmp,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1598 /*simple=*/false, NULL_TREE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1599 /*before=*/true, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1600 shift_stmt = gimple_build_assign (csui, tmp);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1601 gsi_insert_before (&gsi, shift_stmt, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1602 update_stmt (shift_stmt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1603
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1604 profile_probability prob = profile_probability::always ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1605
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1606 /* for each unique set of cases:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1607 if (const & csui) goto target */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1608 for (k = 0; k < count; k++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1609 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1610 prob = profile_probability::always ().apply_scale (test[k].bits,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1611 bt_range);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1612 bt_range -= test[k].bits;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1613 tmp = wide_int_to_tree (word_type_node, test[k].mask);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1614 tmp = fold_build2 (BIT_AND_EXPR, word_type_node, csui, tmp);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1615 tmp = force_gimple_operand_gsi (&gsi, tmp,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1616 /*simple=*/true, NULL_TREE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1617 /*before=*/true, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1618 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, word_mode_zero);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1619 basic_block new_bb
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1620 = hoist_edge_and_branch_if_true (&gsi, tmp, test[k].target_bb, prob);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1621 gsi = gsi_last_bb (new_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1622 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1623
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1624 /* We should have removed all edges now. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1625 gcc_assert (EDGE_COUNT (gsi_bb (gsi)->succs) == 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1626
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1627 /* If nothing matched, go to the default label. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1628 edge e = make_edge (gsi_bb (gsi), default_bb, EDGE_FALLTHRU);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1629 e->probability = profile_probability::always ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1630 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1631
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1632 /* Split the basic block at the statement pointed to by GSIP, and insert
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1633 a branch to the target basic block of E_TRUE conditional on tree
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1634 expression COND.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1635
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1636 It is assumed that there is already an edge from the to-be-split
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1637 basic block to E_TRUE->dest block. This edge is removed, and the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1638 profile information on the edge is re-used for the new conditional
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1639 jump.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1640
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1641 The CFG is updated. The dominator tree will not be valid after
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1642 this transformation, but the immediate dominators are updated if
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1643 UPDATE_DOMINATORS is true.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1644
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1645 Returns the newly created basic block. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1646
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1647 basic_block
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1648 bit_test_cluster::hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1649 tree cond, basic_block case_bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1650 profile_probability prob)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1651 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1652 tree tmp;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1653 gcond *cond_stmt;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1654 edge e_false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1655 basic_block new_bb, split_bb = gsi_bb (*gsip);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1656
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1657 edge e_true = make_edge (split_bb, case_bb, EDGE_TRUE_VALUE);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1658 e_true->probability = prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1659 gcc_assert (e_true->src == split_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1660
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1661 tmp = force_gimple_operand_gsi (gsip, cond, /*simple=*/true, NULL,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1662 /*before=*/true, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1663 cond_stmt = gimple_build_cond_from_tree (tmp, NULL_TREE, NULL_TREE);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1664 gsi_insert_before (gsip, cond_stmt, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1665
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1666 e_false = split_block (split_bb, cond_stmt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1667 new_bb = e_false->dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1668 redirect_edge_pred (e_true, split_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1669
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1670 e_false->flags &= ~EDGE_FALLTHRU;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1671 e_false->flags |= EDGE_FALSE_VALUE;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1672 e_false->probability = e_true->probability.invert ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1673 new_bb->count = e_false->count ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1674
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1675 return new_bb;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1676 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1677
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1678 /* Compute the number of case labels that correspond to each outgoing edge of
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1679 switch statement. Record this information in the aux field of the edge. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1680
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1681 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1682 switch_decision_tree::compute_cases_per_edge ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1683 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1684 reset_out_edges_aux (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1685 int ncases = gimple_switch_num_labels (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1686 for (int i = ncases - 1; i >= 1; --i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1687 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1688 edge case_edge = gimple_switch_edge (cfun, m_switch, i);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1689 case_edge->aux = (void *) ((intptr_t) (case_edge->aux) + 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1690 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1691 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1692
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1693 /* Analyze switch statement and return true when the statement is expanded
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1694 as decision tree. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1695
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1696 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1697 switch_decision_tree::analyze_switch_statement ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1698 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1699 unsigned l = gimple_switch_num_labels (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1700 basic_block bb = gimple_bb (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1701 auto_vec<cluster *> clusters;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1702 clusters.create (l - 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1703
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1704 basic_block default_bb = gimple_switch_default_bb (cfun, m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1705 m_case_bbs.reserve (l);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1706 m_case_bbs.quick_push (default_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1707
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1708 compute_cases_per_edge ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1709
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1710 for (unsigned i = 1; i < l; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1711 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1712 tree elt = gimple_switch_label (m_switch, i);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1713 tree lab = CASE_LABEL (elt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1714 basic_block case_bb = label_to_block (cfun, lab);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1715 edge case_edge = find_edge (bb, case_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1716 tree low = CASE_LOW (elt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1717 tree high = CASE_HIGH (elt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1718
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1719 profile_probability p
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1720 = case_edge->probability.apply_scale (1, (intptr_t) (case_edge->aux));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1721 clusters.quick_push (new simple_cluster (low, high, elt, case_edge->dest,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1722 p));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1723 m_case_bbs.quick_push (case_edge->dest);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1724 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1725
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1726 reset_out_edges_aux (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1727
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1728 /* Find jump table clusters. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1729 vec<cluster *> output = jump_table_cluster::find_jump_tables (clusters);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1730
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1731 /* Find bit test clusters. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1732 vec<cluster *> output2;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1733 auto_vec<cluster *> tmp;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1734 output2.create (1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1735 tmp.create (1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1736
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1737 for (unsigned i = 0; i < output.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1738 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1739 cluster *c = output[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1740 if (c->get_type () != SIMPLE_CASE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1741 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1742 if (!tmp.is_empty ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1743 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1744 vec<cluster *> n = bit_test_cluster::find_bit_tests (tmp);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1745 output2.safe_splice (n);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1746 n.release ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1747 tmp.truncate (0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1748 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1749 output2.safe_push (c);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1750 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1751 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1752 tmp.safe_push (c);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1753 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1754
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1755 /* We still can have a temporary vector to test. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1756 if (!tmp.is_empty ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1757 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1758 vec<cluster *> n = bit_test_cluster::find_bit_tests (tmp);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1759 output2.safe_splice (n);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1760 n.release ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1761 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1762
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1763 if (dump_file)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1764 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1765 fprintf (dump_file, ";; GIMPLE switch case clusters: ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1766 for (unsigned i = 0; i < output2.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1767 output2[i]->dump (dump_file, dump_flags & TDF_DETAILS);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1768 fprintf (dump_file, "\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1769 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1770
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1771 output.release ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1772
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1773 bool expanded = try_switch_expansion (output2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1774
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1775 for (unsigned i = 0; i < output2.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1776 delete output2[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1777
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1778 output2.release ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1779
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1780 return expanded;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1781 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1782
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1783 /* Attempt to expand CLUSTERS as a decision tree. Return true when
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1784 expanded. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1785
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1786 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1787 switch_decision_tree::try_switch_expansion (vec<cluster *> &clusters)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1788 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1789 tree index_expr = gimple_switch_index (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1790 tree index_type = TREE_TYPE (index_expr);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1791 basic_block bb = gimple_bb (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1792
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1793 if (gimple_switch_num_labels (m_switch) == 1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1794 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1795
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1796 /* Find the default case target label. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1797 edge default_edge = gimple_switch_default_edge (cfun, m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1798 m_default_bb = default_edge->dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1799
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1800 /* Do the insertion of a case label into m_case_list. The labels are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1801 fed to us in descending order from the sorted vector of case labels used
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1802 in the tree part of the middle end. So the list we construct is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1803 sorted in ascending order. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1804
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1805 for (int i = clusters.length () - 1; i >= 0; i--)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1806 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1807 case_tree_node *r = m_case_list;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1808 m_case_list = m_case_node_pool.allocate ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1809 m_case_list->m_right = r;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1810 m_case_list->m_c = clusters[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1811 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1812
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1813 record_phi_operand_mapping ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1814
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1815 /* Split basic block that contains the gswitch statement. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1816 gimple_stmt_iterator gsi = gsi_last_bb (bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1817 edge e;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1818 if (gsi_end_p (gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1819 e = split_block_after_labels (bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1820 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1821 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1822 gsi_prev (&gsi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1823 e = split_block (bb, gsi_stmt (gsi));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1824 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1825 bb = split_edge (e);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1826
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1827 /* Create new basic blocks for non-case clusters where specific expansion
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1828 needs to happen. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1829 for (unsigned i = 0; i < clusters.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1830 if (clusters[i]->get_type () != SIMPLE_CASE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1831 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1832 clusters[i]->m_case_bb = create_empty_bb (bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1833 clusters[i]->m_case_bb->loop_father = bb->loop_father;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1834 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1835
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1836 /* Do not do an extra work for a single cluster. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1837 if (clusters.length () == 1
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1838 && clusters[0]->get_type () != SIMPLE_CASE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1839 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1840 cluster *c = clusters[0];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1841 c->emit (index_expr, index_type,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1842 gimple_switch_default_label (m_switch), m_default_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1843 redirect_edge_succ (single_succ_edge (bb), c->m_case_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1844 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1845 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1846 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1847 emit (bb, index_expr, default_edge->probability, index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1848
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1849 /* Emit cluster-specific switch handling. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1850 for (unsigned i = 0; i < clusters.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1851 if (clusters[i]->get_type () != SIMPLE_CASE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1852 clusters[i]->emit (index_expr, index_type,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1853 gimple_switch_default_label (m_switch),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1854 m_default_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1855 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1856
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1857 fix_phi_operands_for_edges ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1858
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1859 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1860 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1861
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1862 /* Before switch transformation, record all SSA_NAMEs defined in switch BB
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1863 and used in a label basic block. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1864
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1865 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1866 switch_decision_tree::record_phi_operand_mapping ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1867 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1868 basic_block switch_bb = gimple_bb (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1869 /* Record all PHI nodes that have to be fixed after conversion. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1870 for (unsigned i = 0; i < m_case_bbs.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1871 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1872 gphi_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1873 basic_block bb = m_case_bbs[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1874 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1875 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1876 gphi *phi = gsi.phi ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1877
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1878 for (unsigned i = 0; i < gimple_phi_num_args (phi); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1879 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1880 basic_block phi_src_bb = gimple_phi_arg_edge (phi, i)->src;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1881 if (phi_src_bb == switch_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1882 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1883 tree def = gimple_phi_arg_def (phi, i);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1884 tree result = gimple_phi_result (phi);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1885 m_phi_mapping.put (result, def);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1886 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1887 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1888 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1889 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1890 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1891 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1892
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1893 /* Append new operands to PHI statements that were introduced due to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1894 addition of new edges to case labels. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1895
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1896 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1897 switch_decision_tree::fix_phi_operands_for_edges ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1898 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1899 gphi_iterator gsi;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1900
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1901 for (unsigned i = 0; i < m_case_bbs.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1902 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1903 basic_block bb = m_case_bbs[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1904 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1905 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1906 gphi *phi = gsi.phi ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1907 for (unsigned j = 0; j < gimple_phi_num_args (phi); j++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1908 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1909 tree def = gimple_phi_arg_def (phi, j);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1910 if (def == NULL_TREE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1911 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1912 edge e = gimple_phi_arg_edge (phi, j);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1913 tree *definition
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1914 = m_phi_mapping.get (gimple_phi_result (phi));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1915 gcc_assert (definition);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1916 add_phi_arg (phi, *definition, e, UNKNOWN_LOCATION);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1917 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1918 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1919 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1920 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1921 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1922
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1923 /* Generate a decision tree, switching on INDEX_EXPR and jumping to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1924 one of the labels in CASE_LIST or to the DEFAULT_LABEL.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1925
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1926 We generate a binary decision tree to select the appropriate target
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1927 code. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1928
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1929 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1930 switch_decision_tree::emit (basic_block bb, tree index_expr,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1931 profile_probability default_prob, tree index_type)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1932 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1933 balance_case_nodes (&m_case_list, NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1934
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1935 if (dump_file)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1936 dump_function_to_file (current_function_decl, dump_file, dump_flags);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1937 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1938 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1939 int indent_step = ceil_log2 (TYPE_PRECISION (index_type)) + 2;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1940 fprintf (dump_file, ";; Expanding GIMPLE switch as decision tree:\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1941 gcc_assert (m_case_list != NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1942 dump_case_nodes (dump_file, m_case_list, indent_step, 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1943 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1944
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1945 bb = emit_case_nodes (bb, index_expr, m_case_list, default_prob, index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1946
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1947 if (bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1948 emit_jump (bb, m_default_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1949
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1950 /* Remove all edges and do just an edge that will reach default_bb. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1951 bb = gimple_bb (m_switch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1952 gimple_stmt_iterator gsi = gsi_last_bb (bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1953 gsi_remove (&gsi, true);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1954
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1955 delete_basic_block (bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1956 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1957
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1958 /* Take an ordered list of case nodes
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1959 and transform them into a near optimal binary tree,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1960 on the assumption that any target code selection value is as
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1961 likely as any other.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1962
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1963 The transformation is performed by splitting the ordered
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1964 list into two equal sections plus a pivot. The parts are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1965 then attached to the pivot as left and right branches. Each
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1966 branch is then transformed recursively. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1967
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1968 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1969 switch_decision_tree::balance_case_nodes (case_tree_node **head,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1970 case_tree_node *parent)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1971 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1972 case_tree_node *np;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1973
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1974 np = *head;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1975 if (np)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1976 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1977 int i = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1978 int ranges = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1979 case_tree_node **npp;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1980 case_tree_node *left;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1981 profile_probability prob = profile_probability::never ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1982
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1983 /* Count the number of entries on branch. Also count the ranges. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1984
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1985 while (np)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1986 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1987 if (!tree_int_cst_equal (np->m_c->get_low (), np->m_c->get_high ()))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1988 ranges++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1989
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1990 i++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1991 prob += np->m_c->m_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1992 np = np->m_right;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1993 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1994
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1995 if (i > 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1996 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1997 /* Split this list if it is long enough for that to help. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1998 npp = head;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1999 left = *npp;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2000 profile_probability pivot_prob = prob.apply_scale (1, 2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2001
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2002 /* Find the place in the list that bisects the list's total cost,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2003 where ranges count as 2. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2004 while (1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2005 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2006 /* Skip nodes while their probability does not reach
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2007 that amount. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2008 prob -= (*npp)->m_c->m_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2009 if ((prob.initialized_p () && prob < pivot_prob)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2010 || ! (*npp)->m_right)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2011 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2012 npp = &(*npp)->m_right;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2013 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2014
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2015 np = *npp;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2016 *npp = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2017 *head = np;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2018 np->m_parent = parent;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2019 np->m_left = left == np ? NULL : left;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2020
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2021 /* Optimize each of the two split parts. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2022 balance_case_nodes (&np->m_left, np);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2023 balance_case_nodes (&np->m_right, np);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2024 np->m_c->m_subtree_prob = np->m_c->m_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2025 if (np->m_left)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2026 np->m_c->m_subtree_prob += np->m_left->m_c->m_subtree_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2027 if (np->m_right)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2028 np->m_c->m_subtree_prob += np->m_right->m_c->m_subtree_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2029 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2030 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2031 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2032 /* Else leave this branch as one level,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2033 but fill in `parent' fields. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2034 np = *head;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2035 np->m_parent = parent;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2036 np->m_c->m_subtree_prob = np->m_c->m_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2037 for (; np->m_right; np = np->m_right)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2038 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2039 np->m_right->m_parent = np;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2040 (*head)->m_c->m_subtree_prob += np->m_right->m_c->m_subtree_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2041 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2042 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2043 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2044 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2045
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2046 /* Dump ROOT, a list or tree of case nodes, to file. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2047
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2048 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2049 switch_decision_tree::dump_case_nodes (FILE *f, case_tree_node *root,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2050 int indent_step, int indent_level)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2051 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2052 if (root == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2053 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2054 indent_level++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2055
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2056 dump_case_nodes (f, root->m_left, indent_step, indent_level);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2057
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2058 fputs (";; ", f);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2059 fprintf (f, "%*s", indent_step * indent_level, "");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2060 root->m_c->dump (f);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2061 root->m_c->m_prob.dump (f);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2062 fputs (" subtree: ", f);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2063 root->m_c->m_subtree_prob.dump (f);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2064 fputs (")\n", f);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2065
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2066 dump_case_nodes (f, root->m_right, indent_step, indent_level);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2067 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2068
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2069
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2070 /* Add an unconditional jump to CASE_BB that happens in basic block BB. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2071
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2072 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2073 switch_decision_tree::emit_jump (basic_block bb, basic_block case_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2074 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2075 edge e = single_succ_edge (bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2076 redirect_edge_succ (e, case_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2077 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2078
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2079 /* Generate code to compare OP0 with OP1 so that the condition codes are
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2080 set and to jump to LABEL_BB if the condition is true.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2081 COMPARISON is the GIMPLE comparison (EQ, NE, GT, etc.).
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2082 PROB is the probability of jumping to LABEL_BB. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2083
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2084 basic_block
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2085 switch_decision_tree::emit_cmp_and_jump_insns (basic_block bb, tree op0,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2086 tree op1, tree_code comparison,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2087 basic_block label_bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2088 profile_probability prob)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2089 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2090 // TODO: it's once called with lhs != index.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2091 op1 = fold_convert (TREE_TYPE (op0), op1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2092
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2093 gcond *cond = gimple_build_cond (comparison, op0, op1, NULL_TREE, NULL_TREE);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2094 gimple_stmt_iterator gsi = gsi_last_bb (bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2095 gsi_insert_after (&gsi, cond, GSI_NEW_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2096
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2097 gcc_assert (single_succ_p (bb));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2098
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2099 /* Make a new basic block where false branch will take place. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2100 edge false_edge = split_block (bb, cond);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2101 false_edge->flags = EDGE_FALSE_VALUE;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2102 false_edge->probability = prob.invert ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2103
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2104 edge true_edge = make_edge (bb, label_bb, EDGE_TRUE_VALUE);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2105 true_edge->probability = prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2106
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2107 return false_edge->dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2108 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2109
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2110 /* Generate code to jump to LABEL if OP0 and OP1 are equal.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2111 PROB is the probability of jumping to LABEL_BB.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2112 BB is a basic block where the new condition will be placed. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2113
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2114 basic_block
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2115 switch_decision_tree::do_jump_if_equal (basic_block bb, tree op0, tree op1,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2116 basic_block label_bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2117 profile_probability prob)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2118 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2119 op1 = fold_convert (TREE_TYPE (op0), op1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2120
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2121 gcond *cond = gimple_build_cond (EQ_EXPR, op0, op1, NULL_TREE, NULL_TREE);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2122 gimple_stmt_iterator gsi = gsi_last_bb (bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2123 gsi_insert_before (&gsi, cond, GSI_SAME_STMT);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2124
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2125 gcc_assert (single_succ_p (bb));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2126
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2127 /* Make a new basic block where false branch will take place. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2128 edge false_edge = split_block (bb, cond);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2129 false_edge->flags = EDGE_FALSE_VALUE;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2130 false_edge->probability = prob.invert ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2132 edge true_edge = make_edge (bb, label_bb, EDGE_TRUE_VALUE);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2133 true_edge->probability = prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2134
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2135 return false_edge->dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2136 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2137
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2138 /* Emit step-by-step code to select a case for the value of INDEX.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2139 The thus generated decision tree follows the form of the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2140 case-node binary tree NODE, whose nodes represent test conditions.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2141 DEFAULT_PROB is probability of cases leading to default BB.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2142 INDEX_TYPE is the type of the index of the switch. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2143
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2144 basic_block
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2145 switch_decision_tree::emit_case_nodes (basic_block bb, tree index,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2146 case_tree_node *node,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2147 profile_probability default_prob,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2148 tree index_type)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2149 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2150 profile_probability p;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2151
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2152 /* If node is null, we are done. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2153 if (node == NULL)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2154 return bb;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2155
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2156 /* Single value case. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2157 if (node->m_c->is_single_value_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2158 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2159 /* Node is single valued. First see if the index expression matches
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2160 this node and then check our children, if any. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2161 p = node->m_c->m_prob / (node->m_c->m_subtree_prob + default_prob);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2162 bb = do_jump_if_equal (bb, index, node->m_c->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2163 node->m_c->m_case_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2164 /* Since this case is taken at this point, reduce its weight from
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2165 subtree_weight. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2166 node->m_c->m_subtree_prob -= p;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2167
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2168 if (node->m_left != NULL && node->m_right != NULL)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2169 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2170 /* 1) the node has both children
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2171
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2172 If both children are single-valued cases with no
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2173 children, finish up all the work. This way, we can save
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2174 one ordered comparison. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2175
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2176 if (!node->m_left->has_child ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2177 && node->m_left->m_c->is_single_value_p ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2178 && !node->m_right->has_child ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2179 && node->m_right->m_c->is_single_value_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2180 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2181 p = (node->m_right->m_c->m_prob
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2182 / (node->m_c->m_subtree_prob + default_prob));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2183 bb = do_jump_if_equal (bb, index, node->m_right->m_c->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2184 node->m_right->m_c->m_case_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2185
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2186 p = (node->m_left->m_c->m_prob
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2187 / (node->m_c->m_subtree_prob + default_prob));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2188 bb = do_jump_if_equal (bb, index, node->m_left->m_c->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2189 node->m_left->m_c->m_case_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2190 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2191 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2192 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2193 /* Branch to a label where we will handle it later. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2194 basic_block test_bb = split_edge (single_succ_edge (bb));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2195 redirect_edge_succ (single_pred_edge (test_bb),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2196 single_succ_edge (bb)->dest);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2197
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2198 p = ((node->m_right->m_c->m_subtree_prob
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2199 + default_prob.apply_scale (1, 2))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2200 / (node->m_c->m_subtree_prob + default_prob));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2201 bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2202 GT_EXPR, test_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2203 default_prob = default_prob.apply_scale (1, 2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2204
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2205 /* Handle the left-hand subtree. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2206 bb = emit_case_nodes (bb, index, node->m_left,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2207 default_prob, index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2208
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2209 /* If the left-hand subtree fell through,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2210 don't let it fall into the right-hand subtree. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2211 if (bb && m_default_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2212 emit_jump (bb, m_default_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2213
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2214 bb = emit_case_nodes (test_bb, index, node->m_right,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2215 default_prob, index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2216 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2217 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2218 else if (node->m_left == NULL && node->m_right != NULL)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2219 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2220 /* 2) the node has only right child. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2221
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2222 /* Here we have a right child but no left so we issue a conditional
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2223 branch to default and process the right child.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2224
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2225 Omit the conditional branch to default if the right child
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2226 does not have any children and is single valued; it would
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2227 cost too much space to save so little time. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2228
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2229 if (node->m_right->has_child ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2230 || !node->m_right->m_c->is_single_value_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2231 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2232 p = (default_prob.apply_scale (1, 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2233 / (node->m_c->m_subtree_prob + default_prob));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2234 bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2235 LT_EXPR, m_default_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2236 default_prob = default_prob.apply_scale (1, 2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2237
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2238 bb = emit_case_nodes (bb, index, node->m_right, default_prob,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2239 index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2240 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2241 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2242 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2243 /* We cannot process node->right normally
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2244 since we haven't ruled out the numbers less than
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2245 this node's value. So handle node->right explicitly. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2246 p = (node->m_right->m_c->m_subtree_prob
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2247 / (node->m_c->m_subtree_prob + default_prob));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2248 bb = do_jump_if_equal (bb, index, node->m_right->m_c->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2249 node->m_right->m_c->m_case_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2250 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2251 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2252 else if (node->m_left != NULL && node->m_right == NULL)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2253 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2254 /* 3) just one subtree, on the left. Similar case as previous. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2255
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2256 if (node->m_left->has_child ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2257 || !node->m_left->m_c->is_single_value_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2258 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2259 p = (default_prob.apply_scale (1, 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2260 / (node->m_c->m_subtree_prob + default_prob));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2261 bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2262 GT_EXPR, m_default_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2263 default_prob = default_prob.apply_scale (1, 2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2264
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2265 bb = emit_case_nodes (bb, index, node->m_left, default_prob,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2266 index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2267 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2268 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2269 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2270 /* We cannot process node->left normally
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2271 since we haven't ruled out the numbers less than
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2272 this node's value. So handle node->left explicitly. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2273 p = (node->m_left->m_c->m_subtree_prob
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2274 / (node->m_c->m_subtree_prob + default_prob));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2275 bb = do_jump_if_equal (bb, index, node->m_left->m_c->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2276 node->m_left->m_c->m_case_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2277 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2278 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2279 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2280 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2281 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2282 /* Node is a range. These cases are very similar to those for a single
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2283 value, except that we do not start by testing whether this node
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2284 is the one to branch to. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2285 if (node->has_child () || node->m_c->get_type () != SIMPLE_CASE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2286 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2287 /* Branch to a label where we will handle it later. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2288 basic_block test_bb = split_edge (single_succ_edge (bb));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2289 redirect_edge_succ (single_pred_edge (test_bb),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2290 single_succ_edge (bb)->dest);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2291
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2292
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2293 profile_probability right_prob = profile_probability::never ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2294 if (node->m_right)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2295 right_prob = node->m_right->m_c->m_subtree_prob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2296 p = ((right_prob + default_prob.apply_scale (1, 2))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2297 / (node->m_c->m_subtree_prob + default_prob));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2298
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2299 bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_high (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2300 GT_EXPR, test_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2301 default_prob = default_prob.apply_scale (1, 2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2302
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2303 /* Value belongs to this node or to the left-hand subtree. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2304 p = node->m_c->m_prob / (node->m_c->m_subtree_prob + default_prob);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2305 bb = emit_cmp_and_jump_insns (bb, index, node->m_c->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2306 GE_EXPR, node->m_c->m_case_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2307
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2308 /* Handle the left-hand subtree. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2309 bb = emit_case_nodes (bb, index, node->m_left,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2310 default_prob, index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2311
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2312 /* If the left-hand subtree fell through,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2313 don't let it fall into the right-hand subtree. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2314 if (bb && m_default_bb)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2315 emit_jump (bb, m_default_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2316
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2317 bb = emit_case_nodes (test_bb, index, node->m_right,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2318 default_prob, index_type);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2319 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2320 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2321 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2322 /* Node has no children so we check low and high bounds to remove
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2323 redundant tests. Only one of the bounds can exist,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2324 since otherwise this node is bounded--a case tested already. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2325 tree lhs, rhs;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2326 generate_range_test (bb, index, node->m_c->get_low (),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2327 node->m_c->get_high (), &lhs, &rhs);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2328 p = default_prob / (node->m_c->m_subtree_prob + default_prob);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2329
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2330 bb = emit_cmp_and_jump_insns (bb, lhs, rhs, GT_EXPR,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2331 m_default_bb, p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2332
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2333 emit_jump (bb, node->m_c->m_case_bb);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2334 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2335 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2336 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2337
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2338 return bb;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2339 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2340
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2341 /* The main function of the pass scans statements for switches and invokes
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2342 process_switch on them. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2343
111
kono
parents: 67
diff changeset
2344 namespace {
kono
parents: 67
diff changeset
2345
kono
parents: 67
diff changeset
2346 const pass_data pass_data_convert_switch =
kono
parents: 67
diff changeset
2347 {
kono
parents: 67
diff changeset
2348 GIMPLE_PASS, /* type */
kono
parents: 67
diff changeset
2349 "switchconv", /* name */
kono
parents: 67
diff changeset
2350 OPTGROUP_NONE, /* optinfo_flags */
kono
parents: 67
diff changeset
2351 TV_TREE_SWITCH_CONVERSION, /* tv_id */
kono
parents: 67
diff changeset
2352 ( PROP_cfg | PROP_ssa ), /* properties_required */
kono
parents: 67
diff changeset
2353 0, /* properties_provided */
kono
parents: 67
diff changeset
2354 0, /* properties_destroyed */
kono
parents: 67
diff changeset
2355 0, /* todo_flags_start */
kono
parents: 67
diff changeset
2356 TODO_update_ssa, /* todo_flags_finish */
kono
parents: 67
diff changeset
2357 };
kono
parents: 67
diff changeset
2358
kono
parents: 67
diff changeset
2359 class pass_convert_switch : public gimple_opt_pass
kono
parents: 67
diff changeset
2360 {
kono
parents: 67
diff changeset
2361 public:
kono
parents: 67
diff changeset
2362 pass_convert_switch (gcc::context *ctxt)
kono
parents: 67
diff changeset
2363 : gimple_opt_pass (pass_data_convert_switch, ctxt)
kono
parents: 67
diff changeset
2364 {}
kono
parents: 67
diff changeset
2365
kono
parents: 67
diff changeset
2366 /* opt_pass methods: */
kono
parents: 67
diff changeset
2367 virtual bool gate (function *) { return flag_tree_switch_conversion != 0; }
kono
parents: 67
diff changeset
2368 virtual unsigned int execute (function *);
kono
parents: 67
diff changeset
2369
kono
parents: 67
diff changeset
2370 }; // class pass_convert_switch
kono
parents: 67
diff changeset
2371
kono
parents: 67
diff changeset
2372 unsigned int
kono
parents: 67
diff changeset
2373 pass_convert_switch::execute (function *fun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2374 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2375 basic_block bb;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2376 bool cfg_altered = false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2377
111
kono
parents: 67
diff changeset
2378 FOR_EACH_BB_FN (bb, fun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2379 {
111
kono
parents: 67
diff changeset
2380 gimple *stmt = last_stmt (bb);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2381 if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2382 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2383 if (dump_file)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2384 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2385 expanded_location loc = expand_location (gimple_location (stmt));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2386
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2387 fprintf (dump_file, "beginning to process the following "
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2388 "SWITCH statement (%s:%d) : ------- \n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2389 loc.file, loc.line);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2390 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2391 putc ('\n', dump_file);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2392 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2393
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2394 switch_conversion sconv;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2395 sconv.expand (as_a <gswitch *> (stmt));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2396 cfg_altered |= sconv.m_cfg_altered;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2397 if (!sconv.m_reason)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2398 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2399 if (dump_file)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2400 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2401 fputs ("Switch converted\n", dump_file);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2402 fputs ("--------------------------------\n", dump_file);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2403 }
111
kono
parents: 67
diff changeset
2404
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2405 /* Make no effort to update the post-dominator tree.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2406 It is actually not that hard for the transformations
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2407 we have performed, but it is not supported
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2408 by iterate_fix_dominators. */
111
kono
parents: 67
diff changeset
2409 free_dominance_info (CDI_POST_DOMINATORS);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2410 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2411 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2412 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2413 if (dump_file)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2414 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2415 fputs ("Bailing out - ", dump_file);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2416 fputs (sconv.m_reason, dump_file);
111
kono
parents: 67
diff changeset
2417 fputs ("\n--------------------------------\n", dump_file);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2418 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2419 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2420 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2421 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2422
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2423 return cfg_altered ? TODO_cleanup_cfg : 0;;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2424 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2425
111
kono
parents: 67
diff changeset
2426 } // anon namespace
kono
parents: 67
diff changeset
2427
kono
parents: 67
diff changeset
2428 gimple_opt_pass *
kono
parents: 67
diff changeset
2429 make_pass_convert_switch (gcc::context *ctxt)
kono
parents: 67
diff changeset
2430 {
kono
parents: 67
diff changeset
2431 return new pass_convert_switch (ctxt);
kono
parents: 67
diff changeset
2432 }
kono
parents: 67
diff changeset
2433
kono
parents: 67
diff changeset
2434 /* The main function of the pass scans statements for switches and invokes
kono
parents: 67
diff changeset
2435 process_switch on them. */
kono
parents: 67
diff changeset
2436
kono
parents: 67
diff changeset
2437 namespace {
kono
parents: 67
diff changeset
2438
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2439 template <bool O0> class pass_lower_switch: public gimple_opt_pass
111
kono
parents: 67
diff changeset
2440 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2441 public:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2442 pass_lower_switch (gcc::context *ctxt) : gimple_opt_pass (data, ctxt) {}
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2443
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2444 static const pass_data data;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2445 opt_pass *
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2446 clone ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2447 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2448 return new pass_lower_switch<O0> (m_ctxt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2449 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2450
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2451 virtual bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2452 gate (function *)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2453 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2454 return !O0 || !optimize;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2455 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2456
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2457 virtual unsigned int execute (function *fun);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2458 }; // class pass_lower_switch
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2459
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2460 template <bool O0>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2461 const pass_data pass_lower_switch<O0>::data = {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2462 GIMPLE_PASS, /* type */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2463 O0 ? "switchlower_O0" : "switchlower", /* name */
111
kono
parents: 67
diff changeset
2464 OPTGROUP_NONE, /* optinfo_flags */
kono
parents: 67
diff changeset
2465 TV_TREE_SWITCH_LOWERING, /* tv_id */
kono
parents: 67
diff changeset
2466 ( PROP_cfg | PROP_ssa ), /* properties_required */
kono
parents: 67
diff changeset
2467 0, /* properties_provided */
kono
parents: 67
diff changeset
2468 0, /* properties_destroyed */
kono
parents: 67
diff changeset
2469 0, /* todo_flags_start */
kono
parents: 67
diff changeset
2470 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
kono
parents: 67
diff changeset
2471 };
kono
parents: 67
diff changeset
2472
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2473 template <bool O0>
111
kono
parents: 67
diff changeset
2474 unsigned int
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2475 pass_lower_switch<O0>::execute (function *fun)
111
kono
parents: 67
diff changeset
2476 {
kono
parents: 67
diff changeset
2477 basic_block bb;
kono
parents: 67
diff changeset
2478 bool expanded = false;
kono
parents: 67
diff changeset
2479
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2480 auto_vec<gimple *> switch_statements;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2481 switch_statements.create (1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2482
111
kono
parents: 67
diff changeset
2483 FOR_EACH_BB_FN (bb, fun)
kono
parents: 67
diff changeset
2484 {
kono
parents: 67
diff changeset
2485 gimple *stmt = last_stmt (bb);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2486 gswitch *swtch;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2487 if (stmt && (swtch = dyn_cast<gswitch *> (stmt)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2488 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2489 if (!O0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2490 group_case_labels_stmt (swtch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2491 switch_statements.safe_push (swtch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2492 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2493 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2494
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2495 for (unsigned i = 0; i < switch_statements.length (); i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2496 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2497 gimple *stmt = switch_statements[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2498 if (dump_file)
111
kono
parents: 67
diff changeset
2499 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2500 expanded_location loc = expand_location (gimple_location (stmt));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2501
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2502 fprintf (dump_file, "beginning to process the following "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2503 "SWITCH statement (%s:%d) : ------- \n",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2504 loc.file, loc.line);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2505 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2506 putc ('\n', dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2507 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2508
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2509 gswitch *swtch = dyn_cast<gswitch *> (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2510 if (swtch)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2511 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2512 switch_decision_tree dt (swtch);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2513 expanded |= dt.analyze_switch_statement ();
111
kono
parents: 67
diff changeset
2514 }
kono
parents: 67
diff changeset
2515 }
kono
parents: 67
diff changeset
2516
kono
parents: 67
diff changeset
2517 if (expanded)
kono
parents: 67
diff changeset
2518 {
kono
parents: 67
diff changeset
2519 free_dominance_info (CDI_DOMINATORS);
kono
parents: 67
diff changeset
2520 free_dominance_info (CDI_POST_DOMINATORS);
kono
parents: 67
diff changeset
2521 mark_virtual_operands_for_renaming (cfun);
kono
parents: 67
diff changeset
2522 }
kono
parents: 67
diff changeset
2523
kono
parents: 67
diff changeset
2524 return 0;
kono
parents: 67
diff changeset
2525 }
kono
parents: 67
diff changeset
2526
kono
parents: 67
diff changeset
2527 } // anon namespace
kono
parents: 67
diff changeset
2528
kono
parents: 67
diff changeset
2529 gimple_opt_pass *
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2530 make_pass_lower_switch_O0 (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2531 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2532 return new pass_lower_switch<true> (ctxt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2533 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2534 gimple_opt_pass *
111
kono
parents: 67
diff changeset
2535 make_pass_lower_switch (gcc::context *ctxt)
kono
parents: 67
diff changeset
2536 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2537 return new pass_lower_switch<false> (ctxt);
111
kono
parents: 67
diff changeset
2538 }
kono
parents: 67
diff changeset
2539
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2540