annotate gcc/stmt.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
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Expands front end tree to back end RTL for GCC
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 1987-2020 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 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
14 for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 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
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 /* This file handles the generation of rtl code from tree structure
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 above the level of expressions, using subroutines in exp*.c and emit-rtl.c.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 The functions whose names start with `expand_' are called by the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 expander to generate RTL instructions for various kinds of constructs. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 #include "coretypes.h"
111
kono
parents: 67
diff changeset
28 #include "backend.h"
kono
parents: 67
diff changeset
29 #include "target.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 #include "rtl.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 #include "tree.h"
111
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 "predict.h"
kono
parents: 67
diff changeset
35 #include "memmodel.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 #include "tm_p.h"
111
kono
parents: 67
diff changeset
37 #include "optabs.h"
kono
parents: 67
diff changeset
38 #include "regs.h"
kono
parents: 67
diff changeset
39 #include "emit-rtl.h"
kono
parents: 67
diff changeset
40 #include "pretty-print.h"
kono
parents: 67
diff changeset
41 #include "diagnostic-core.h"
kono
parents: 67
diff changeset
42
kono
parents: 67
diff changeset
43 #include "fold-const.h"
kono
parents: 67
diff changeset
44 #include "varasm.h"
kono
parents: 67
diff changeset
45 #include "stor-layout.h"
kono
parents: 67
diff changeset
46 #include "dojump.h"
kono
parents: 67
diff changeset
47 #include "explow.h"
kono
parents: 67
diff changeset
48 #include "stmt.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 #include "expr.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 #include "langhooks.h"
111
kono
parents: 67
diff changeset
51 #include "cfganal.h"
kono
parents: 67
diff changeset
52 #include "tree-cfg.h"
kono
parents: 67
diff changeset
53 #include "dumpfile.h"
kono
parents: 67
diff changeset
54 #include "builtins.h"
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
55
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 /* Functions and data structures for expanding case statements. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 /* Case label structure, used to hold info on labels within case
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 statements. We handle "range" labels; for a single-value label
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 as in C, the high and low limits are the same.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 We start with a vector of case nodes sorted in ascending order, and
111
kono
parents: 67
diff changeset
64 the default label as the last element in the vector.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65
111
kono
parents: 67
diff changeset
66 Switch statements are expanded in jump table form.
kono
parents: 67
diff changeset
67
kono
parents: 67
diff changeset
68 */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
70 class simple_case_node
111
kono
parents: 67
diff changeset
71 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
72 public:
111
kono
parents: 67
diff changeset
73 simple_case_node (tree low, tree high, tree code_label):
kono
parents: 67
diff changeset
74 m_low (low), m_high (high), m_code_label (code_label)
kono
parents: 67
diff changeset
75 {}
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76
111
kono
parents: 67
diff changeset
77 /* Lowest index value for this label. */
kono
parents: 67
diff changeset
78 tree m_low;
kono
parents: 67
diff changeset
79 /* Highest index value for this label. */
kono
parents: 67
diff changeset
80 tree m_high;
kono
parents: 67
diff changeset
81 /* Label to jump to when node matches. */
kono
parents: 67
diff changeset
82 tree m_code_label;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
85 static bool check_unique_operand_names (tree, tree, tree);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
86 static char *resolve_operand_name_1 (char *, tree, tree, tree);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 /* Return the rtx-label that corresponds to a LABEL_DECL,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 creating it if necessary. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90
111
kono
parents: 67
diff changeset
91 rtx_insn *
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 label_rtx (tree label)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 gcc_assert (TREE_CODE (label) == LABEL_DECL);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 if (!DECL_RTL_SET_P (label))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 {
111
kono
parents: 67
diff changeset
98 rtx_code_label *r = gen_label_rtx ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 SET_DECL_RTL (label, r);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 if (FORCED_LABEL (label) || DECL_NONLOCAL (label))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 LABEL_PRESERVE_P (r) = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103
111
kono
parents: 67
diff changeset
104 return as_a <rtx_insn *> (DECL_RTL (label));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 /* As above, but also put it on the forced-reference list of the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 function that contains it. */
111
kono
parents: 67
diff changeset
109 rtx_insn *
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 force_label_rtx (tree label)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 {
111
kono
parents: 67
diff changeset
112 rtx_insn *ref = label_rtx (label);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 tree function = decl_function_context (label);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 gcc_assert (function);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
116
111
kono
parents: 67
diff changeset
117 vec_safe_push (forced_labels, ref);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
118 return ref;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120
111
kono
parents: 67
diff changeset
121 /* As label_rtx, but ensures (in check build), that returned value is
kono
parents: 67
diff changeset
122 an existing label (i.e. rtx with code CODE_LABEL). */
kono
parents: 67
diff changeset
123 rtx_code_label *
kono
parents: 67
diff changeset
124 jump_target_rtx (tree label)
kono
parents: 67
diff changeset
125 {
kono
parents: 67
diff changeset
126 return as_a <rtx_code_label *> (label_rtx (label));
kono
parents: 67
diff changeset
127 }
kono
parents: 67
diff changeset
128
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 /* Add an unconditional jump to LABEL as the next sequential instruction. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
130
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 emit_jump (rtx label)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 do_pending_stack_adjust ();
111
kono
parents: 67
diff changeset
135 emit_jump_insn (targetm.gen_jump (label));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 emit_barrier ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 /* Handle goto statements and the labels that they can go to. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 /* Specify the location in the RTL code of a label LABEL,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 which is a LABEL_DECL tree node.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 This is used for the kind of label that the user can jump to with a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 goto statement, and for alternatives of a switch or case statement.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 RTL labels generated for loops and conditionals don't go through here;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 they are generated directly at the RTL level, by other functions below.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 Note that this has nothing to do with defining label *names*.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 Languages vary in how they do that and what that even means. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
151
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 expand_label (tree label)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 {
111
kono
parents: 67
diff changeset
155 rtx_code_label *label_r = jump_target_rtx (label);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 do_pending_stack_adjust ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 emit_label (label_r);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 if (DECL_NAME (label))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 LABEL_NAME (DECL_RTL (label)) = IDENTIFIER_POINTER (DECL_NAME (label));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 if (DECL_NONLOCAL (label))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 {
111
kono
parents: 67
diff changeset
164 expand_builtin_setjmp_receiver (NULL);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 nonlocal_goto_handler_labels
111
kono
parents: 67
diff changeset
166 = gen_rtx_INSN_LIST (VOIDmode, label_r,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 nonlocal_goto_handler_labels);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
168 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 if (FORCED_LABEL (label))
111
kono
parents: 67
diff changeset
171 vec_safe_push<rtx_insn *> (forced_labels, label_r);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
172
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 maybe_set_first_label_num (label_r);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 /* Parse the output constraint pointed to by *CONSTRAINT_P. It is the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 OPERAND_NUMth output operand, indexed from zero. There are NINPUTS
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 inputs and NOUTPUTS outputs to this extended-asm. Upon return,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 *ALLOWS_MEM will be TRUE iff the constraint allows the use of a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 memory operand. Similarly, *ALLOWS_REG will be TRUE iff the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 constraint allows the use of a register operand. And, *IS_INOUT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 will be true if the operand is read-write, i.e., if it is used as
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 an input as well as an output. If *CONSTRAINT_P is not in
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 canonical form, it will be made canonical. (Note that `+' will be
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
186 replaced with `=' as part of this process.)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 Returns TRUE if all went well; FALSE if an error occurred. */
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 bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 parse_output_constraint (const char **constraint_p, int operand_num,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 int ninputs, int noutputs, bool *allows_mem,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 bool *allows_reg, bool *is_inout)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 const char *constraint = *constraint_p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 const char *p;
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 /* Assume the constraint doesn't allow the use of either a register
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 or memory. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 *allows_mem = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 *allows_reg = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 /* Allow the `=' or `+' to not be at the beginning of the string,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 since it wasn't explicitly documented that way, and there is a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 large body of code that puts it last. Swap the character to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 the front, so as not to uglify any place else. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 p = strchr (constraint, '=');
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 if (!p)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 p = strchr (constraint, '+');
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 /* If the string doesn't contain an `=', issue an error
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 message. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 if (!p)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 error ("output operand constraint lacks %<=%>");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 /* If the constraint begins with `+', then the operand is both read
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 from and written to. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 *is_inout = (*p == '+');
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 /* Canonicalize the output constraint so that it begins with `='. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
224 if (p != constraint || *is_inout)
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 char *buf;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 size_t c_len = strlen (constraint);
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 if (p != constraint)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 warning (0, "output constraint %qc for operand %d "
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 "is not at the beginning",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 *p, operand_num);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 /* Make a copy of the constraint. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 buf = XALLOCAVEC (char, c_len + 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 strcpy (buf, constraint);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 /* Swap the first character and the `=' or `+'. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 buf[p - constraint] = buf[0];
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 /* Make sure the first character is an `='. (Until we do this,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 it might be a `+'.) */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 buf[0] = '=';
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 /* Replace the constraint with the canonicalized string. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 *constraint_p = ggc_alloc_string (buf, c_len);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 constraint = *constraint_p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 /* Loop through the constraint string. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
248 for (p = constraint + 1; *p; )
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
249 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
250 switch (*p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
251 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
252 case '+':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
253 case '=':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
254 error ("operand constraint contains incorrectly positioned "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
255 "%<+%> or %<=%>");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
256 return false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
258 case '%':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
259 if (operand_num + 1 == ninputs + noutputs)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
260 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
261 error ("%<%%%> constraint used with last operand");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
262 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
263 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
264 break;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
266 case '?': case '!': case '*': case '&': case '#':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
267 case '$': case '^':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
268 case 'E': case 'F': case 'G': case 'H':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
269 case 's': case 'i': case 'n':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
270 case 'I': case 'J': case 'K': case 'L': case 'M':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
271 case 'N': case 'O': case 'P': case ',':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
272 break;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
274 case '0': case '1': case '2': case '3': case '4':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
275 case '5': case '6': case '7': case '8': case '9':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
276 case '[':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
277 error ("matching constraint not valid in output operand");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
278 return false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
280 case '<': case '>':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
281 /* ??? Before flow, auto inc/dec insns are not supposed to exist,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
282 excepting those that expand_call created. So match memory
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
283 and hope. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
284 *allows_mem = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
285 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
286
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
287 case 'g': case 'X':
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
288 *allows_reg = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
289 *allows_mem = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
290 break;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
292 default:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
293 if (!ISALPHA (*p))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
294 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
295 enum constraint_num cn = lookup_constraint (p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
296 if (reg_class_for_constraint (cn) != NO_REGS
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
297 || insn_extra_address_constraint (cn))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
298 *allows_reg = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
299 else if (insn_extra_memory_constraint (cn))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
300 *allows_mem = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
301 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
302 insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 break;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
304 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
305
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
306 for (size_t len = CONSTRAINT_LEN (*p, p); len; len--, p++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
307 if (*p == '\0')
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
308 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
309 }
0
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 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 /* Similar, but for input constraints. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 parse_input_constraint (const char **constraint_p, int input_num,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 int ninputs, int noutputs, int ninout,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 const char * const * constraints,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 bool *allows_mem, bool *allows_reg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
321 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 const char *constraint = *constraint_p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 const char *orig_constraint = constraint;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 size_t c_len = strlen (constraint);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
325 size_t j;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 bool saw_match = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
327
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 /* Assume the constraint doesn't allow the use of either
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 a register or memory. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 *allows_mem = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
331 *allows_reg = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
332
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 /* Make sure constraint has neither `=', `+', nor '&'. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 for (j = 0; j < c_len; j += CONSTRAINT_LEN (constraint[j], constraint+j))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 switch (constraint[j])
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 case '+': case '=': case '&':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 if (constraint == orig_constraint)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 error ("input operand constraint contains %qc", constraint[j]);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
342 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 case '%':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 if (constraint == orig_constraint
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 && input_num + 1 == ninputs - ninout)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 error ("%<%%%> constraint used with last operand");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
354
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355 case '<': case '>':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 case '?': case '!': case '*': case '#':
111
kono
parents: 67
diff changeset
357 case '$': case '^':
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
358 case 'E': case 'F': case 'G': case 'H':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 case 's': case 'i': case 'n':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
360 case 'I': case 'J': case 'K': case 'L': case 'M':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
361 case 'N': case 'O': case 'P': case ',':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 break;
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 /* Whether or not a numeric constraint allows a register is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
365 decided by the matching constraint, and so there is no need
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
366 to do anything special with them. We must handle them in
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367 the default case, so that we don't unnecessarily force
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 operands to memory. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369 case '0': case '1': case '2': case '3': case '4':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 case '5': case '6': case '7': case '8': case '9':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
371 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
372 char *end;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
373 unsigned long match;
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 saw_match = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
376
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
377 match = strtoul (constraint + j, &end, 10);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
378 if (match >= (unsigned long) noutputs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
379 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 error ("matching constraint references invalid operand number");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
381 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
382 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
383
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384 /* Try and find the real constraint for this dup. Only do this
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385 if the matching constraint is the only alternative. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
386 if (*end == '\0'
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 && (j == 0 || (j == 1 && constraint[0] == '%')))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389 constraint = constraints[match];
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 *constraint_p = constraint;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 c_len = strlen (constraint);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392 j = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393 /* ??? At the end of the loop, we will skip the first part of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 the matched constraint. This assumes not only that the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 other constraint is an output constraint, but also that
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396 the '=' or '+' come first. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
398 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
400 j = end - constraint;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
401 /* Anticipate increment at end of loop. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 j--;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
403 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
404 /* Fall through. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
405
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
406 case 'g': case 'X':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
407 *allows_reg = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
408 *allows_mem = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 if (! ISALPHA (constraint[j]))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
413 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414 error ("invalid punctuation %qc in constraint", constraint[j]);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
415 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
416 }
111
kono
parents: 67
diff changeset
417 enum constraint_num cn = lookup_constraint (constraint + j);
kono
parents: 67
diff changeset
418 if (reg_class_for_constraint (cn) != NO_REGS
kono
parents: 67
diff changeset
419 || insn_extra_address_constraint (cn))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
420 *allows_reg = true;
111
kono
parents: 67
diff changeset
421 else if (insn_extra_memory_constraint (cn)
kono
parents: 67
diff changeset
422 || insn_extra_special_memory_constraint (cn))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423 *allows_mem = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
424 else
111
kono
parents: 67
diff changeset
425 insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
426 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
427 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
428
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
429 if (saw_match && !*allows_reg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
430 warning (0, "matching constraint does not allow a register");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
431
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
432 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
433 }
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 /* Return DECL iff there's an overlap between *REGS and DECL, where DECL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
436 can be an asm-declared register. Called via walk_tree. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
437
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
438 static tree
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
439 decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
440 void *data)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
441 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
442 tree decl = *declp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
443 const HARD_REG_SET *const regs = (const HARD_REG_SET *) data;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
444
111
kono
parents: 67
diff changeset
445 if (VAR_P (decl))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
446 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
447 if (DECL_HARD_REGISTER (decl)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
448 && REG_P (DECL_RTL (decl))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
449 && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
450 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
451 rtx reg = DECL_RTL (decl);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
452
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453 if (overlaps_hard_reg_set_p (*regs, GET_MODE (reg), REGNO (reg)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
454 return decl;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
455 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456 walk_subtrees = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
458 else if (TYPE_P (decl) || TREE_CODE (decl) == PARM_DECL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
459 walk_subtrees = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460 return NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
461 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
462
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463 /* If there is an overlap between *REGS and DECL, return the first overlap
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 found. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465 tree
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466 tree_overlaps_hard_reg_set (tree decl, HARD_REG_SET *regs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 return walk_tree (&decl, decl_overlaps_hard_reg_set_p, regs, NULL);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
472 /* A subroutine of expand_asm_operands. Check that all operand names
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
473 are unique. Return true if so. We rely on the fact that these names
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
474 are identifiers, and so have been canonicalized by get_identifier,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
475 so all we need are pointer comparisons. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
476
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
477 static bool
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
478 check_unique_operand_names (tree outputs, tree inputs, tree labels)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
479 {
111
kono
parents: 67
diff changeset
480 tree i, j, i_name = NULL_TREE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
481
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
482 for (i = outputs; i ; i = TREE_CHAIN (i))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
483 {
111
kono
parents: 67
diff changeset
484 i_name = TREE_PURPOSE (TREE_PURPOSE (i));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
485 if (! i_name)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
488 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490 goto failure;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
491 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
492
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
493 for (i = inputs; i ; i = TREE_CHAIN (i))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
494 {
111
kono
parents: 67
diff changeset
495 i_name = TREE_PURPOSE (TREE_PURPOSE (i));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
496 if (! i_name)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
497 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
498
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
500 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
501 goto failure;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
502 for (j = outputs; j ; j = TREE_CHAIN (j))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
503 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
504 goto failure;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
505 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
506
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
507 for (i = labels; i ; i = TREE_CHAIN (i))
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
508 {
111
kono
parents: 67
diff changeset
509 i_name = TREE_PURPOSE (i);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
510 if (! i_name)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
511 continue;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
512
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
513 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
514 if (simple_cst_equal (i_name, TREE_PURPOSE (j)))
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
515 goto failure;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
516 for (j = inputs; j ; j = TREE_CHAIN (j))
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
517 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
518 goto failure;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
519 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
520
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
521 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
522
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 failure:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
524 error ("duplicate %<asm%> operand name %qs", TREE_STRING_POINTER (i_name));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
525 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
526 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
527
111
kono
parents: 67
diff changeset
528 /* Resolve the names of the operands in *POUTPUTS and *PINPUTS to numbers,
kono
parents: 67
diff changeset
529 and replace the name expansions in STRING and in the constraints to
kono
parents: 67
diff changeset
530 those numbers. This is generally done in the front end while creating
kono
parents: 67
diff changeset
531 the ASM_EXPR generic tree that eventually becomes the GIMPLE_ASM. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
532
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
533 tree
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
534 resolve_asm_operand_names (tree string, tree outputs, tree inputs, tree labels)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
535 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
536 char *buffer;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
537 char *p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
538 const char *c;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
539 tree t;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
540
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
541 check_unique_operand_names (outputs, inputs, labels);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
542
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
543 /* Substitute [<name>] in input constraint strings. There should be no
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
544 named operands in output constraints. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
545 for (t = inputs; t ; t = TREE_CHAIN (t))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
546 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
547 c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
548 if (strchr (c, '[') != NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
549 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
550 p = buffer = xstrdup (c);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
551 while ((p = strchr (p, '[')) != NULL)
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
552 p = resolve_operand_name_1 (p, outputs, inputs, NULL);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
553 TREE_VALUE (TREE_PURPOSE (t))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
554 = build_string (strlen (buffer), buffer);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 free (buffer);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
556 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
558
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559 /* Now check for any needed substitutions in the template. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 c = TREE_STRING_POINTER (string);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
561 while ((c = strchr (c, '%')) != NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
562 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
563 if (c[1] == '[')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
564 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
565 else if (ISALPHA (c[1]) && c[2] == '[')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
566 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
567 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
568 {
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
569 c += 1 + (c[1] == '%');
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
570 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
571 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
572 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
573
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
574 if (c)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
575 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
576 /* OK, we need to make a copy so we can perform the substitutions.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
577 Assume that we will not need extra space--we get to remove '['
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578 and ']', which means we cannot have a problem until we have more
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579 than 999 operands. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
580 buffer = xstrdup (TREE_STRING_POINTER (string));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 p = buffer + (c - TREE_STRING_POINTER (string));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
582
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
583 while ((p = strchr (p, '%')) != NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
584 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585 if (p[1] == '[')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
586 p += 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
587 else if (ISALPHA (p[1]) && p[2] == '[')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
588 p += 2;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
589 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
590 {
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
591 p += 1 + (p[1] == '%');
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
593 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
594
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
595 p = resolve_operand_name_1 (p, outputs, inputs, labels);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
596 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
597
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
598 string = build_string (strlen (buffer), buffer);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
599 free (buffer);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
600 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
601
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
602 return string;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
603 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
604
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
605 /* A subroutine of resolve_operand_names. P points to the '[' for a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606 potential named operand of the form [<name>]. In place, replace
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 the name and brackets with a number. Return a pointer to the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
608 balance of the string after substitution. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
609
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
610 static char *
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
611 resolve_operand_name_1 (char *p, tree outputs, tree inputs, tree labels)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
612 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
613 char *q;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
614 int op;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
615 tree t;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
616
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
617 /* Collect the operand name. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
618 q = strchr (++p, ']');
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
619 if (!q)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
620 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
621 error ("missing close brace for named operand");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
622 return strchr (p, '\0');
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
623 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
624 *q = '\0';
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
626 /* Resolve the name to a number. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627 for (op = 0, t = outputs; t ; t = TREE_CHAIN (t), op++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
628 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
629 tree name = TREE_PURPOSE (TREE_PURPOSE (t));
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
630 if (name && strcmp (TREE_STRING_POINTER (name), p) == 0)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
631 goto found;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
632 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 for (t = inputs; t ; t = TREE_CHAIN (t), op++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
634 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
635 tree name = TREE_PURPOSE (TREE_PURPOSE (t));
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
636 if (name && strcmp (TREE_STRING_POINTER (name), p) == 0)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
637 goto found;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
639 for (t = labels; t ; t = TREE_CHAIN (t), op++)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
640 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
641 tree name = TREE_PURPOSE (t);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
642 if (name && strcmp (TREE_STRING_POINTER (name), p) == 0)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
643 goto found;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
644 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
645
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
646 error ("undefined named operand %qs", identifier_to_locale (p));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
647 op = 0;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
648
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 found:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
650 /* Replace the name with the number. Unfortunately, not all libraries
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
651 get the return value of sprintf correct, so search for the end of the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
652 generated string by hand. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
653 sprintf (--p, "%d", op);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
654 p = strchr (p, '\0');
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
655
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
656 /* Verify the no extra buffer space assumption. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
657 gcc_assert (p <= q);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
658
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
659 /* Shift the rest of the buffer down to fill the gap. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
660 memmove (p, q + 1, strlen (q + 1) + 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
661
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
662 return p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
663 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
664
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
665
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
666 /* Generate RTL to return directly from the current function.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
667 (That is, we bypass any return value.) */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
668
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
669 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
670 expand_naked_return (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
671 {
111
kono
parents: 67
diff changeset
672 rtx_code_label *end_label;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
673
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
674 clear_pending_stack_adjust ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
675 do_pending_stack_adjust ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
676
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
677 end_label = naked_return_label;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
678 if (end_label == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
679 end_label = naked_return_label = gen_label_rtx ();
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 emit_jump (end_label);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
682 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
683
111
kono
parents: 67
diff changeset
684 /* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. PROB
kono
parents: 67
diff changeset
685 is the probability of jumping to LABEL. */
kono
parents: 67
diff changeset
686 static void
kono
parents: 67
diff changeset
687 do_jump_if_equal (machine_mode mode, rtx op0, rtx op1, rtx_code_label *label,
kono
parents: 67
diff changeset
688 int unsignedp, profile_probability prob)
kono
parents: 67
diff changeset
689 {
kono
parents: 67
diff changeset
690 do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode,
kono
parents: 67
diff changeset
691 NULL_RTX, NULL, label, prob);
kono
parents: 67
diff changeset
692 }
kono
parents: 67
diff changeset
693
kono
parents: 67
diff changeset
694 /* Return the sum of probabilities of outgoing edges of basic block BB. */
kono
parents: 67
diff changeset
695
kono
parents: 67
diff changeset
696 static profile_probability
kono
parents: 67
diff changeset
697 get_outgoing_edge_probs (basic_block bb)
kono
parents: 67
diff changeset
698 {
kono
parents: 67
diff changeset
699 edge e;
kono
parents: 67
diff changeset
700 edge_iterator ei;
kono
parents: 67
diff changeset
701 profile_probability prob_sum = profile_probability::never ();
kono
parents: 67
diff changeset
702 if (!bb)
kono
parents: 67
diff changeset
703 return profile_probability::never ();
kono
parents: 67
diff changeset
704 FOR_EACH_EDGE (e, ei, bb->succs)
kono
parents: 67
diff changeset
705 prob_sum += e->probability;
kono
parents: 67
diff changeset
706 return prob_sum;
kono
parents: 67
diff changeset
707 }
kono
parents: 67
diff changeset
708
kono
parents: 67
diff changeset
709 /* Computes the conditional probability of jumping to a target if the branch
kono
parents: 67
diff changeset
710 instruction is executed.
kono
parents: 67
diff changeset
711 TARGET_PROB is the estimated probability of jumping to a target relative
kono
parents: 67
diff changeset
712 to some basic block BB.
kono
parents: 67
diff changeset
713 BASE_PROB is the probability of reaching the branch instruction relative
kono
parents: 67
diff changeset
714 to the same basic block BB. */
kono
parents: 67
diff changeset
715
kono
parents: 67
diff changeset
716 static inline profile_probability
kono
parents: 67
diff changeset
717 conditional_probability (profile_probability target_prob,
kono
parents: 67
diff changeset
718 profile_probability base_prob)
kono
parents: 67
diff changeset
719 {
kono
parents: 67
diff changeset
720 return target_prob / base_prob;
kono
parents: 67
diff changeset
721 }
kono
parents: 67
diff changeset
722
kono
parents: 67
diff changeset
723 /* Generate a dispatch tabler, switching on INDEX_EXPR and jumping to
kono
parents: 67
diff changeset
724 one of the labels in CASE_LIST or to the DEFAULT_LABEL.
kono
parents: 67
diff changeset
725 MINVAL, MAXVAL, and RANGE are the extrema and range of the case
kono
parents: 67
diff changeset
726 labels in CASE_LIST. STMT_BB is the basic block containing the statement.
kono
parents: 67
diff changeset
727
kono
parents: 67
diff changeset
728 First, a jump insn is emitted. First we try "casesi". If that
kono
parents: 67
diff changeset
729 fails, try "tablejump". A target *must* have one of them (or both).
kono
parents: 67
diff changeset
730
kono
parents: 67
diff changeset
731 Then, a table with the target labels is emitted.
kono
parents: 67
diff changeset
732
kono
parents: 67
diff changeset
733 The process is unaware of the CFG. The caller has to fix up
kono
parents: 67
diff changeset
734 the CFG itself. This is done in cfgexpand.c. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
735
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
736 static void
111
kono
parents: 67
diff changeset
737 emit_case_dispatch_table (tree index_expr, tree index_type,
kono
parents: 67
diff changeset
738 auto_vec<simple_case_node> &case_list,
kono
parents: 67
diff changeset
739 rtx default_label,
kono
parents: 67
diff changeset
740 edge default_edge, tree minval, tree maxval,
kono
parents: 67
diff changeset
741 tree range, basic_block stmt_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
742 {
111
kono
parents: 67
diff changeset
743 int i, ncases;
kono
parents: 67
diff changeset
744 rtx *labelvec;
kono
parents: 67
diff changeset
745 rtx_insn *fallback_label = label_rtx (case_list[0].m_code_label);
kono
parents: 67
diff changeset
746 rtx_code_label *table_label = gen_label_rtx ();
kono
parents: 67
diff changeset
747 bool has_gaps = false;
kono
parents: 67
diff changeset
748 profile_probability default_prob = default_edge ? default_edge->probability
kono
parents: 67
diff changeset
749 : profile_probability::never ();
kono
parents: 67
diff changeset
750 profile_probability base = get_outgoing_edge_probs (stmt_bb);
kono
parents: 67
diff changeset
751 bool try_with_tablejump = false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
752
111
kono
parents: 67
diff changeset
753 profile_probability new_default_prob = conditional_probability (default_prob,
kono
parents: 67
diff changeset
754 base);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
755
111
kono
parents: 67
diff changeset
756 if (! try_casesi (index_type, index_expr, minval, range,
kono
parents: 67
diff changeset
757 table_label, default_label, fallback_label,
kono
parents: 67
diff changeset
758 new_default_prob))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
759 {
111
kono
parents: 67
diff changeset
760 /* Index jumptables from zero for suitable values of minval to avoid
kono
parents: 67
diff changeset
761 a subtraction. For the rationale see:
kono
parents: 67
diff changeset
762 "http://gcc.gnu.org/ml/gcc-patches/2001-10/msg01234.html". */
kono
parents: 67
diff changeset
763 if (optimize_insn_for_speed_p ()
kono
parents: 67
diff changeset
764 && compare_tree_int (minval, 0) > 0
kono
parents: 67
diff changeset
765 && compare_tree_int (minval, 3) < 0)
kono
parents: 67
diff changeset
766 {
kono
parents: 67
diff changeset
767 minval = build_int_cst (index_type, 0);
kono
parents: 67
diff changeset
768 range = maxval;
kono
parents: 67
diff changeset
769 has_gaps = true;
kono
parents: 67
diff changeset
770 }
kono
parents: 67
diff changeset
771 try_with_tablejump = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
772 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
773
111
kono
parents: 67
diff changeset
774 /* Get table of labels to jump to, in order of case index. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
775
111
kono
parents: 67
diff changeset
776 ncases = tree_to_shwi (range) + 1;
kono
parents: 67
diff changeset
777 labelvec = XALLOCAVEC (rtx, ncases);
kono
parents: 67
diff changeset
778 memset (labelvec, 0, ncases * sizeof (rtx));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
779
111
kono
parents: 67
diff changeset
780 for (unsigned j = 0; j < case_list.length (); j++)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
781 {
111
kono
parents: 67
diff changeset
782 simple_case_node *n = &case_list[j];
kono
parents: 67
diff changeset
783 /* Compute the low and high bounds relative to the minimum
kono
parents: 67
diff changeset
784 value since that should fit in a HOST_WIDE_INT while the
kono
parents: 67
diff changeset
785 actual values may not. */
kono
parents: 67
diff changeset
786 HOST_WIDE_INT i_low
kono
parents: 67
diff changeset
787 = tree_to_uhwi (fold_build2 (MINUS_EXPR, index_type,
kono
parents: 67
diff changeset
788 n->m_low, minval));
kono
parents: 67
diff changeset
789 HOST_WIDE_INT i_high
kono
parents: 67
diff changeset
790 = tree_to_uhwi (fold_build2 (MINUS_EXPR, index_type,
kono
parents: 67
diff changeset
791 n->m_high, minval));
kono
parents: 67
diff changeset
792 HOST_WIDE_INT i;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
793
111
kono
parents: 67
diff changeset
794 for (i = i_low; i <= i_high; i ++)
kono
parents: 67
diff changeset
795 labelvec[i]
kono
parents: 67
diff changeset
796 = gen_rtx_LABEL_REF (Pmode, label_rtx (n->m_code_label));
kono
parents: 67
diff changeset
797 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
798
111
kono
parents: 67
diff changeset
799 /* The dispatch table may contain gaps, including at the beginning of
kono
parents: 67
diff changeset
800 the table if we tried to avoid the minval subtraction. We fill the
kono
parents: 67
diff changeset
801 dispatch table slots associated with the gaps with the default case label.
kono
parents: 67
diff changeset
802 However, in the event the default case is unreachable, we then use
kono
parents: 67
diff changeset
803 any label from one of the case statements. */
kono
parents: 67
diff changeset
804 rtx gap_label = (default_label) ? default_label : fallback_label;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
805
111
kono
parents: 67
diff changeset
806 for (i = 0; i < ncases; i++)
kono
parents: 67
diff changeset
807 if (labelvec[i] == 0)
kono
parents: 67
diff changeset
808 {
kono
parents: 67
diff changeset
809 has_gaps = true;
kono
parents: 67
diff changeset
810 labelvec[i] = gen_rtx_LABEL_REF (Pmode, gap_label);
kono
parents: 67
diff changeset
811 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
812
111
kono
parents: 67
diff changeset
813 if (has_gaps && default_label)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
814 {
111
kono
parents: 67
diff changeset
815 /* There is at least one entry in the jump table that jumps
kono
parents: 67
diff changeset
816 to default label. The default label can either be reached
kono
parents: 67
diff changeset
817 through the indirect jump or the direct conditional jump
kono
parents: 67
diff changeset
818 before that. Split the probability of reaching the
kono
parents: 67
diff changeset
819 default label among these two jumps. */
kono
parents: 67
diff changeset
820 new_default_prob
kono
parents: 67
diff changeset
821 = conditional_probability (default_prob.apply_scale (1, 2), base);
kono
parents: 67
diff changeset
822 default_prob = default_prob.apply_scale (1, 2);
kono
parents: 67
diff changeset
823 base -= default_prob;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
824 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
825 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
826 {
111
kono
parents: 67
diff changeset
827 base -= default_prob;
kono
parents: 67
diff changeset
828 default_prob = profile_probability::never ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
829 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
830
111
kono
parents: 67
diff changeset
831 if (default_edge)
kono
parents: 67
diff changeset
832 default_edge->probability = default_prob;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
833
111
kono
parents: 67
diff changeset
834 /* We have altered the probability of the default edge. So the probabilities
kono
parents: 67
diff changeset
835 of all other edges need to be adjusted so that it sums up to
kono
parents: 67
diff changeset
836 REG_BR_PROB_BASE. */
kono
parents: 67
diff changeset
837 if (base > profile_probability::never ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
838 {
111
kono
parents: 67
diff changeset
839 edge e;
kono
parents: 67
diff changeset
840 edge_iterator ei;
kono
parents: 67
diff changeset
841 FOR_EACH_EDGE (e, ei, stmt_bb->succs)
kono
parents: 67
diff changeset
842 e->probability /= base;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
843 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
844
111
kono
parents: 67
diff changeset
845 if (try_with_tablejump)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
846 {
111
kono
parents: 67
diff changeset
847 bool ok = try_tablejump (index_type, index_expr, minval, range,
kono
parents: 67
diff changeset
848 table_label, default_label, new_default_prob);
kono
parents: 67
diff changeset
849 gcc_assert (ok);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
850 }
111
kono
parents: 67
diff changeset
851 /* Output the table. */
kono
parents: 67
diff changeset
852 emit_label (table_label);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
853
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
854 if (CASE_VECTOR_PC_RELATIVE
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
855 || (flag_pic && targetm.asm_out.generate_pic_addr_diff_vec ()))
111
kono
parents: 67
diff changeset
856 emit_jump_table_data (gen_rtx_ADDR_DIFF_VEC (CASE_VECTOR_MODE,
kono
parents: 67
diff changeset
857 gen_rtx_LABEL_REF (Pmode,
kono
parents: 67
diff changeset
858 table_label),
kono
parents: 67
diff changeset
859 gen_rtvec_v (ncases, labelvec),
kono
parents: 67
diff changeset
860 const0_rtx, const0_rtx));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
861 else
111
kono
parents: 67
diff changeset
862 emit_jump_table_data (gen_rtx_ADDR_VEC (CASE_VECTOR_MODE,
kono
parents: 67
diff changeset
863 gen_rtvec_v (ncases, labelvec)));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
864
111
kono
parents: 67
diff changeset
865 /* Record no drop-through after the table. */
kono
parents: 67
diff changeset
866 emit_barrier ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
867 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
868
111
kono
parents: 67
diff changeset
869 /* Terminate a case Ada or switch (C) statement
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
870 in which ORIG_INDEX is the expression to be tested.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
871 If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
872 type as given in the source before any compiler conversions.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
873 Generate the code to test it and jump to the right place. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
874
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
875 void
111
kono
parents: 67
diff changeset
876 expand_case (gswitch *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
877 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
878 tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE;
111
kono
parents: 67
diff changeset
879 rtx_code_label *default_label;
kono
parents: 67
diff changeset
880 unsigned int count;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
881 int i;
111
kono
parents: 67
diff changeset
882 int ncases = gimple_switch_num_labels (stmt);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
883 tree index_expr = gimple_switch_index (stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
884 tree index_type = TREE_TYPE (index_expr);
111
kono
parents: 67
diff changeset
885 tree elt;
kono
parents: 67
diff changeset
886 basic_block bb = gimple_bb (stmt);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
887 gimple *def_stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
888
111
kono
parents: 67
diff changeset
889 auto_vec<simple_case_node> case_list;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
890
111
kono
parents: 67
diff changeset
891 /* An ERROR_MARK occurs for various reasons including invalid data type.
kono
parents: 67
diff changeset
892 ??? Can this still happen, with GIMPLE and all? */
kono
parents: 67
diff changeset
893 if (index_type == error_mark_node)
kono
parents: 67
diff changeset
894 return;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
895
111
kono
parents: 67
diff changeset
896 /* cleanup_tree_cfg removes all SWITCH_EXPR with their index
kono
parents: 67
diff changeset
897 expressions being INTEGER_CST. */
kono
parents: 67
diff changeset
898 gcc_assert (TREE_CODE (index_expr) != INTEGER_CST);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
899
111
kono
parents: 67
diff changeset
900 /* Optimization of switch statements with only one label has already
kono
parents: 67
diff changeset
901 occurred, so we should never see them at this point. */
kono
parents: 67
diff changeset
902 gcc_assert (ncases > 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
903
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
904 do_pending_stack_adjust ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
905
111
kono
parents: 67
diff changeset
906 /* Find the default case target label. */
kono
parents: 67
diff changeset
907 tree default_lab = CASE_LABEL (gimple_switch_default_label (stmt));
kono
parents: 67
diff changeset
908 default_label = jump_target_rtx (default_lab);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
909 basic_block default_bb = label_to_block (cfun, default_lab);
111
kono
parents: 67
diff changeset
910 edge default_edge = find_edge (bb, default_bb);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
911
111
kono
parents: 67
diff changeset
912 /* Get upper and lower bounds of case values. */
kono
parents: 67
diff changeset
913 elt = gimple_switch_label (stmt, 1);
kono
parents: 67
diff changeset
914 minval = fold_convert (index_type, CASE_LOW (elt));
kono
parents: 67
diff changeset
915 elt = gimple_switch_label (stmt, ncases - 1);
kono
parents: 67
diff changeset
916 if (CASE_HIGH (elt))
kono
parents: 67
diff changeset
917 maxval = fold_convert (index_type, CASE_HIGH (elt));
kono
parents: 67
diff changeset
918 else
kono
parents: 67
diff changeset
919 maxval = fold_convert (index_type, CASE_LOW (elt));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
920
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
921 /* Try to narrow the index type if it's larger than a word.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
922 That is mainly for -O0 where an equivalent optimization
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
923 done by forward propagation is not run and is aimed at
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
924 avoiding a call to a comparison routine of libgcc. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
925 if (TYPE_PRECISION (index_type) > BITS_PER_WORD
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
926 && TREE_CODE (index_expr) == SSA_NAME
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
927 && (def_stmt = SSA_NAME_DEF_STMT (index_expr))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
928 && is_gimple_assign (def_stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
929 && gimple_assign_rhs_code (def_stmt) == NOP_EXPR)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
930 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
931 tree inner_index_expr = gimple_assign_rhs1 (def_stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
932 tree inner_index_type = TREE_TYPE (inner_index_expr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
933
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
934 if (INTEGRAL_TYPE_P (inner_index_type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
935 && TYPE_PRECISION (inner_index_type) <= BITS_PER_WORD
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
936 && int_fits_type_p (minval, inner_index_type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
937 && int_fits_type_p (maxval, inner_index_type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
938 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
939 index_expr = inner_index_expr;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
940 index_type = inner_index_type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
941 minval = fold_convert (index_type, minval);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
942 maxval = fold_convert (index_type, maxval);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
943 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
944 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
945
111
kono
parents: 67
diff changeset
946 /* Compute span of values. */
kono
parents: 67
diff changeset
947 range = fold_build2 (MINUS_EXPR, index_type, maxval, minval);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
948
111
kono
parents: 67
diff changeset
949 /* Listify the labels queue and gather some numbers to decide
kono
parents: 67
diff changeset
950 how to expand this switch(). */
kono
parents: 67
diff changeset
951 count = 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
952
111
kono
parents: 67
diff changeset
953 for (i = ncases - 1; i >= 1; --i)
kono
parents: 67
diff changeset
954 {
kono
parents: 67
diff changeset
955 elt = gimple_switch_label (stmt, i);
kono
parents: 67
diff changeset
956 tree low = CASE_LOW (elt);
kono
parents: 67
diff changeset
957 gcc_assert (low);
kono
parents: 67
diff changeset
958 tree high = CASE_HIGH (elt);
kono
parents: 67
diff changeset
959 gcc_assert (! high || tree_int_cst_lt (low, high));
kono
parents: 67
diff changeset
960 tree lab = CASE_LABEL (elt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
961
111
kono
parents: 67
diff changeset
962 /* Count the elements.
kono
parents: 67
diff changeset
963 A range counts double, since it requires two compares. */
kono
parents: 67
diff changeset
964 count++;
kono
parents: 67
diff changeset
965 if (high)
kono
parents: 67
diff changeset
966 count++;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
967
111
kono
parents: 67
diff changeset
968 /* The bounds on the case range, LOW and HIGH, have to be converted
kono
parents: 67
diff changeset
969 to case's index type TYPE. Note that the original type of the
kono
parents: 67
diff changeset
970 case index in the source code is usually "lost" during
kono
parents: 67
diff changeset
971 gimplification due to type promotion, but the case labels retain the
kono
parents: 67
diff changeset
972 original type. Make sure to drop overflow flags. */
kono
parents: 67
diff changeset
973 low = fold_convert (index_type, low);
kono
parents: 67
diff changeset
974 if (TREE_OVERFLOW (low))
kono
parents: 67
diff changeset
975 low = wide_int_to_tree (index_type, wi::to_wide (low));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
976
111
kono
parents: 67
diff changeset
977 /* The canonical from of a case label in GIMPLE is that a simple case
kono
parents: 67
diff changeset
978 has an empty CASE_HIGH. For the casesi and tablejump expanders,
kono
parents: 67
diff changeset
979 the back ends want simple cases to have high == low. */
kono
parents: 67
diff changeset
980 if (! high)
kono
parents: 67
diff changeset
981 high = low;
kono
parents: 67
diff changeset
982 high = fold_convert (index_type, high);
kono
parents: 67
diff changeset
983 if (TREE_OVERFLOW (high))
kono
parents: 67
diff changeset
984 high = wide_int_to_tree (index_type, wi::to_wide (high));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
985
111
kono
parents: 67
diff changeset
986 case_list.safe_push (simple_case_node (low, high, lab));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
987 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
988
111
kono
parents: 67
diff changeset
989 /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
kono
parents: 67
diff changeset
990 destination, such as one with a default case only.
kono
parents: 67
diff changeset
991 It also removes cases that are out of range for the switch
kono
parents: 67
diff changeset
992 type, so we should never get a zero here. */
kono
parents: 67
diff changeset
993 gcc_assert (count > 0);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
994
111
kono
parents: 67
diff changeset
995 rtx_insn *before_case = get_last_insn ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
996
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
997 /* If the default case is unreachable, then set default_label to NULL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
998 so that we omit the range check when generating the dispatch table.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
999 We also remove the edge to the unreachable default case. The block
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1000 itself will be automatically removed later. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1001 if (EDGE_COUNT (default_edge->dest->succs) == 0
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1002 && gimple_seq_unreachable_p (bb_seq (default_edge->dest)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1003 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1004 default_label = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1005 remove_edge (default_edge);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1006 default_edge = NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1007 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1008
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1009 emit_case_dispatch_table (index_expr, index_type,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1010 case_list, default_label, default_edge,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1011 minval, maxval, range, bb);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1012
111
kono
parents: 67
diff changeset
1013 reorder_insns (NEXT_INSN (before_case), get_last_insn (), before_case);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1014
111
kono
parents: 67
diff changeset
1015 free_temp_slots ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1016 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1017
111
kono
parents: 67
diff changeset
1018 /* Expand the dispatch to a short decrement chain if there are few cases
kono
parents: 67
diff changeset
1019 to dispatch to. Likewise if neither casesi nor tablejump is available,
kono
parents: 67
diff changeset
1020 or if flag_jump_tables is set. Otherwise, expand as a casesi or a
kono
parents: 67
diff changeset
1021 tablejump. The index mode is always the mode of integer_type_node.
kono
parents: 67
diff changeset
1022 Trap if no case matches the index.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1023
111
kono
parents: 67
diff changeset
1024 DISPATCH_INDEX is the index expression to switch on. It should be a
kono
parents: 67
diff changeset
1025 memory or register operand.
kono
parents: 67
diff changeset
1026
kono
parents: 67
diff changeset
1027 DISPATCH_TABLE is a set of case labels. The set should be sorted in
kono
parents: 67
diff changeset
1028 ascending order, be contiguous, starting with value 0, and contain only
kono
parents: 67
diff changeset
1029 single-valued case labels. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1030
111
kono
parents: 67
diff changeset
1031 void
kono
parents: 67
diff changeset
1032 expand_sjlj_dispatch_table (rtx dispatch_index,
kono
parents: 67
diff changeset
1033 vec<tree> dispatch_table)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1034 {
111
kono
parents: 67
diff changeset
1035 tree index_type = integer_type_node;
kono
parents: 67
diff changeset
1036 machine_mode index_mode = TYPE_MODE (index_type);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1037
111
kono
parents: 67
diff changeset
1038 int ncases = dispatch_table.length ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1039
111
kono
parents: 67
diff changeset
1040 do_pending_stack_adjust ();
kono
parents: 67
diff changeset
1041 rtx_insn *before_case = get_last_insn ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1042
111
kono
parents: 67
diff changeset
1043 /* Expand as a decrement-chain if there are 5 or fewer dispatch
kono
parents: 67
diff changeset
1044 labels. This covers more than 98% of the cases in libjava,
kono
parents: 67
diff changeset
1045 and seems to be a reasonable compromise between the "old way"
kono
parents: 67
diff changeset
1046 of expanding as a decision tree or dispatch table vs. the "new
kono
parents: 67
diff changeset
1047 way" with decrement chain or dispatch table. */
kono
parents: 67
diff changeset
1048 if (dispatch_table.length () <= 5
kono
parents: 67
diff changeset
1049 || (!targetm.have_casesi () && !targetm.have_tablejump ())
kono
parents: 67
diff changeset
1050 || !flag_jump_tables)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1051 {
111
kono
parents: 67
diff changeset
1052 /* Expand the dispatch as a decrement chain:
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1053
111
kono
parents: 67
diff changeset
1054 "switch(index) {case 0: do_0; case 1: do_1; ...; case N: do_N;}"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1055
111
kono
parents: 67
diff changeset
1056 ==>
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1057
111
kono
parents: 67
diff changeset
1058 if (index == 0) do_0; else index--;
kono
parents: 67
diff changeset
1059 if (index == 0) do_1; else index--;
kono
parents: 67
diff changeset
1060 ...
kono
parents: 67
diff changeset
1061 if (index == 0) do_N; else index--;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1062
111
kono
parents: 67
diff changeset
1063 This is more efficient than a dispatch table on most machines.
kono
parents: 67
diff changeset
1064 The last "index--" is redundant but the code is trivially dead
kono
parents: 67
diff changeset
1065 and will be cleaned up by later passes. */
kono
parents: 67
diff changeset
1066 rtx index = copy_to_mode_reg (index_mode, dispatch_index);
kono
parents: 67
diff changeset
1067 rtx zero = CONST0_RTX (index_mode);
kono
parents: 67
diff changeset
1068 for (int i = 0; i < ncases; i++)
kono
parents: 67
diff changeset
1069 {
kono
parents: 67
diff changeset
1070 tree elt = dispatch_table[i];
kono
parents: 67
diff changeset
1071 rtx_code_label *lab = jump_target_rtx (CASE_LABEL (elt));
kono
parents: 67
diff changeset
1072 do_jump_if_equal (index_mode, index, zero, lab, 0,
kono
parents: 67
diff changeset
1073 profile_probability::uninitialized ());
kono
parents: 67
diff changeset
1074 force_expand_binop (index_mode, sub_optab,
kono
parents: 67
diff changeset
1075 index, CONST1_RTX (index_mode),
kono
parents: 67
diff changeset
1076 index, 0, OPTAB_DIRECT);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1077 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1078 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1079 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1080 {
111
kono
parents: 67
diff changeset
1081 /* Similar to expand_case, but much simpler. */
kono
parents: 67
diff changeset
1082 auto_vec<simple_case_node> case_list;
kono
parents: 67
diff changeset
1083 tree index_expr = make_tree (index_type, dispatch_index);
kono
parents: 67
diff changeset
1084 tree minval = build_int_cst (index_type, 0);
kono
parents: 67
diff changeset
1085 tree maxval = CASE_LOW (dispatch_table.last ());
kono
parents: 67
diff changeset
1086 tree range = maxval;
kono
parents: 67
diff changeset
1087 rtx_code_label *default_label = gen_label_rtx ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1088
111
kono
parents: 67
diff changeset
1089 for (int i = ncases - 1; i >= 0; --i)
kono
parents: 67
diff changeset
1090 {
kono
parents: 67
diff changeset
1091 tree elt = dispatch_table[i];
kono
parents: 67
diff changeset
1092 tree high = CASE_HIGH (elt);
kono
parents: 67
diff changeset
1093 if (high == NULL_TREE)
kono
parents: 67
diff changeset
1094 high = CASE_LOW (elt);
kono
parents: 67
diff changeset
1095 case_list.safe_push (simple_case_node (CASE_LOW (elt), high,
kono
parents: 67
diff changeset
1096 CASE_LABEL (elt)));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1097 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1098
111
kono
parents: 67
diff changeset
1099 emit_case_dispatch_table (index_expr, index_type,
kono
parents: 67
diff changeset
1100 case_list, default_label, NULL,
kono
parents: 67
diff changeset
1101 minval, maxval, range,
kono
parents: 67
diff changeset
1102 BLOCK_FOR_INSN (before_case));
kono
parents: 67
diff changeset
1103 emit_label (default_label);
kono
parents: 67
diff changeset
1104 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1105
111
kono
parents: 67
diff changeset
1106 /* Dispatching something not handled? Trap! */
kono
parents: 67
diff changeset
1107 expand_builtin_trap ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1108
111
kono
parents: 67
diff changeset
1109 reorder_insns (NEXT_INSN (before_case), get_last_insn (), before_case);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1110
111
kono
parents: 67
diff changeset
1111 free_temp_slots ();
kono
parents: 67
diff changeset
1112 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1113
111
kono
parents: 67
diff changeset
1114