annotate gcc/tree-switch-conversion.c @ 158:494b0b89df80 default tip

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