* Add TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV target macro.
[official-gcc.git] / gcc / gimplify-me.c
blob5454e0cab2c4aa798d7c3bc0268ef93172143fe8
1 /* Tree lowering to gimple for middle end use only.
2 This converts the GENERIC functions-as-trees tree representation into
3 the GIMPLE form.
4 Copyright (C) 2013-2014 Free Software Foundation, Inc.
5 Major work done by Sebastian Pop <s.pop@laposte.net>,
6 Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tree.h"
28 #include "stmt.h"
29 #include "stor-layout.h"
30 #include "predict.h"
31 #include "vec.h"
32 #include "hashtab.h"
33 #include "hash-set.h"
34 #include "machmode.h"
35 #include "tm.h"
36 #include "hard-reg-set.h"
37 #include "input.h"
38 #include "function.h"
39 #include "basic-block.h"
40 #include "tree-ssa-alias.h"
41 #include "internal-fn.h"
42 #include "tree-eh.h"
43 #include "gimple-expr.h"
44 #include "is-a.h"
45 #include "gimple.h"
46 #include "gimple-iterator.h"
47 #include "gimplify.h"
48 #include "gimplify-me.h"
49 #include "gimple-ssa.h"
50 #include "stringpool.h"
51 #include "tree-ssanames.h"
54 /* Expand EXPR to list of gimple statements STMTS. GIMPLE_TEST_F specifies
55 the predicate that will hold for the result. If VAR is not NULL, make the
56 base variable of the final destination be VAR if suitable. */
58 tree
59 force_gimple_operand_1 (tree expr, gimple_seq *stmts,
60 gimple_predicate gimple_test_f, tree var)
62 enum gimplify_status ret;
63 location_t saved_location;
65 *stmts = NULL;
67 /* gimple_test_f might be more strict than is_gimple_val, make
68 sure we pass both. Just checking gimple_test_f doesn't work
69 because most gimple predicates do not work recursively. */
70 if (is_gimple_val (expr)
71 && (*gimple_test_f) (expr))
72 return expr;
74 push_gimplify_context (gimple_in_ssa_p (cfun), true);
75 saved_location = input_location;
76 input_location = UNKNOWN_LOCATION;
78 if (var)
80 if (gimple_in_ssa_p (cfun) && is_gimple_reg (var))
81 var = make_ssa_name (var);
82 expr = build2 (MODIFY_EXPR, TREE_TYPE (var), var, expr);
85 if (TREE_CODE (expr) != MODIFY_EXPR
86 && TREE_TYPE (expr) == void_type_node)
88 gimplify_and_add (expr, stmts);
89 expr = NULL_TREE;
91 else
93 ret = gimplify_expr (&expr, stmts, NULL, gimple_test_f, fb_rvalue);
94 gcc_assert (ret != GS_ERROR);
97 input_location = saved_location;
98 pop_gimplify_context (NULL);
100 return expr;
103 /* Expand EXPR to list of gimple statements STMTS. If SIMPLE is true,
104 force the result to be either ssa_name or an invariant, otherwise
105 just force it to be a rhs expression. If VAR is not NULL, make the
106 base variable of the final destination be VAR if suitable. */
108 tree
109 force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
111 return force_gimple_operand_1 (expr, stmts,
112 simple ? is_gimple_val : is_gimple_reg_rhs,
113 var);
116 /* Invoke force_gimple_operand_1 for EXPR with parameters GIMPLE_TEST_F
117 and VAR. If some statements are produced, emits them at GSI.
118 If BEFORE is true. the statements are appended before GSI, otherwise
119 they are appended after it. M specifies the way GSI moves after
120 insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING are the usual values). */
122 tree
123 force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr,
124 gimple_predicate gimple_test_f,
125 tree var, bool before,
126 enum gsi_iterator_update m)
128 gimple_seq stmts;
130 expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var);
132 if (!gimple_seq_empty_p (stmts))
134 if (before)
135 gsi_insert_seq_before (gsi, stmts, m);
136 else
137 gsi_insert_seq_after (gsi, stmts, m);
140 return expr;
143 /* Invoke force_gimple_operand_1 for EXPR with parameter VAR.
144 If SIMPLE is true, force the result to be either ssa_name or an invariant,
145 otherwise just force it to be a rhs expression. If some statements are
146 produced, emits them at GSI. If BEFORE is true, the statements are
147 appended before GSI, otherwise they are appended after it. M specifies
148 the way GSI moves after insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING
149 are the usual values). */
151 tree
152 force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
153 bool simple_p, tree var, bool before,
154 enum gsi_iterator_update m)
156 return force_gimple_operand_gsi_1 (gsi, expr,
157 simple_p
158 ? is_gimple_val : is_gimple_reg_rhs,
159 var, before, m);
162 /* Some transformations like inlining may invalidate the GIMPLE form
163 for operands. This function traverses all the operands in STMT and
164 gimplifies anything that is not a valid gimple operand. Any new
165 GIMPLE statements are inserted before *GSI_P. */
167 void
168 gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
170 size_t i, num_ops;
171 tree lhs;
172 gimple_seq pre = NULL;
173 gimple post_stmt = NULL;
175 push_gimplify_context (gimple_in_ssa_p (cfun));
177 switch (gimple_code (stmt))
179 case GIMPLE_COND:
181 gcond *cond_stmt = as_a <gcond *> (stmt);
182 gimplify_expr (gimple_cond_lhs_ptr (cond_stmt), &pre, NULL,
183 is_gimple_val, fb_rvalue);
184 gimplify_expr (gimple_cond_rhs_ptr (cond_stmt), &pre, NULL,
185 is_gimple_val, fb_rvalue);
187 break;
188 case GIMPLE_SWITCH:
189 gimplify_expr (gimple_switch_index_ptr (as_a <gswitch *> (stmt)),
190 &pre, NULL, is_gimple_val, fb_rvalue);
191 break;
192 case GIMPLE_OMP_ATOMIC_LOAD:
193 gimplify_expr (gimple_omp_atomic_load_rhs_ptr (
194 as_a <gomp_atomic_load *> (stmt)),
195 &pre, NULL, is_gimple_val, fb_rvalue);
196 break;
197 case GIMPLE_ASM:
199 gasm *asm_stmt = as_a <gasm *> (stmt);
200 size_t i, noutputs = gimple_asm_noutputs (asm_stmt);
201 const char *constraint, **oconstraints;
202 bool allows_mem, allows_reg, is_inout;
204 oconstraints
205 = (const char **) alloca ((noutputs) * sizeof (const char *));
206 for (i = 0; i < noutputs; i++)
208 tree op = gimple_asm_output_op (asm_stmt, i);
209 constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
210 oconstraints[i] = constraint;
211 parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
212 &allows_reg, &is_inout);
213 gimplify_expr (&TREE_VALUE (op), &pre, NULL,
214 is_inout ? is_gimple_min_lval : is_gimple_lvalue,
215 fb_lvalue | fb_mayfail);
217 for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
219 tree op = gimple_asm_input_op (asm_stmt, i);
220 constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
221 parse_input_constraint (&constraint, 0, 0, noutputs, 0,
222 oconstraints, &allows_mem, &allows_reg);
223 if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
224 allows_reg = 0;
225 if (!allows_reg && allows_mem)
226 gimplify_expr (&TREE_VALUE (op), &pre, NULL,
227 is_gimple_lvalue, fb_lvalue | fb_mayfail);
228 else
229 gimplify_expr (&TREE_VALUE (op), &pre, NULL,
230 is_gimple_asm_val, fb_rvalue);
233 break;
234 default:
235 /* NOTE: We start gimplifying operands from last to first to
236 make sure that side-effects on the RHS of calls, assignments
237 and ASMs are executed before the LHS. The ordering is not
238 important for other statements. */
239 num_ops = gimple_num_ops (stmt);
240 for (i = num_ops; i > 0; i--)
242 tree op = gimple_op (stmt, i - 1);
243 if (op == NULL_TREE)
244 continue;
245 if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt)))
246 gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue);
247 else if (i == 2
248 && is_gimple_assign (stmt)
249 && num_ops == 2
250 && get_gimple_rhs_class (gimple_expr_code (stmt))
251 == GIMPLE_SINGLE_RHS)
252 gimplify_expr (&op, &pre, NULL,
253 rhs_predicate_for (gimple_assign_lhs (stmt)),
254 fb_rvalue);
255 else if (i == 2 && is_gimple_call (stmt))
257 if (TREE_CODE (op) == FUNCTION_DECL)
258 continue;
259 gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue);
261 else
262 gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue);
263 gimple_set_op (stmt, i - 1, op);
266 lhs = gimple_get_lhs (stmt);
267 /* If the LHS changed it in a way that requires a simple RHS,
268 create temporary. */
269 if (lhs && !is_gimple_reg (lhs))
271 bool need_temp = false;
273 if (is_gimple_assign (stmt)
274 && num_ops == 2
275 && get_gimple_rhs_class (gimple_expr_code (stmt))
276 == GIMPLE_SINGLE_RHS)
277 gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL,
278 rhs_predicate_for (gimple_assign_lhs (stmt)),
279 fb_rvalue);
280 else if (is_gimple_reg (lhs))
282 if (is_gimple_reg_type (TREE_TYPE (lhs)))
284 if (is_gimple_call (stmt))
286 i = gimple_call_flags (stmt);
287 if ((i & ECF_LOOPING_CONST_OR_PURE)
288 || !(i & (ECF_CONST | ECF_PURE)))
289 need_temp = true;
291 if (stmt_can_throw_internal (stmt))
292 need_temp = true;
295 else
297 if (is_gimple_reg_type (TREE_TYPE (lhs)))
298 need_temp = true;
299 else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode)
301 if (is_gimple_call (stmt))
303 tree fndecl = gimple_call_fndecl (stmt);
305 if (!aggregate_value_p (TREE_TYPE (lhs), fndecl)
306 && !(fndecl && DECL_RESULT (fndecl)
307 && DECL_BY_REFERENCE (DECL_RESULT (fndecl))))
308 need_temp = true;
310 else
311 need_temp = true;
314 if (need_temp)
316 tree temp = create_tmp_reg (TREE_TYPE (lhs));
317 if (gimple_in_ssa_p (cfun))
318 temp = make_ssa_name (temp);
319 gimple_set_lhs (stmt, temp);
320 post_stmt = gimple_build_assign (lhs, temp);
323 break;
326 if (!gimple_seq_empty_p (pre))
327 gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
328 if (post_stmt)
329 gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
331 pop_gimplify_context (NULL);
333 update_stmt (stmt);