xref: /dflybsd-src/contrib/gcc-4.7/gcc/cfgexpand.c (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
1e4b17023SJohn Marino /* A pass for lowering trees to RTL.
2e4b17023SJohn Marino    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
3e4b17023SJohn Marino    Free Software Foundation, Inc.
4e4b17023SJohn Marino 
5e4b17023SJohn Marino This file is part of GCC.
6e4b17023SJohn Marino 
7e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
8e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
9e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
10e4b17023SJohn Marino any later version.
11e4b17023SJohn Marino 
12e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
13e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
14e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15e4b17023SJohn Marino GNU General Public License for more details.
16e4b17023SJohn Marino 
17e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20e4b17023SJohn Marino 
21e4b17023SJohn Marino #include "config.h"
22e4b17023SJohn Marino #include "system.h"
23e4b17023SJohn Marino #include "coretypes.h"
24e4b17023SJohn Marino #include "tm.h"
25e4b17023SJohn Marino #include "tree.h"
26e4b17023SJohn Marino #include "rtl.h"
27e4b17023SJohn Marino #include "tm_p.h"
28e4b17023SJohn Marino #include "basic-block.h"
29e4b17023SJohn Marino #include "function.h"
30e4b17023SJohn Marino #include "expr.h"
31e4b17023SJohn Marino #include "langhooks.h"
32e4b17023SJohn Marino #include "tree-flow.h"
33e4b17023SJohn Marino #include "timevar.h"
34e4b17023SJohn Marino #include "tree-dump.h"
35e4b17023SJohn Marino #include "tree-pass.h"
36e4b17023SJohn Marino #include "except.h"
37e4b17023SJohn Marino #include "flags.h"
38e4b17023SJohn Marino #include "diagnostic.h"
39e4b17023SJohn Marino #include "tree-pretty-print.h"
40e4b17023SJohn Marino #include "gimple-pretty-print.h"
41e4b17023SJohn Marino #include "toplev.h"
42e4b17023SJohn Marino #include "debug.h"
43e4b17023SJohn Marino #include "params.h"
44e4b17023SJohn Marino #include "tree-inline.h"
45e4b17023SJohn Marino #include "value-prof.h"
46e4b17023SJohn Marino #include "target.h"
47e4b17023SJohn Marino #include "ssaexpand.h"
48e4b17023SJohn Marino #include "bitmap.h"
49e4b17023SJohn Marino #include "sbitmap.h"
50e4b17023SJohn Marino #include "insn-attr.h" /* For INSN_SCHEDULING.  */
51e4b17023SJohn Marino 
52e4b17023SJohn Marino /* This variable holds information helping the rewriting of SSA trees
53e4b17023SJohn Marino    into RTL.  */
54e4b17023SJohn Marino struct ssaexpand SA;
55e4b17023SJohn Marino 
56e4b17023SJohn Marino /* This variable holds the currently expanded gimple statement for purposes
57e4b17023SJohn Marino    of comminucating the profile info to the builtin expanders.  */
58e4b17023SJohn Marino gimple currently_expanding_gimple_stmt;
59e4b17023SJohn Marino 
60e4b17023SJohn Marino static rtx expand_debug_expr (tree);
61e4b17023SJohn Marino 
62e4b17023SJohn Marino /* Return an expression tree corresponding to the RHS of GIMPLE
63e4b17023SJohn Marino    statement STMT.  */
64e4b17023SJohn Marino 
65e4b17023SJohn Marino tree
gimple_assign_rhs_to_tree(gimple stmt)66e4b17023SJohn Marino gimple_assign_rhs_to_tree (gimple stmt)
67e4b17023SJohn Marino {
68e4b17023SJohn Marino   tree t;
69e4b17023SJohn Marino   enum gimple_rhs_class grhs_class;
70e4b17023SJohn Marino 
71e4b17023SJohn Marino   grhs_class = get_gimple_rhs_class (gimple_expr_code (stmt));
72e4b17023SJohn Marino 
73e4b17023SJohn Marino   if (grhs_class == GIMPLE_TERNARY_RHS)
74e4b17023SJohn Marino     t = build3 (gimple_assign_rhs_code (stmt),
75e4b17023SJohn Marino 		TREE_TYPE (gimple_assign_lhs (stmt)),
76e4b17023SJohn Marino 		gimple_assign_rhs1 (stmt),
77e4b17023SJohn Marino 		gimple_assign_rhs2 (stmt),
78e4b17023SJohn Marino 		gimple_assign_rhs3 (stmt));
79e4b17023SJohn Marino   else if (grhs_class == GIMPLE_BINARY_RHS)
80e4b17023SJohn Marino     t = build2 (gimple_assign_rhs_code (stmt),
81e4b17023SJohn Marino 		TREE_TYPE (gimple_assign_lhs (stmt)),
82e4b17023SJohn Marino 		gimple_assign_rhs1 (stmt),
83e4b17023SJohn Marino 		gimple_assign_rhs2 (stmt));
84e4b17023SJohn Marino   else if (grhs_class == GIMPLE_UNARY_RHS)
85e4b17023SJohn Marino     t = build1 (gimple_assign_rhs_code (stmt),
86e4b17023SJohn Marino 		TREE_TYPE (gimple_assign_lhs (stmt)),
87e4b17023SJohn Marino 		gimple_assign_rhs1 (stmt));
88e4b17023SJohn Marino   else if (grhs_class == GIMPLE_SINGLE_RHS)
89e4b17023SJohn Marino     {
90e4b17023SJohn Marino       t = gimple_assign_rhs1 (stmt);
91e4b17023SJohn Marino       /* Avoid modifying this tree in place below.  */
92e4b17023SJohn Marino       if ((gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (t)
93e4b17023SJohn Marino 	   && gimple_location (stmt) != EXPR_LOCATION (t))
94e4b17023SJohn Marino 	  || (gimple_block (stmt)
95e4b17023SJohn Marino 	      && currently_expanding_to_rtl
96e4b17023SJohn Marino 	      && EXPR_P (t)
97e4b17023SJohn Marino 	      && gimple_block (stmt) != TREE_BLOCK (t)))
98e4b17023SJohn Marino 	t = copy_node (t);
99e4b17023SJohn Marino     }
100e4b17023SJohn Marino   else
101e4b17023SJohn Marino     gcc_unreachable ();
102e4b17023SJohn Marino 
103e4b17023SJohn Marino   if (gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (t))
104e4b17023SJohn Marino     SET_EXPR_LOCATION (t, gimple_location (stmt));
105e4b17023SJohn Marino   if (gimple_block (stmt) && currently_expanding_to_rtl && EXPR_P (t))
106e4b17023SJohn Marino     TREE_BLOCK (t) = gimple_block (stmt);
107e4b17023SJohn Marino 
108e4b17023SJohn Marino   return t;
109e4b17023SJohn Marino }
110e4b17023SJohn Marino 
111e4b17023SJohn Marino 
112e4b17023SJohn Marino #ifndef STACK_ALIGNMENT_NEEDED
113e4b17023SJohn Marino #define STACK_ALIGNMENT_NEEDED 1
114e4b17023SJohn Marino #endif
115e4b17023SJohn Marino 
116e4b17023SJohn Marino #define SSAVAR(x) (TREE_CODE (x) == SSA_NAME ? SSA_NAME_VAR (x) : x)
117e4b17023SJohn Marino 
118e4b17023SJohn Marino /* Associate declaration T with storage space X.  If T is no
119e4b17023SJohn Marino    SSA name this is exactly SET_DECL_RTL, otherwise make the
120e4b17023SJohn Marino    partition of T associated with X.  */
121e4b17023SJohn Marino static inline void
set_rtl(tree t,rtx x)122e4b17023SJohn Marino set_rtl (tree t, rtx x)
123e4b17023SJohn Marino {
124e4b17023SJohn Marino   if (TREE_CODE (t) == SSA_NAME)
125e4b17023SJohn Marino     {
126e4b17023SJohn Marino       SA.partition_to_pseudo[var_to_partition (SA.map, t)] = x;
127e4b17023SJohn Marino       if (x && !MEM_P (x))
128e4b17023SJohn Marino 	set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (t), x);
129e4b17023SJohn Marino       /* For the benefit of debug information at -O0 (where vartracking
130e4b17023SJohn Marino          doesn't run) record the place also in the base DECL if it's
131e4b17023SJohn Marino 	 a normal variable (not a parameter).  */
132e4b17023SJohn Marino       if (x && x != pc_rtx && TREE_CODE (SSA_NAME_VAR (t)) == VAR_DECL)
133e4b17023SJohn Marino 	{
134e4b17023SJohn Marino 	  tree var = SSA_NAME_VAR (t);
135e4b17023SJohn Marino 	  /* If we don't yet have something recorded, just record it now.  */
136e4b17023SJohn Marino 	  if (!DECL_RTL_SET_P (var))
137e4b17023SJohn Marino 	    SET_DECL_RTL (var, x);
138e4b17023SJohn Marino 	  /* If we have it set already to "multiple places" don't
139e4b17023SJohn Marino 	     change this.  */
140e4b17023SJohn Marino 	  else if (DECL_RTL (var) == pc_rtx)
141e4b17023SJohn Marino 	    ;
142e4b17023SJohn Marino 	  /* If we have something recorded and it's not the same place
143e4b17023SJohn Marino 	     as we want to record now, we have multiple partitions for the
144e4b17023SJohn Marino 	     same base variable, with different places.  We can't just
145e4b17023SJohn Marino 	     randomly chose one, hence we have to say that we don't know.
146e4b17023SJohn Marino 	     This only happens with optimization, and there var-tracking
147e4b17023SJohn Marino 	     will figure out the right thing.  */
148e4b17023SJohn Marino 	  else if (DECL_RTL (var) != x)
149e4b17023SJohn Marino 	    SET_DECL_RTL (var, pc_rtx);
150e4b17023SJohn Marino 	}
151e4b17023SJohn Marino     }
152e4b17023SJohn Marino   else
153e4b17023SJohn Marino     SET_DECL_RTL (t, x);
154e4b17023SJohn Marino }
155e4b17023SJohn Marino 
156e4b17023SJohn Marino /* This structure holds data relevant to one variable that will be
157e4b17023SJohn Marino    placed in a stack slot.  */
158e4b17023SJohn Marino struct stack_var
159e4b17023SJohn Marino {
160e4b17023SJohn Marino   /* The Variable.  */
161e4b17023SJohn Marino   tree decl;
162e4b17023SJohn Marino 
163e4b17023SJohn Marino   /* Initially, the size of the variable.  Later, the size of the partition,
164e4b17023SJohn Marino      if this variable becomes it's partition's representative.  */
165e4b17023SJohn Marino   HOST_WIDE_INT size;
166e4b17023SJohn Marino 
167e4b17023SJohn Marino   /* The *byte* alignment required for this variable.  Or as, with the
168e4b17023SJohn Marino      size, the alignment for this partition.  */
169e4b17023SJohn Marino   unsigned int alignb;
170e4b17023SJohn Marino 
171e4b17023SJohn Marino   /* The partition representative.  */
172e4b17023SJohn Marino   size_t representative;
173e4b17023SJohn Marino 
174e4b17023SJohn Marino   /* The next stack variable in the partition, or EOC.  */
175e4b17023SJohn Marino   size_t next;
176e4b17023SJohn Marino 
177e4b17023SJohn Marino   /* The numbers of conflicting stack variables.  */
178e4b17023SJohn Marino   bitmap conflicts;
179e4b17023SJohn Marino };
180e4b17023SJohn Marino 
181e4b17023SJohn Marino #define EOC  ((size_t)-1)
182e4b17023SJohn Marino 
183e4b17023SJohn Marino /* We have an array of such objects while deciding allocation.  */
184e4b17023SJohn Marino static struct stack_var *stack_vars;
185e4b17023SJohn Marino static size_t stack_vars_alloc;
186e4b17023SJohn Marino static size_t stack_vars_num;
187e4b17023SJohn Marino static struct pointer_map_t *decl_to_stack_part;
188e4b17023SJohn Marino 
189e4b17023SJohn Marino /* An array of indices such that stack_vars[stack_vars_sorted[i]].size
190e4b17023SJohn Marino    is non-decreasing.  */
191e4b17023SJohn Marino static size_t *stack_vars_sorted;
192e4b17023SJohn Marino 
193e4b17023SJohn Marino /* The phase of the stack frame.  This is the known misalignment of
194e4b17023SJohn Marino    virtual_stack_vars_rtx from PREFERRED_STACK_BOUNDARY.  That is,
195e4b17023SJohn Marino    (frame_offset+frame_phase) % PREFERRED_STACK_BOUNDARY == 0.  */
196e4b17023SJohn Marino static int frame_phase;
197e4b17023SJohn Marino 
198e4b17023SJohn Marino /* Used during expand_used_vars to remember if we saw any decls for
199e4b17023SJohn Marino    which we'd like to enable stack smashing protection.  */
200e4b17023SJohn Marino static bool has_protected_decls;
201e4b17023SJohn Marino 
202e4b17023SJohn Marino /* Used during expand_used_vars.  Remember if we say a character buffer
203e4b17023SJohn Marino    smaller than our cutoff threshold.  Used for -Wstack-protector.  */
204e4b17023SJohn Marino static bool has_short_buffer;
205e4b17023SJohn Marino 
206e4b17023SJohn Marino /* Compute the byte alignment to use for DECL.  Ignore alignment
207e4b17023SJohn Marino    we can't do with expected alignment of the stack boundary.  */
208e4b17023SJohn Marino 
209e4b17023SJohn Marino static unsigned int
align_local_variable(tree decl)210e4b17023SJohn Marino align_local_variable (tree decl)
211e4b17023SJohn Marino {
212e4b17023SJohn Marino   unsigned int align = LOCAL_DECL_ALIGNMENT (decl);
213e4b17023SJohn Marino   DECL_ALIGN (decl) = align;
214e4b17023SJohn Marino   return align / BITS_PER_UNIT;
215e4b17023SJohn Marino }
216e4b17023SJohn Marino 
217e4b17023SJohn Marino /* Allocate SIZE bytes at byte alignment ALIGN from the stack frame.
218e4b17023SJohn Marino    Return the frame offset.  */
219e4b17023SJohn Marino 
220e4b17023SJohn Marino static HOST_WIDE_INT
alloc_stack_frame_space(HOST_WIDE_INT size,unsigned HOST_WIDE_INT align)221e4b17023SJohn Marino alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
222e4b17023SJohn Marino {
223e4b17023SJohn Marino   HOST_WIDE_INT offset, new_frame_offset;
224e4b17023SJohn Marino 
225e4b17023SJohn Marino   new_frame_offset = frame_offset;
226e4b17023SJohn Marino   if (FRAME_GROWS_DOWNWARD)
227e4b17023SJohn Marino     {
228e4b17023SJohn Marino       new_frame_offset -= size + frame_phase;
229e4b17023SJohn Marino       new_frame_offset &= -align;
230e4b17023SJohn Marino       new_frame_offset += frame_phase;
231e4b17023SJohn Marino       offset = new_frame_offset;
232e4b17023SJohn Marino     }
233e4b17023SJohn Marino   else
234e4b17023SJohn Marino     {
235e4b17023SJohn Marino       new_frame_offset -= frame_phase;
236e4b17023SJohn Marino       new_frame_offset += align - 1;
237e4b17023SJohn Marino       new_frame_offset &= -align;
238e4b17023SJohn Marino       new_frame_offset += frame_phase;
239e4b17023SJohn Marino       offset = new_frame_offset;
240e4b17023SJohn Marino       new_frame_offset += size;
241e4b17023SJohn Marino     }
242e4b17023SJohn Marino   frame_offset = new_frame_offset;
243e4b17023SJohn Marino 
244e4b17023SJohn Marino   if (frame_offset_overflow (frame_offset, cfun->decl))
245e4b17023SJohn Marino     frame_offset = offset = 0;
246e4b17023SJohn Marino 
247e4b17023SJohn Marino   return offset;
248e4b17023SJohn Marino }
249e4b17023SJohn Marino 
250e4b17023SJohn Marino /* Accumulate DECL into STACK_VARS.  */
251e4b17023SJohn Marino 
252e4b17023SJohn Marino static void
add_stack_var(tree decl)253e4b17023SJohn Marino add_stack_var (tree decl)
254e4b17023SJohn Marino {
255e4b17023SJohn Marino   struct stack_var *v;
256e4b17023SJohn Marino 
257e4b17023SJohn Marino   if (stack_vars_num >= stack_vars_alloc)
258e4b17023SJohn Marino     {
259e4b17023SJohn Marino       if (stack_vars_alloc)
260e4b17023SJohn Marino 	stack_vars_alloc = stack_vars_alloc * 3 / 2;
261e4b17023SJohn Marino       else
262e4b17023SJohn Marino 	stack_vars_alloc = 32;
263e4b17023SJohn Marino       stack_vars
264e4b17023SJohn Marino 	= XRESIZEVEC (struct stack_var, stack_vars, stack_vars_alloc);
265e4b17023SJohn Marino     }
266e4b17023SJohn Marino   if (!decl_to_stack_part)
267e4b17023SJohn Marino     decl_to_stack_part = pointer_map_create ();
268e4b17023SJohn Marino 
269e4b17023SJohn Marino   v = &stack_vars[stack_vars_num];
270e4b17023SJohn Marino   * (size_t *)pointer_map_insert (decl_to_stack_part, decl) = stack_vars_num;
271e4b17023SJohn Marino 
272e4b17023SJohn Marino   v->decl = decl;
273e4b17023SJohn Marino   v->size = tree_low_cst (DECL_SIZE_UNIT (SSAVAR (decl)), 1);
274e4b17023SJohn Marino   /* Ensure that all variables have size, so that &a != &b for any two
275e4b17023SJohn Marino      variables that are simultaneously live.  */
276e4b17023SJohn Marino   if (v->size == 0)
277e4b17023SJohn Marino     v->size = 1;
278e4b17023SJohn Marino   v->alignb = align_local_variable (SSAVAR (decl));
279e4b17023SJohn Marino   /* An alignment of zero can mightily confuse us later.  */
280e4b17023SJohn Marino   gcc_assert (v->alignb != 0);
281e4b17023SJohn Marino 
282e4b17023SJohn Marino   /* All variables are initially in their own partition.  */
283e4b17023SJohn Marino   v->representative = stack_vars_num;
284e4b17023SJohn Marino   v->next = EOC;
285e4b17023SJohn Marino 
286e4b17023SJohn Marino   /* All variables initially conflict with no other.  */
287e4b17023SJohn Marino   v->conflicts = NULL;
288e4b17023SJohn Marino 
289e4b17023SJohn Marino   /* Ensure that this decl doesn't get put onto the list twice.  */
290e4b17023SJohn Marino   set_rtl (decl, pc_rtx);
291e4b17023SJohn Marino 
292e4b17023SJohn Marino   stack_vars_num++;
293e4b17023SJohn Marino }
294e4b17023SJohn Marino 
295e4b17023SJohn Marino /* Make the decls associated with luid's X and Y conflict.  */
296e4b17023SJohn Marino 
297e4b17023SJohn Marino static void
add_stack_var_conflict(size_t x,size_t y)298e4b17023SJohn Marino add_stack_var_conflict (size_t x, size_t y)
299e4b17023SJohn Marino {
300e4b17023SJohn Marino   struct stack_var *a = &stack_vars[x];
301e4b17023SJohn Marino   struct stack_var *b = &stack_vars[y];
302e4b17023SJohn Marino   if (!a->conflicts)
303e4b17023SJohn Marino     a->conflicts = BITMAP_ALLOC (NULL);
304e4b17023SJohn Marino   if (!b->conflicts)
305e4b17023SJohn Marino     b->conflicts = BITMAP_ALLOC (NULL);
306e4b17023SJohn Marino   bitmap_set_bit (a->conflicts, y);
307e4b17023SJohn Marino   bitmap_set_bit (b->conflicts, x);
308e4b17023SJohn Marino }
309e4b17023SJohn Marino 
310e4b17023SJohn Marino /* Check whether the decls associated with luid's X and Y conflict.  */
311e4b17023SJohn Marino 
312e4b17023SJohn Marino static bool
stack_var_conflict_p(size_t x,size_t y)313e4b17023SJohn Marino stack_var_conflict_p (size_t x, size_t y)
314e4b17023SJohn Marino {
315e4b17023SJohn Marino   struct stack_var *a = &stack_vars[x];
316e4b17023SJohn Marino   struct stack_var *b = &stack_vars[y];
317e4b17023SJohn Marino   if (x == y)
318e4b17023SJohn Marino     return false;
319e4b17023SJohn Marino   /* Partitions containing an SSA name result from gimple registers
320e4b17023SJohn Marino      with things like unsupported modes.  They are top-level and
321e4b17023SJohn Marino      hence conflict with everything else.  */
322e4b17023SJohn Marino   if (TREE_CODE (a->decl) == SSA_NAME || TREE_CODE (b->decl) == SSA_NAME)
323e4b17023SJohn Marino     return true;
324e4b17023SJohn Marino 
325e4b17023SJohn Marino   if (!a->conflicts || !b->conflicts)
326e4b17023SJohn Marino     return false;
327e4b17023SJohn Marino   return bitmap_bit_p (a->conflicts, y);
328e4b17023SJohn Marino }
329e4b17023SJohn Marino 
330e4b17023SJohn Marino /* Returns true if TYPE is or contains a union type.  */
331e4b17023SJohn Marino 
332e4b17023SJohn Marino static bool
aggregate_contains_union_type(tree type)333e4b17023SJohn Marino aggregate_contains_union_type (tree type)
334e4b17023SJohn Marino {
335e4b17023SJohn Marino   tree field;
336e4b17023SJohn Marino 
337e4b17023SJohn Marino   if (TREE_CODE (type) == UNION_TYPE
338e4b17023SJohn Marino       || TREE_CODE (type) == QUAL_UNION_TYPE)
339e4b17023SJohn Marino     return true;
340e4b17023SJohn Marino   if (TREE_CODE (type) == ARRAY_TYPE)
341e4b17023SJohn Marino     return aggregate_contains_union_type (TREE_TYPE (type));
342e4b17023SJohn Marino   if (TREE_CODE (type) != RECORD_TYPE)
343e4b17023SJohn Marino     return false;
344e4b17023SJohn Marino 
345e4b17023SJohn Marino   for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
346e4b17023SJohn Marino     if (TREE_CODE (field) == FIELD_DECL)
347e4b17023SJohn Marino       if (aggregate_contains_union_type (TREE_TYPE (field)))
348e4b17023SJohn Marino 	return true;
349e4b17023SJohn Marino 
350e4b17023SJohn Marino   return false;
351e4b17023SJohn Marino }
352e4b17023SJohn Marino 
353e4b17023SJohn Marino /* A subroutine of expand_used_vars.  If two variables X and Y have alias
354e4b17023SJohn Marino    sets that do not conflict, then do add a conflict for these variables
355e4b17023SJohn Marino    in the interference graph.  We also need to make sure to add conflicts
356e4b17023SJohn Marino    for union containing structures.  Else RTL alias analysis comes along
357e4b17023SJohn Marino    and due to type based aliasing rules decides that for two overlapping
358e4b17023SJohn Marino    union temporaries { short s; int i; } accesses to the same mem through
359e4b17023SJohn Marino    different types may not alias and happily reorders stores across
360e4b17023SJohn Marino    life-time boundaries of the temporaries (See PR25654).  */
361e4b17023SJohn Marino 
362e4b17023SJohn Marino static void
add_alias_set_conflicts(void)363e4b17023SJohn Marino add_alias_set_conflicts (void)
364e4b17023SJohn Marino {
365e4b17023SJohn Marino   size_t i, j, n = stack_vars_num;
366e4b17023SJohn Marino 
367e4b17023SJohn Marino   for (i = 0; i < n; ++i)
368e4b17023SJohn Marino     {
369e4b17023SJohn Marino       tree type_i = TREE_TYPE (stack_vars[i].decl);
370e4b17023SJohn Marino       bool aggr_i = AGGREGATE_TYPE_P (type_i);
371e4b17023SJohn Marino       bool contains_union;
372e4b17023SJohn Marino 
373e4b17023SJohn Marino       contains_union = aggregate_contains_union_type (type_i);
374e4b17023SJohn Marino       for (j = 0; j < i; ++j)
375e4b17023SJohn Marino 	{
376e4b17023SJohn Marino 	  tree type_j = TREE_TYPE (stack_vars[j].decl);
377e4b17023SJohn Marino 	  bool aggr_j = AGGREGATE_TYPE_P (type_j);
378e4b17023SJohn Marino 	  if (aggr_i != aggr_j
379e4b17023SJohn Marino 	      /* Either the objects conflict by means of type based
380e4b17023SJohn Marino 		 aliasing rules, or we need to add a conflict.  */
381e4b17023SJohn Marino 	      || !objects_must_conflict_p (type_i, type_j)
382e4b17023SJohn Marino 	      /* In case the types do not conflict ensure that access
383e4b17023SJohn Marino 		 to elements will conflict.  In case of unions we have
384e4b17023SJohn Marino 		 to be careful as type based aliasing rules may say
385e4b17023SJohn Marino 		 access to the same memory does not conflict.  So play
386e4b17023SJohn Marino 		 safe and add a conflict in this case when
387e4b17023SJohn Marino                  -fstrict-aliasing is used.  */
388e4b17023SJohn Marino               || (contains_union && flag_strict_aliasing))
389e4b17023SJohn Marino 	    add_stack_var_conflict (i, j);
390e4b17023SJohn Marino 	}
391e4b17023SJohn Marino     }
392e4b17023SJohn Marino }
393e4b17023SJohn Marino 
394e4b17023SJohn Marino /* Callback for walk_stmt_ops.  If OP is a decl touched by add_stack_var
395e4b17023SJohn Marino    enter its partition number into bitmap DATA.  */
396e4b17023SJohn Marino 
397e4b17023SJohn Marino static bool
visit_op(gimple stmt ATTRIBUTE_UNUSED,tree op,void * data)398e4b17023SJohn Marino visit_op (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
399e4b17023SJohn Marino {
400e4b17023SJohn Marino   bitmap active = (bitmap)data;
401e4b17023SJohn Marino   op = get_base_address (op);
402e4b17023SJohn Marino   if (op
403e4b17023SJohn Marino       && DECL_P (op)
404e4b17023SJohn Marino       && DECL_RTL_IF_SET (op) == pc_rtx)
405e4b17023SJohn Marino     {
406e4b17023SJohn Marino       size_t *v = (size_t *) pointer_map_contains (decl_to_stack_part, op);
407e4b17023SJohn Marino       if (v)
408e4b17023SJohn Marino 	bitmap_set_bit (active, *v);
409e4b17023SJohn Marino     }
410e4b17023SJohn Marino   return false;
411e4b17023SJohn Marino }
412e4b17023SJohn Marino 
413e4b17023SJohn Marino /* Callback for walk_stmt_ops.  If OP is a decl touched by add_stack_var
414e4b17023SJohn Marino    record conflicts between it and all currently active other partitions
415e4b17023SJohn Marino    from bitmap DATA.  */
416e4b17023SJohn Marino 
417e4b17023SJohn Marino static bool
visit_conflict(gimple stmt ATTRIBUTE_UNUSED,tree op,void * data)418e4b17023SJohn Marino visit_conflict (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
419e4b17023SJohn Marino {
420e4b17023SJohn Marino   bitmap active = (bitmap)data;
421e4b17023SJohn Marino   op = get_base_address (op);
422e4b17023SJohn Marino   if (op
423e4b17023SJohn Marino       && DECL_P (op)
424e4b17023SJohn Marino       && DECL_RTL_IF_SET (op) == pc_rtx)
425e4b17023SJohn Marino     {
426e4b17023SJohn Marino       size_t *v =
427e4b17023SJohn Marino 	(size_t *) pointer_map_contains (decl_to_stack_part, op);
428e4b17023SJohn Marino       if (v && bitmap_set_bit (active, *v))
429e4b17023SJohn Marino 	{
430e4b17023SJohn Marino 	  size_t num = *v;
431e4b17023SJohn Marino 	  bitmap_iterator bi;
432e4b17023SJohn Marino 	  unsigned i;
433e4b17023SJohn Marino 	  gcc_assert (num < stack_vars_num);
434e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_BITMAP (active, 0, i, bi)
435e4b17023SJohn Marino 	    add_stack_var_conflict (num, i);
436e4b17023SJohn Marino 	}
437e4b17023SJohn Marino     }
438e4b17023SJohn Marino   return false;
439e4b17023SJohn Marino }
440e4b17023SJohn Marino 
441e4b17023SJohn Marino /* Helper routine for add_scope_conflicts, calculating the active partitions
442e4b17023SJohn Marino    at the end of BB, leaving the result in WORK.  We're called to generate
443e4b17023SJohn Marino    conflicts when FOR_CONFLICT is true, otherwise we're just tracking
444e4b17023SJohn Marino    liveness.  */
445e4b17023SJohn Marino 
446e4b17023SJohn Marino static void
add_scope_conflicts_1(basic_block bb,bitmap work,bool for_conflict)447e4b17023SJohn Marino add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict)
448e4b17023SJohn Marino {
449e4b17023SJohn Marino   edge e;
450e4b17023SJohn Marino   edge_iterator ei;
451e4b17023SJohn Marino   gimple_stmt_iterator gsi;
452e4b17023SJohn Marino   bool (*visit)(gimple, tree, void *);
453e4b17023SJohn Marino 
454e4b17023SJohn Marino   bitmap_clear (work);
455e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, bb->preds)
456e4b17023SJohn Marino     bitmap_ior_into (work, (bitmap)e->src->aux);
457e4b17023SJohn Marino 
458e4b17023SJohn Marino   visit = visit_op;
459e4b17023SJohn Marino 
460e4b17023SJohn Marino   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
461e4b17023SJohn Marino     {
462e4b17023SJohn Marino       gimple stmt = gsi_stmt (gsi);
463e4b17023SJohn Marino       walk_stmt_load_store_addr_ops (stmt, work, NULL, NULL, visit);
464e4b17023SJohn Marino     }
465e4b17023SJohn Marino   for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
466e4b17023SJohn Marino     {
467e4b17023SJohn Marino       gimple stmt = gsi_stmt (gsi);
468e4b17023SJohn Marino 
469e4b17023SJohn Marino       if (gimple_clobber_p (stmt))
470e4b17023SJohn Marino 	{
471e4b17023SJohn Marino 	  tree lhs = gimple_assign_lhs (stmt);
472e4b17023SJohn Marino 	  size_t *v;
473e4b17023SJohn Marino 	  /* Nested function lowering might introduce LHSs
474e4b17023SJohn Marino 	     that are COMPONENT_REFs.  */
475e4b17023SJohn Marino 	  if (TREE_CODE (lhs) != VAR_DECL)
476e4b17023SJohn Marino 	    continue;
477e4b17023SJohn Marino 	  if (DECL_RTL_IF_SET (lhs) == pc_rtx
478e4b17023SJohn Marino 	      && (v = (size_t *)
479e4b17023SJohn Marino 		  pointer_map_contains (decl_to_stack_part, lhs)))
480e4b17023SJohn Marino 	    bitmap_clear_bit (work, *v);
481e4b17023SJohn Marino 	}
482e4b17023SJohn Marino       else if (!is_gimple_debug (stmt))
483e4b17023SJohn Marino 	{
484e4b17023SJohn Marino 	  if (for_conflict
485e4b17023SJohn Marino 	      && visit == visit_op)
486e4b17023SJohn Marino 	    {
487e4b17023SJohn Marino 	      /* If this is the first real instruction in this BB we need
488e4b17023SJohn Marino 	         to add conflicts for everything live at this point now.
489e4b17023SJohn Marino 		 Unlike classical liveness for named objects we can't
490e4b17023SJohn Marino 		 rely on seeing a def/use of the names we're interested in.
491e4b17023SJohn Marino 		 There might merely be indirect loads/stores.  We'd not add any
492e4b17023SJohn Marino 		 conflicts for such partitions.  */
493e4b17023SJohn Marino 	      bitmap_iterator bi;
494e4b17023SJohn Marino 	      unsigned i;
495e4b17023SJohn Marino 	      EXECUTE_IF_SET_IN_BITMAP (work, 0, i, bi)
496e4b17023SJohn Marino 		{
497e4b17023SJohn Marino 		  unsigned j;
498e4b17023SJohn Marino 		  bitmap_iterator bj;
499e4b17023SJohn Marino 		  EXECUTE_IF_SET_IN_BITMAP (work, i + 1, j, bj)
500e4b17023SJohn Marino 		    add_stack_var_conflict (i, j);
501e4b17023SJohn Marino 		}
502e4b17023SJohn Marino 	      visit = visit_conflict;
503e4b17023SJohn Marino 	    }
504e4b17023SJohn Marino 	  walk_stmt_load_store_addr_ops (stmt, work, visit, visit, visit);
505e4b17023SJohn Marino 	}
506e4b17023SJohn Marino     }
507e4b17023SJohn Marino }
508e4b17023SJohn Marino 
509e4b17023SJohn Marino /* Generate stack partition conflicts between all partitions that are
510e4b17023SJohn Marino    simultaneously live.  */
511e4b17023SJohn Marino 
512e4b17023SJohn Marino static void
add_scope_conflicts(void)513e4b17023SJohn Marino add_scope_conflicts (void)
514e4b17023SJohn Marino {
515e4b17023SJohn Marino   basic_block bb;
516e4b17023SJohn Marino   bool changed;
517e4b17023SJohn Marino   bitmap work = BITMAP_ALLOC (NULL);
518e4b17023SJohn Marino 
519e4b17023SJohn Marino   /* We approximate the live range of a stack variable by taking the first
520e4b17023SJohn Marino      mention of its name as starting point(s), and by the end-of-scope
521e4b17023SJohn Marino      death clobber added by gimplify as ending point(s) of the range.
522e4b17023SJohn Marino      This overapproximates in the case we for instance moved an address-taken
523e4b17023SJohn Marino      operation upward, without also moving a dereference to it upwards.
524e4b17023SJohn Marino      But it's conservatively correct as a variable never can hold values
525e4b17023SJohn Marino      before its name is mentioned at least once.
526e4b17023SJohn Marino 
527e4b17023SJohn Marino      We then do a mostly classical bitmap liveness algorithm.  */
528e4b17023SJohn Marino 
529e4b17023SJohn Marino   FOR_ALL_BB (bb)
530e4b17023SJohn Marino     bb->aux = BITMAP_ALLOC (NULL);
531e4b17023SJohn Marino 
532e4b17023SJohn Marino   changed = true;
533e4b17023SJohn Marino   while (changed)
534e4b17023SJohn Marino     {
535e4b17023SJohn Marino       changed = false;
536e4b17023SJohn Marino       FOR_EACH_BB (bb)
537e4b17023SJohn Marino 	{
538e4b17023SJohn Marino 	  bitmap active = (bitmap)bb->aux;
539e4b17023SJohn Marino 	  add_scope_conflicts_1 (bb, work, false);
540e4b17023SJohn Marino 	  if (bitmap_ior_into (active, work))
541e4b17023SJohn Marino 	    changed = true;
542e4b17023SJohn Marino 	}
543e4b17023SJohn Marino     }
544e4b17023SJohn Marino 
545e4b17023SJohn Marino   FOR_EACH_BB (bb)
546e4b17023SJohn Marino     add_scope_conflicts_1 (bb, work, true);
547e4b17023SJohn Marino 
548e4b17023SJohn Marino   BITMAP_FREE (work);
549e4b17023SJohn Marino   FOR_ALL_BB (bb)
550e4b17023SJohn Marino     BITMAP_FREE (bb->aux);
551e4b17023SJohn Marino }
552e4b17023SJohn Marino 
553e4b17023SJohn Marino /* A subroutine of partition_stack_vars.  A comparison function for qsort,
554e4b17023SJohn Marino    sorting an array of indices by the properties of the object.  */
555e4b17023SJohn Marino 
556e4b17023SJohn Marino static int
stack_var_cmp(const void * a,const void * b)557e4b17023SJohn Marino stack_var_cmp (const void *a, const void *b)
558e4b17023SJohn Marino {
559e4b17023SJohn Marino   size_t ia = *(const size_t *)a;
560e4b17023SJohn Marino   size_t ib = *(const size_t *)b;
561e4b17023SJohn Marino   unsigned int aligna = stack_vars[ia].alignb;
562e4b17023SJohn Marino   unsigned int alignb = stack_vars[ib].alignb;
563e4b17023SJohn Marino   HOST_WIDE_INT sizea = stack_vars[ia].size;
564e4b17023SJohn Marino   HOST_WIDE_INT sizeb = stack_vars[ib].size;
565e4b17023SJohn Marino   tree decla = stack_vars[ia].decl;
566e4b17023SJohn Marino   tree declb = stack_vars[ib].decl;
567e4b17023SJohn Marino   bool largea, largeb;
568e4b17023SJohn Marino   unsigned int uida, uidb;
569e4b17023SJohn Marino 
570e4b17023SJohn Marino   /* Primary compare on "large" alignment.  Large comes first.  */
571e4b17023SJohn Marino   largea = (aligna * BITS_PER_UNIT > MAX_SUPPORTED_STACK_ALIGNMENT);
572e4b17023SJohn Marino   largeb = (alignb * BITS_PER_UNIT > MAX_SUPPORTED_STACK_ALIGNMENT);
573e4b17023SJohn Marino   if (largea != largeb)
574e4b17023SJohn Marino     return (int)largeb - (int)largea;
575e4b17023SJohn Marino 
576e4b17023SJohn Marino   /* Secondary compare on size, decreasing  */
577e4b17023SJohn Marino   if (sizea > sizeb)
578e4b17023SJohn Marino     return -1;
579e4b17023SJohn Marino   if (sizea < sizeb)
580e4b17023SJohn Marino     return 1;
581e4b17023SJohn Marino 
582e4b17023SJohn Marino   /* Tertiary compare on true alignment, decreasing.  */
583e4b17023SJohn Marino   if (aligna < alignb)
584e4b17023SJohn Marino     return -1;
585e4b17023SJohn Marino   if (aligna > alignb)
586e4b17023SJohn Marino     return 1;
587e4b17023SJohn Marino 
588e4b17023SJohn Marino   /* Final compare on ID for sort stability, increasing.
589e4b17023SJohn Marino      Two SSA names are compared by their version, SSA names come before
590e4b17023SJohn Marino      non-SSA names, and two normal decls are compared by their DECL_UID.  */
591e4b17023SJohn Marino   if (TREE_CODE (decla) == SSA_NAME)
592e4b17023SJohn Marino     {
593e4b17023SJohn Marino       if (TREE_CODE (declb) == SSA_NAME)
594e4b17023SJohn Marino 	uida = SSA_NAME_VERSION (decla), uidb = SSA_NAME_VERSION (declb);
595e4b17023SJohn Marino       else
596e4b17023SJohn Marino 	return -1;
597e4b17023SJohn Marino     }
598e4b17023SJohn Marino   else if (TREE_CODE (declb) == SSA_NAME)
599e4b17023SJohn Marino     return 1;
600e4b17023SJohn Marino   else
601e4b17023SJohn Marino     uida = DECL_UID (decla), uidb = DECL_UID (declb);
602e4b17023SJohn Marino   if (uida < uidb)
603e4b17023SJohn Marino     return 1;
604e4b17023SJohn Marino   if (uida > uidb)
605e4b17023SJohn Marino     return -1;
606e4b17023SJohn Marino   return 0;
607e4b17023SJohn Marino }
608e4b17023SJohn Marino 
609e4b17023SJohn Marino 
610e4b17023SJohn Marino /* If the points-to solution *PI points to variables that are in a partition
611e4b17023SJohn Marino    together with other variables add all partition members to the pointed-to
612e4b17023SJohn Marino    variables bitmap.  */
613e4b17023SJohn Marino 
614e4b17023SJohn Marino static void
add_partitioned_vars_to_ptset(struct pt_solution * pt,struct pointer_map_t * decls_to_partitions,struct pointer_set_t * visited,bitmap temp)615e4b17023SJohn Marino add_partitioned_vars_to_ptset (struct pt_solution *pt,
616e4b17023SJohn Marino 			       struct pointer_map_t *decls_to_partitions,
617e4b17023SJohn Marino 			       struct pointer_set_t *visited, bitmap temp)
618e4b17023SJohn Marino {
619e4b17023SJohn Marino   bitmap_iterator bi;
620e4b17023SJohn Marino   unsigned i;
621e4b17023SJohn Marino   bitmap *part;
622e4b17023SJohn Marino 
623e4b17023SJohn Marino   if (pt->anything
624e4b17023SJohn Marino       || pt->vars == NULL
625e4b17023SJohn Marino       /* The pointed-to vars bitmap is shared, it is enough to
626e4b17023SJohn Marino 	 visit it once.  */
627e4b17023SJohn Marino       || pointer_set_insert(visited, pt->vars))
628e4b17023SJohn Marino     return;
629e4b17023SJohn Marino 
630e4b17023SJohn Marino   bitmap_clear (temp);
631e4b17023SJohn Marino 
632e4b17023SJohn Marino   /* By using a temporary bitmap to store all members of the partitions
633e4b17023SJohn Marino      we have to add we make sure to visit each of the partitions only
634e4b17023SJohn Marino      once.  */
635e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (pt->vars, 0, i, bi)
636e4b17023SJohn Marino     if ((!temp
637e4b17023SJohn Marino 	 || !bitmap_bit_p (temp, i))
638e4b17023SJohn Marino 	&& (part = (bitmap *) pointer_map_contains (decls_to_partitions,
639e4b17023SJohn Marino 						    (void *)(size_t) i)))
640e4b17023SJohn Marino       bitmap_ior_into (temp, *part);
641e4b17023SJohn Marino   if (!bitmap_empty_p (temp))
642e4b17023SJohn Marino     bitmap_ior_into (pt->vars, temp);
643e4b17023SJohn Marino }
644e4b17023SJohn Marino 
645e4b17023SJohn Marino /* Update points-to sets based on partition info, so we can use them on RTL.
646e4b17023SJohn Marino    The bitmaps representing stack partitions will be saved until expand,
647e4b17023SJohn Marino    where partitioned decls used as bases in memory expressions will be
648e4b17023SJohn Marino    rewritten.  */
649e4b17023SJohn Marino 
650e4b17023SJohn Marino static void
update_alias_info_with_stack_vars(void)651e4b17023SJohn Marino update_alias_info_with_stack_vars (void)
652e4b17023SJohn Marino {
653e4b17023SJohn Marino   struct pointer_map_t *decls_to_partitions = NULL;
654e4b17023SJohn Marino   size_t i, j;
655e4b17023SJohn Marino   tree var = NULL_TREE;
656e4b17023SJohn Marino 
657e4b17023SJohn Marino   for (i = 0; i < stack_vars_num; i++)
658e4b17023SJohn Marino     {
659e4b17023SJohn Marino       bitmap part = NULL;
660e4b17023SJohn Marino       tree name;
661e4b17023SJohn Marino       struct ptr_info_def *pi;
662e4b17023SJohn Marino 
663e4b17023SJohn Marino       /* Not interested in partitions with single variable.  */
664e4b17023SJohn Marino       if (stack_vars[i].representative != i
665e4b17023SJohn Marino           || stack_vars[i].next == EOC)
666e4b17023SJohn Marino         continue;
667e4b17023SJohn Marino 
668e4b17023SJohn Marino       if (!decls_to_partitions)
669e4b17023SJohn Marino 	{
670e4b17023SJohn Marino 	  decls_to_partitions = pointer_map_create ();
671e4b17023SJohn Marino 	  cfun->gimple_df->decls_to_pointers = pointer_map_create ();
672e4b17023SJohn Marino 	}
673e4b17023SJohn Marino 
674e4b17023SJohn Marino       /* Create an SSA_NAME that points to the partition for use
675e4b17023SJohn Marino          as base during alias-oracle queries on RTL for bases that
676e4b17023SJohn Marino 	 have been partitioned.  */
677e4b17023SJohn Marino       if (var == NULL_TREE)
678e4b17023SJohn Marino 	var = create_tmp_var (ptr_type_node, NULL);
679e4b17023SJohn Marino       name = make_ssa_name (var, NULL);
680e4b17023SJohn Marino 
681e4b17023SJohn Marino       /* Create bitmaps representing partitions.  They will be used for
682e4b17023SJohn Marino          points-to sets later, so use GGC alloc.  */
683e4b17023SJohn Marino       part = BITMAP_GGC_ALLOC ();
684e4b17023SJohn Marino       for (j = i; j != EOC; j = stack_vars[j].next)
685e4b17023SJohn Marino 	{
686e4b17023SJohn Marino 	  tree decl = stack_vars[j].decl;
687e4b17023SJohn Marino 	  unsigned int uid = DECL_PT_UID (decl);
688e4b17023SJohn Marino 	  /* We should never end up partitioning SSA names (though they
689e4b17023SJohn Marino 	     may end up on the stack).  Neither should we allocate stack
690e4b17023SJohn Marino 	     space to something that is unused and thus unreferenced, except
691e4b17023SJohn Marino 	     for -O0 where we are preserving even unreferenced variables.  */
692e4b17023SJohn Marino 	  gcc_assert (DECL_P (decl)
693e4b17023SJohn Marino 		      && (!optimize
694e4b17023SJohn Marino 			  || referenced_var_lookup (cfun, DECL_UID (decl))));
695e4b17023SJohn Marino 	  bitmap_set_bit (part, uid);
696e4b17023SJohn Marino 	  *((bitmap *) pointer_map_insert (decls_to_partitions,
697e4b17023SJohn Marino 					   (void *)(size_t) uid)) = part;
698e4b17023SJohn Marino 	  *((tree *) pointer_map_insert (cfun->gimple_df->decls_to_pointers,
699e4b17023SJohn Marino 					 decl)) = name;
7005ce9237cSJohn Marino 	  if (TREE_ADDRESSABLE (decl))
7015ce9237cSJohn Marino 	    TREE_ADDRESSABLE (name) = 1;
702e4b17023SJohn Marino 	}
703e4b17023SJohn Marino 
704e4b17023SJohn Marino       /* Make the SSA name point to all partition members.  */
705e4b17023SJohn Marino       pi = get_ptr_info (name);
706e4b17023SJohn Marino       pt_solution_set (&pi->pt, part, false);
707e4b17023SJohn Marino     }
708e4b17023SJohn Marino 
709e4b17023SJohn Marino   /* Make all points-to sets that contain one member of a partition
710e4b17023SJohn Marino      contain all members of the partition.  */
711e4b17023SJohn Marino   if (decls_to_partitions)
712e4b17023SJohn Marino     {
713e4b17023SJohn Marino       unsigned i;
714e4b17023SJohn Marino       struct pointer_set_t *visited = pointer_set_create ();
715e4b17023SJohn Marino       bitmap temp = BITMAP_ALLOC (NULL);
716e4b17023SJohn Marino 
717e4b17023SJohn Marino       for (i = 1; i < num_ssa_names; i++)
718e4b17023SJohn Marino 	{
719e4b17023SJohn Marino 	  tree name = ssa_name (i);
720e4b17023SJohn Marino 	  struct ptr_info_def *pi;
721e4b17023SJohn Marino 
722e4b17023SJohn Marino 	  if (name
723e4b17023SJohn Marino 	      && POINTER_TYPE_P (TREE_TYPE (name))
724e4b17023SJohn Marino 	      && ((pi = SSA_NAME_PTR_INFO (name)) != NULL))
725e4b17023SJohn Marino 	    add_partitioned_vars_to_ptset (&pi->pt, decls_to_partitions,
726e4b17023SJohn Marino 					   visited, temp);
727e4b17023SJohn Marino 	}
728e4b17023SJohn Marino 
729e4b17023SJohn Marino       add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
730e4b17023SJohn Marino 				     decls_to_partitions, visited, temp);
731e4b17023SJohn Marino 
732e4b17023SJohn Marino       pointer_set_destroy (visited);
733e4b17023SJohn Marino       pointer_map_destroy (decls_to_partitions);
734e4b17023SJohn Marino       BITMAP_FREE (temp);
735e4b17023SJohn Marino     }
736e4b17023SJohn Marino }
737e4b17023SJohn Marino 
738e4b17023SJohn Marino /* A subroutine of partition_stack_vars.  The UNION portion of a UNION/FIND
739e4b17023SJohn Marino    partitioning algorithm.  Partitions A and B are known to be non-conflicting.
740e4b17023SJohn Marino    Merge them into a single partition A.  */
741e4b17023SJohn Marino 
742e4b17023SJohn Marino static void
union_stack_vars(size_t a,size_t b)743e4b17023SJohn Marino union_stack_vars (size_t a, size_t b)
744e4b17023SJohn Marino {
745e4b17023SJohn Marino   struct stack_var *vb = &stack_vars[b];
746e4b17023SJohn Marino   bitmap_iterator bi;
747e4b17023SJohn Marino   unsigned u;
748e4b17023SJohn Marino 
749e4b17023SJohn Marino   gcc_assert (stack_vars[b].next == EOC);
750e4b17023SJohn Marino    /* Add B to A's partition.  */
751e4b17023SJohn Marino   stack_vars[b].next = stack_vars[a].next;
752e4b17023SJohn Marino   stack_vars[b].representative = a;
753e4b17023SJohn Marino   stack_vars[a].next = b;
754e4b17023SJohn Marino 
755e4b17023SJohn Marino   /* Update the required alignment of partition A to account for B.  */
756e4b17023SJohn Marino   if (stack_vars[a].alignb < stack_vars[b].alignb)
757e4b17023SJohn Marino     stack_vars[a].alignb = stack_vars[b].alignb;
758e4b17023SJohn Marino 
759e4b17023SJohn Marino   /* Update the interference graph and merge the conflicts.  */
760e4b17023SJohn Marino   if (vb->conflicts)
761e4b17023SJohn Marino     {
762e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (vb->conflicts, 0, u, bi)
763e4b17023SJohn Marino 	add_stack_var_conflict (a, stack_vars[u].representative);
764e4b17023SJohn Marino       BITMAP_FREE (vb->conflicts);
765e4b17023SJohn Marino     }
766e4b17023SJohn Marino }
767e4b17023SJohn Marino 
768e4b17023SJohn Marino /* A subroutine of expand_used_vars.  Binpack the variables into
769e4b17023SJohn Marino    partitions constrained by the interference graph.  The overall
770e4b17023SJohn Marino    algorithm used is as follows:
771e4b17023SJohn Marino 
772e4b17023SJohn Marino 	Sort the objects by size in descending order.
773e4b17023SJohn Marino 	For each object A {
774e4b17023SJohn Marino 	  S = size(A)
775e4b17023SJohn Marino 	  O = 0
776e4b17023SJohn Marino 	  loop {
777e4b17023SJohn Marino 	    Look for the largest non-conflicting object B with size <= S.
778e4b17023SJohn Marino 	    UNION (A, B)
779e4b17023SJohn Marino 	  }
780e4b17023SJohn Marino 	}
781e4b17023SJohn Marino */
782e4b17023SJohn Marino 
783e4b17023SJohn Marino static void
partition_stack_vars(void)784e4b17023SJohn Marino partition_stack_vars (void)
785e4b17023SJohn Marino {
786e4b17023SJohn Marino   size_t si, sj, n = stack_vars_num;
787e4b17023SJohn Marino 
788e4b17023SJohn Marino   stack_vars_sorted = XNEWVEC (size_t, stack_vars_num);
789e4b17023SJohn Marino   for (si = 0; si < n; ++si)
790e4b17023SJohn Marino     stack_vars_sorted[si] = si;
791e4b17023SJohn Marino 
792e4b17023SJohn Marino   if (n == 1)
793e4b17023SJohn Marino     return;
794e4b17023SJohn Marino 
795e4b17023SJohn Marino   qsort (stack_vars_sorted, n, sizeof (size_t), stack_var_cmp);
796e4b17023SJohn Marino 
797e4b17023SJohn Marino   for (si = 0; si < n; ++si)
798e4b17023SJohn Marino     {
799e4b17023SJohn Marino       size_t i = stack_vars_sorted[si];
800e4b17023SJohn Marino       unsigned int ialign = stack_vars[i].alignb;
801e4b17023SJohn Marino 
802e4b17023SJohn Marino       /* Ignore objects that aren't partition representatives. If we
803e4b17023SJohn Marino          see a var that is not a partition representative, it must
804e4b17023SJohn Marino          have been merged earlier.  */
805e4b17023SJohn Marino       if (stack_vars[i].representative != i)
806e4b17023SJohn Marino         continue;
807e4b17023SJohn Marino 
808e4b17023SJohn Marino       for (sj = si + 1; sj < n; ++sj)
809e4b17023SJohn Marino 	{
810e4b17023SJohn Marino 	  size_t j = stack_vars_sorted[sj];
811e4b17023SJohn Marino 	  unsigned int jalign = stack_vars[j].alignb;
812e4b17023SJohn Marino 
813e4b17023SJohn Marino 	  /* Ignore objects that aren't partition representatives.  */
814e4b17023SJohn Marino 	  if (stack_vars[j].representative != j)
815e4b17023SJohn Marino 	    continue;
816e4b17023SJohn Marino 
817e4b17023SJohn Marino 	  /* Ignore conflicting objects.  */
818e4b17023SJohn Marino 	  if (stack_var_conflict_p (i, j))
819e4b17023SJohn Marino 	    continue;
820e4b17023SJohn Marino 
821e4b17023SJohn Marino 	  /* Do not mix objects of "small" (supported) alignment
822e4b17023SJohn Marino 	     and "large" (unsupported) alignment.  */
823e4b17023SJohn Marino 	  if ((ialign * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
824e4b17023SJohn Marino 	      != (jalign * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT))
825e4b17023SJohn Marino 	    continue;
826e4b17023SJohn Marino 
827e4b17023SJohn Marino 	  /* UNION the objects, placing J at OFFSET.  */
828e4b17023SJohn Marino 	  union_stack_vars (i, j);
829e4b17023SJohn Marino 	}
830e4b17023SJohn Marino     }
831e4b17023SJohn Marino 
832e4b17023SJohn Marino   update_alias_info_with_stack_vars ();
833e4b17023SJohn Marino }
834e4b17023SJohn Marino 
835e4b17023SJohn Marino /* A debugging aid for expand_used_vars.  Dump the generated partitions.  */
836e4b17023SJohn Marino 
837e4b17023SJohn Marino static void
dump_stack_var_partition(void)838e4b17023SJohn Marino dump_stack_var_partition (void)
839e4b17023SJohn Marino {
840e4b17023SJohn Marino   size_t si, i, j, n = stack_vars_num;
841e4b17023SJohn Marino 
842e4b17023SJohn Marino   for (si = 0; si < n; ++si)
843e4b17023SJohn Marino     {
844e4b17023SJohn Marino       i = stack_vars_sorted[si];
845e4b17023SJohn Marino 
846e4b17023SJohn Marino       /* Skip variables that aren't partition representatives, for now.  */
847e4b17023SJohn Marino       if (stack_vars[i].representative != i)
848e4b17023SJohn Marino 	continue;
849e4b17023SJohn Marino 
850e4b17023SJohn Marino       fprintf (dump_file, "Partition %lu: size " HOST_WIDE_INT_PRINT_DEC
851e4b17023SJohn Marino 	       " align %u\n", (unsigned long) i, stack_vars[i].size,
852e4b17023SJohn Marino 	       stack_vars[i].alignb);
853e4b17023SJohn Marino 
854e4b17023SJohn Marino       for (j = i; j != EOC; j = stack_vars[j].next)
855e4b17023SJohn Marino 	{
856e4b17023SJohn Marino 	  fputc ('\t', dump_file);
857e4b17023SJohn Marino 	  print_generic_expr (dump_file, stack_vars[j].decl, dump_flags);
858e4b17023SJohn Marino 	}
859e4b17023SJohn Marino       fputc ('\n', dump_file);
860e4b17023SJohn Marino     }
861e4b17023SJohn Marino }
862e4b17023SJohn Marino 
863e4b17023SJohn Marino /* Assign rtl to DECL at BASE + OFFSET.  */
864e4b17023SJohn Marino 
865e4b17023SJohn Marino static void
expand_one_stack_var_at(tree decl,rtx base,unsigned base_align,HOST_WIDE_INT offset)866e4b17023SJohn Marino expand_one_stack_var_at (tree decl, rtx base, unsigned base_align,
867e4b17023SJohn Marino 			 HOST_WIDE_INT offset)
868e4b17023SJohn Marino {
869e4b17023SJohn Marino   unsigned align;
870e4b17023SJohn Marino   rtx x;
871e4b17023SJohn Marino 
872e4b17023SJohn Marino   /* If this fails, we've overflowed the stack frame.  Error nicely?  */
873e4b17023SJohn Marino   gcc_assert (offset == trunc_int_for_mode (offset, Pmode));
874e4b17023SJohn Marino 
875e4b17023SJohn Marino   x = plus_constant (base, offset);
876e4b17023SJohn Marino   x = gen_rtx_MEM (DECL_MODE (SSAVAR (decl)), x);
877e4b17023SJohn Marino 
878e4b17023SJohn Marino   if (TREE_CODE (decl) != SSA_NAME)
879e4b17023SJohn Marino     {
880e4b17023SJohn Marino       /* Set alignment we actually gave this decl if it isn't an SSA name.
881e4b17023SJohn Marino          If it is we generate stack slots only accidentally so it isn't as
882e4b17023SJohn Marino 	 important, we'll simply use the alignment that is already set.  */
883e4b17023SJohn Marino       if (base == virtual_stack_vars_rtx)
884e4b17023SJohn Marino 	offset -= frame_phase;
885e4b17023SJohn Marino       align = offset & -offset;
886e4b17023SJohn Marino       align *= BITS_PER_UNIT;
887e4b17023SJohn Marino       if (align == 0 || align > base_align)
888e4b17023SJohn Marino 	align = base_align;
889e4b17023SJohn Marino 
890e4b17023SJohn Marino       /* One would think that we could assert that we're not decreasing
891e4b17023SJohn Marino 	 alignment here, but (at least) the i386 port does exactly this
892e4b17023SJohn Marino 	 via the MINIMUM_ALIGNMENT hook.  */
893e4b17023SJohn Marino 
894e4b17023SJohn Marino       DECL_ALIGN (decl) = align;
895e4b17023SJohn Marino       DECL_USER_ALIGN (decl) = 0;
896e4b17023SJohn Marino     }
897e4b17023SJohn Marino 
898e4b17023SJohn Marino   set_mem_attributes (x, SSAVAR (decl), true);
899e4b17023SJohn Marino   set_rtl (decl, x);
900e4b17023SJohn Marino }
901e4b17023SJohn Marino 
902e4b17023SJohn Marino /* A subroutine of expand_used_vars.  Give each partition representative
903e4b17023SJohn Marino    a unique location within the stack frame.  Update each partition member
904e4b17023SJohn Marino    with that location.  */
905e4b17023SJohn Marino 
906e4b17023SJohn Marino static void
expand_stack_vars(bool (* pred)(tree))907e4b17023SJohn Marino expand_stack_vars (bool (*pred) (tree))
908e4b17023SJohn Marino {
909e4b17023SJohn Marino   size_t si, i, j, n = stack_vars_num;
910e4b17023SJohn Marino   HOST_WIDE_INT large_size = 0, large_alloc = 0;
911e4b17023SJohn Marino   rtx large_base = NULL;
912e4b17023SJohn Marino   unsigned large_align = 0;
913e4b17023SJohn Marino   tree decl;
914e4b17023SJohn Marino 
915e4b17023SJohn Marino   /* Determine if there are any variables requiring "large" alignment.
916e4b17023SJohn Marino      Since these are dynamically allocated, we only process these if
917e4b17023SJohn Marino      no predicate involved.  */
918e4b17023SJohn Marino   large_align = stack_vars[stack_vars_sorted[0]].alignb * BITS_PER_UNIT;
919e4b17023SJohn Marino   if (pred == NULL && large_align > MAX_SUPPORTED_STACK_ALIGNMENT)
920e4b17023SJohn Marino     {
921e4b17023SJohn Marino       /* Find the total size of these variables.  */
922e4b17023SJohn Marino       for (si = 0; si < n; ++si)
923e4b17023SJohn Marino 	{
924e4b17023SJohn Marino 	  unsigned alignb;
925e4b17023SJohn Marino 
926e4b17023SJohn Marino 	  i = stack_vars_sorted[si];
927e4b17023SJohn Marino 	  alignb = stack_vars[i].alignb;
928e4b17023SJohn Marino 
929e4b17023SJohn Marino 	  /* Stop when we get to the first decl with "small" alignment.  */
930e4b17023SJohn Marino 	  if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
931e4b17023SJohn Marino 	    break;
932e4b17023SJohn Marino 
933e4b17023SJohn Marino 	  /* Skip variables that aren't partition representatives.  */
934e4b17023SJohn Marino 	  if (stack_vars[i].representative != i)
935e4b17023SJohn Marino 	    continue;
936e4b17023SJohn Marino 
937e4b17023SJohn Marino 	  /* Skip variables that have already had rtl assigned.  See also
938e4b17023SJohn Marino 	     add_stack_var where we perpetrate this pc_rtx hack.  */
939e4b17023SJohn Marino 	  decl = stack_vars[i].decl;
940e4b17023SJohn Marino 	  if ((TREE_CODE (decl) == SSA_NAME
941e4b17023SJohn Marino 	      ? SA.partition_to_pseudo[var_to_partition (SA.map, decl)]
942e4b17023SJohn Marino 	      : DECL_RTL (decl)) != pc_rtx)
943e4b17023SJohn Marino 	    continue;
944e4b17023SJohn Marino 
945e4b17023SJohn Marino 	  large_size += alignb - 1;
946e4b17023SJohn Marino 	  large_size &= -(HOST_WIDE_INT)alignb;
947e4b17023SJohn Marino 	  large_size += stack_vars[i].size;
948e4b17023SJohn Marino 	}
949e4b17023SJohn Marino 
950e4b17023SJohn Marino       /* If there were any, allocate space.  */
951e4b17023SJohn Marino       if (large_size > 0)
952e4b17023SJohn Marino 	large_base = allocate_dynamic_stack_space (GEN_INT (large_size), 0,
953e4b17023SJohn Marino 						   large_align, true);
954e4b17023SJohn Marino     }
955e4b17023SJohn Marino 
956e4b17023SJohn Marino   for (si = 0; si < n; ++si)
957e4b17023SJohn Marino     {
958e4b17023SJohn Marino       rtx base;
959e4b17023SJohn Marino       unsigned base_align, alignb;
960e4b17023SJohn Marino       HOST_WIDE_INT offset;
961e4b17023SJohn Marino 
962e4b17023SJohn Marino       i = stack_vars_sorted[si];
963e4b17023SJohn Marino 
964e4b17023SJohn Marino       /* Skip variables that aren't partition representatives, for now.  */
965e4b17023SJohn Marino       if (stack_vars[i].representative != i)
966e4b17023SJohn Marino 	continue;
967e4b17023SJohn Marino 
968e4b17023SJohn Marino       /* Skip variables that have already had rtl assigned.  See also
969e4b17023SJohn Marino 	 add_stack_var where we perpetrate this pc_rtx hack.  */
970e4b17023SJohn Marino       decl = stack_vars[i].decl;
971e4b17023SJohn Marino       if ((TREE_CODE (decl) == SSA_NAME
972e4b17023SJohn Marino 	   ? SA.partition_to_pseudo[var_to_partition (SA.map, decl)]
973e4b17023SJohn Marino 	   : DECL_RTL (decl)) != pc_rtx)
974e4b17023SJohn Marino 	continue;
975e4b17023SJohn Marino 
976e4b17023SJohn Marino       /* Check the predicate to see whether this variable should be
977e4b17023SJohn Marino 	 allocated in this pass.  */
978e4b17023SJohn Marino       if (pred && !pred (decl))
979e4b17023SJohn Marino 	continue;
980e4b17023SJohn Marino 
981e4b17023SJohn Marino       alignb = stack_vars[i].alignb;
982e4b17023SJohn Marino       if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
983e4b17023SJohn Marino 	{
984e4b17023SJohn Marino 	  offset = alloc_stack_frame_space (stack_vars[i].size, alignb);
985e4b17023SJohn Marino 	  base = virtual_stack_vars_rtx;
986e4b17023SJohn Marino 	  base_align = crtl->max_used_stack_slot_alignment;
987e4b17023SJohn Marino 	}
988e4b17023SJohn Marino       else
989e4b17023SJohn Marino 	{
990e4b17023SJohn Marino 	  /* Large alignment is only processed in the last pass.  */
991e4b17023SJohn Marino 	  if (pred)
992e4b17023SJohn Marino 	    continue;
993e4b17023SJohn Marino 	  gcc_assert (large_base != NULL);
994e4b17023SJohn Marino 
995e4b17023SJohn Marino 	  large_alloc += alignb - 1;
996e4b17023SJohn Marino 	  large_alloc &= -(HOST_WIDE_INT)alignb;
997e4b17023SJohn Marino 	  offset = large_alloc;
998e4b17023SJohn Marino 	  large_alloc += stack_vars[i].size;
999e4b17023SJohn Marino 
1000e4b17023SJohn Marino 	  base = large_base;
1001e4b17023SJohn Marino 	  base_align = large_align;
1002e4b17023SJohn Marino 	}
1003e4b17023SJohn Marino 
1004e4b17023SJohn Marino       /* Create rtl for each variable based on their location within the
1005e4b17023SJohn Marino 	 partition.  */
1006e4b17023SJohn Marino       for (j = i; j != EOC; j = stack_vars[j].next)
1007e4b17023SJohn Marino 	{
1008e4b17023SJohn Marino 	  expand_one_stack_var_at (stack_vars[j].decl,
1009e4b17023SJohn Marino 				   base, base_align,
1010e4b17023SJohn Marino 				   offset);
1011e4b17023SJohn Marino 	}
1012e4b17023SJohn Marino     }
1013e4b17023SJohn Marino 
1014e4b17023SJohn Marino   gcc_assert (large_alloc == large_size);
1015e4b17023SJohn Marino }
1016e4b17023SJohn Marino 
1017e4b17023SJohn Marino /* Take into account all sizes of partitions and reset DECL_RTLs.  */
1018e4b17023SJohn Marino static HOST_WIDE_INT
account_stack_vars(void)1019e4b17023SJohn Marino account_stack_vars (void)
1020e4b17023SJohn Marino {
1021e4b17023SJohn Marino   size_t si, j, i, n = stack_vars_num;
1022e4b17023SJohn Marino   HOST_WIDE_INT size = 0;
1023e4b17023SJohn Marino 
1024e4b17023SJohn Marino   for (si = 0; si < n; ++si)
1025e4b17023SJohn Marino     {
1026e4b17023SJohn Marino       i = stack_vars_sorted[si];
1027e4b17023SJohn Marino 
1028e4b17023SJohn Marino       /* Skip variables that aren't partition representatives, for now.  */
1029e4b17023SJohn Marino       if (stack_vars[i].representative != i)
1030e4b17023SJohn Marino 	continue;
1031e4b17023SJohn Marino 
1032e4b17023SJohn Marino       size += stack_vars[i].size;
1033e4b17023SJohn Marino       for (j = i; j != EOC; j = stack_vars[j].next)
1034e4b17023SJohn Marino 	set_rtl (stack_vars[j].decl, NULL);
1035e4b17023SJohn Marino     }
1036e4b17023SJohn Marino   return size;
1037e4b17023SJohn Marino }
1038e4b17023SJohn Marino 
1039e4b17023SJohn Marino /* A subroutine of expand_one_var.  Called to immediately assign rtl
1040e4b17023SJohn Marino    to a variable to be allocated in the stack frame.  */
1041e4b17023SJohn Marino 
1042e4b17023SJohn Marino static void
expand_one_stack_var(tree var)1043e4b17023SJohn Marino expand_one_stack_var (tree var)
1044e4b17023SJohn Marino {
1045e4b17023SJohn Marino   HOST_WIDE_INT size, offset;
1046e4b17023SJohn Marino   unsigned byte_align;
1047e4b17023SJohn Marino 
1048e4b17023SJohn Marino   size = tree_low_cst (DECL_SIZE_UNIT (SSAVAR (var)), 1);
1049e4b17023SJohn Marino   byte_align = align_local_variable (SSAVAR (var));
1050e4b17023SJohn Marino 
1051e4b17023SJohn Marino   /* We handle highly aligned variables in expand_stack_vars.  */
1052e4b17023SJohn Marino   gcc_assert (byte_align * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT);
1053e4b17023SJohn Marino 
1054e4b17023SJohn Marino   offset = alloc_stack_frame_space (size, byte_align);
1055e4b17023SJohn Marino 
1056e4b17023SJohn Marino   expand_one_stack_var_at (var, virtual_stack_vars_rtx,
1057e4b17023SJohn Marino 			   crtl->max_used_stack_slot_alignment, offset);
1058e4b17023SJohn Marino }
1059e4b17023SJohn Marino 
1060e4b17023SJohn Marino /* A subroutine of expand_one_var.  Called to assign rtl to a VAR_DECL
1061e4b17023SJohn Marino    that will reside in a hard register.  */
1062e4b17023SJohn Marino 
1063e4b17023SJohn Marino static void
expand_one_hard_reg_var(tree var)1064e4b17023SJohn Marino expand_one_hard_reg_var (tree var)
1065e4b17023SJohn Marino {
1066e4b17023SJohn Marino   rest_of_decl_compilation (var, 0, 0);
1067e4b17023SJohn Marino }
1068e4b17023SJohn Marino 
1069e4b17023SJohn Marino /* A subroutine of expand_one_var.  Called to assign rtl to a VAR_DECL
1070e4b17023SJohn Marino    that will reside in a pseudo register.  */
1071e4b17023SJohn Marino 
1072e4b17023SJohn Marino static void
expand_one_register_var(tree var)1073e4b17023SJohn Marino expand_one_register_var (tree var)
1074e4b17023SJohn Marino {
1075e4b17023SJohn Marino   tree decl = SSAVAR (var);
1076e4b17023SJohn Marino   tree type = TREE_TYPE (decl);
1077e4b17023SJohn Marino   enum machine_mode reg_mode = promote_decl_mode (decl, NULL);
1078e4b17023SJohn Marino   rtx x = gen_reg_rtx (reg_mode);
1079e4b17023SJohn Marino 
1080e4b17023SJohn Marino   set_rtl (var, x);
1081e4b17023SJohn Marino 
1082e4b17023SJohn Marino   /* Note if the object is a user variable.  */
1083e4b17023SJohn Marino   if (!DECL_ARTIFICIAL (decl))
1084e4b17023SJohn Marino     mark_user_reg (x);
1085e4b17023SJohn Marino 
1086e4b17023SJohn Marino   if (POINTER_TYPE_P (type))
1087e4b17023SJohn Marino     mark_reg_pointer (x, get_pointer_alignment (var));
1088e4b17023SJohn Marino }
1089e4b17023SJohn Marino 
1090e4b17023SJohn Marino /* A subroutine of expand_one_var.  Called to assign rtl to a VAR_DECL that
1091e4b17023SJohn Marino    has some associated error, e.g. its type is error-mark.  We just need
1092e4b17023SJohn Marino    to pick something that won't crash the rest of the compiler.  */
1093e4b17023SJohn Marino 
1094e4b17023SJohn Marino static void
expand_one_error_var(tree var)1095e4b17023SJohn Marino expand_one_error_var (tree var)
1096e4b17023SJohn Marino {
1097e4b17023SJohn Marino   enum machine_mode mode = DECL_MODE (var);
1098e4b17023SJohn Marino   rtx x;
1099e4b17023SJohn Marino 
1100e4b17023SJohn Marino   if (mode == BLKmode)
1101e4b17023SJohn Marino     x = gen_rtx_MEM (BLKmode, const0_rtx);
1102e4b17023SJohn Marino   else if (mode == VOIDmode)
1103e4b17023SJohn Marino     x = const0_rtx;
1104e4b17023SJohn Marino   else
1105e4b17023SJohn Marino     x = gen_reg_rtx (mode);
1106e4b17023SJohn Marino 
1107e4b17023SJohn Marino   SET_DECL_RTL (var, x);
1108e4b17023SJohn Marino }
1109e4b17023SJohn Marino 
1110e4b17023SJohn Marino /* A subroutine of expand_one_var.  VAR is a variable that will be
1111e4b17023SJohn Marino    allocated to the local stack frame.  Return true if we wish to
1112e4b17023SJohn Marino    add VAR to STACK_VARS so that it will be coalesced with other
1113e4b17023SJohn Marino    variables.  Return false to allocate VAR immediately.
1114e4b17023SJohn Marino 
1115e4b17023SJohn Marino    This function is used to reduce the number of variables considered
1116e4b17023SJohn Marino    for coalescing, which reduces the size of the quadratic problem.  */
1117e4b17023SJohn Marino 
1118e4b17023SJohn Marino static bool
defer_stack_allocation(tree var,bool toplevel)1119e4b17023SJohn Marino defer_stack_allocation (tree var, bool toplevel)
1120e4b17023SJohn Marino {
1121e4b17023SJohn Marino   /* If stack protection is enabled, *all* stack variables must be deferred,
1122e4b17023SJohn Marino      so that we can re-order the strings to the top of the frame.  */
1123e4b17023SJohn Marino   if (flag_stack_protect)
1124e4b17023SJohn Marino     return true;
1125e4b17023SJohn Marino 
1126e4b17023SJohn Marino   /* We handle "large" alignment via dynamic allocation.  We want to handle
1127e4b17023SJohn Marino      this extra complication in only one place, so defer them.  */
1128e4b17023SJohn Marino   if (DECL_ALIGN (var) > MAX_SUPPORTED_STACK_ALIGNMENT)
1129e4b17023SJohn Marino     return true;
1130e4b17023SJohn Marino 
1131e4b17023SJohn Marino   /* Variables in the outermost scope automatically conflict with
1132e4b17023SJohn Marino      every other variable.  The only reason to want to defer them
1133e4b17023SJohn Marino      at all is that, after sorting, we can more efficiently pack
1134e4b17023SJohn Marino      small variables in the stack frame.  Continue to defer at -O2.  */
1135e4b17023SJohn Marino   if (toplevel && optimize < 2)
1136e4b17023SJohn Marino     return false;
1137e4b17023SJohn Marino 
1138e4b17023SJohn Marino   /* Without optimization, *most* variables are allocated from the
1139e4b17023SJohn Marino      stack, which makes the quadratic problem large exactly when we
1140e4b17023SJohn Marino      want compilation to proceed as quickly as possible.  On the
1141e4b17023SJohn Marino      other hand, we don't want the function's stack frame size to
1142e4b17023SJohn Marino      get completely out of hand.  So we avoid adding scalars and
1143e4b17023SJohn Marino      "small" aggregates to the list at all.  */
1144e4b17023SJohn Marino   if (optimize == 0 && tree_low_cst (DECL_SIZE_UNIT (var), 1) < 32)
1145e4b17023SJohn Marino     return false;
1146e4b17023SJohn Marino 
1147e4b17023SJohn Marino   return true;
1148e4b17023SJohn Marino }
1149e4b17023SJohn Marino 
1150e4b17023SJohn Marino /* A subroutine of expand_used_vars.  Expand one variable according to
1151e4b17023SJohn Marino    its flavor.  Variables to be placed on the stack are not actually
1152e4b17023SJohn Marino    expanded yet, merely recorded.
1153e4b17023SJohn Marino    When REALLY_EXPAND is false, only add stack values to be allocated.
1154e4b17023SJohn Marino    Return stack usage this variable is supposed to take.
1155e4b17023SJohn Marino */
1156e4b17023SJohn Marino 
1157e4b17023SJohn Marino static HOST_WIDE_INT
expand_one_var(tree var,bool toplevel,bool really_expand)1158e4b17023SJohn Marino expand_one_var (tree var, bool toplevel, bool really_expand)
1159e4b17023SJohn Marino {
1160e4b17023SJohn Marino   unsigned int align = BITS_PER_UNIT;
1161e4b17023SJohn Marino   tree origvar = var;
1162e4b17023SJohn Marino 
1163e4b17023SJohn Marino   var = SSAVAR (var);
1164e4b17023SJohn Marino 
1165e4b17023SJohn Marino   if (TREE_TYPE (var) != error_mark_node && TREE_CODE (var) == VAR_DECL)
1166e4b17023SJohn Marino     {
1167e4b17023SJohn Marino       /* Because we don't know if VAR will be in register or on stack,
1168e4b17023SJohn Marino 	 we conservatively assume it will be on stack even if VAR is
1169e4b17023SJohn Marino 	 eventually put into register after RA pass.  For non-automatic
1170e4b17023SJohn Marino 	 variables, which won't be on stack, we collect alignment of
1171e4b17023SJohn Marino 	 type and ignore user specified alignment.  */
1172e4b17023SJohn Marino       if (TREE_STATIC (var) || DECL_EXTERNAL (var))
1173e4b17023SJohn Marino 	align = MINIMUM_ALIGNMENT (TREE_TYPE (var),
1174e4b17023SJohn Marino 				   TYPE_MODE (TREE_TYPE (var)),
1175e4b17023SJohn Marino 				   TYPE_ALIGN (TREE_TYPE (var)));
1176e4b17023SJohn Marino       else if (DECL_HAS_VALUE_EXPR_P (var)
1177e4b17023SJohn Marino 	       || (DECL_RTL_SET_P (var) && MEM_P (DECL_RTL (var))))
1178e4b17023SJohn Marino 	/* Don't consider debug only variables with DECL_HAS_VALUE_EXPR_P set
1179e4b17023SJohn Marino 	   or variables which were assigned a stack slot already by
1180e4b17023SJohn Marino 	   expand_one_stack_var_at - in the latter case DECL_ALIGN has been
1181e4b17023SJohn Marino 	   changed from the offset chosen to it.  */
1182e4b17023SJohn Marino 	align = crtl->stack_alignment_estimated;
1183e4b17023SJohn Marino       else
1184e4b17023SJohn Marino 	align = MINIMUM_ALIGNMENT (var, DECL_MODE (var), DECL_ALIGN (var));
1185e4b17023SJohn Marino 
1186e4b17023SJohn Marino       /* If the variable alignment is very large we'll dynamicaly allocate
1187e4b17023SJohn Marino 	 it, which means that in-frame portion is just a pointer.  */
1188e4b17023SJohn Marino       if (align > MAX_SUPPORTED_STACK_ALIGNMENT)
1189e4b17023SJohn Marino 	align = POINTER_SIZE;
1190e4b17023SJohn Marino     }
1191e4b17023SJohn Marino 
1192e4b17023SJohn Marino   if (SUPPORTS_STACK_ALIGNMENT
1193e4b17023SJohn Marino       && crtl->stack_alignment_estimated < align)
1194e4b17023SJohn Marino     {
1195e4b17023SJohn Marino       /* stack_alignment_estimated shouldn't change after stack
1196e4b17023SJohn Marino          realign decision made */
1197e4b17023SJohn Marino       gcc_assert(!crtl->stack_realign_processed);
1198e4b17023SJohn Marino       crtl->stack_alignment_estimated = align;
1199e4b17023SJohn Marino     }
1200e4b17023SJohn Marino 
1201e4b17023SJohn Marino   /* stack_alignment_needed > PREFERRED_STACK_BOUNDARY is permitted.
1202e4b17023SJohn Marino      So here we only make sure stack_alignment_needed >= align.  */
1203e4b17023SJohn Marino   if (crtl->stack_alignment_needed < align)
1204e4b17023SJohn Marino     crtl->stack_alignment_needed = align;
1205e4b17023SJohn Marino   if (crtl->max_used_stack_slot_alignment < align)
1206e4b17023SJohn Marino     crtl->max_used_stack_slot_alignment = align;
1207e4b17023SJohn Marino 
1208e4b17023SJohn Marino   if (TREE_CODE (origvar) == SSA_NAME)
1209e4b17023SJohn Marino     {
1210e4b17023SJohn Marino       gcc_assert (TREE_CODE (var) != VAR_DECL
1211e4b17023SJohn Marino 		  || (!DECL_EXTERNAL (var)
1212e4b17023SJohn Marino 		      && !DECL_HAS_VALUE_EXPR_P (var)
1213e4b17023SJohn Marino 		      && !TREE_STATIC (var)
1214e4b17023SJohn Marino 		      && TREE_TYPE (var) != error_mark_node
1215e4b17023SJohn Marino 		      && !DECL_HARD_REGISTER (var)
1216e4b17023SJohn Marino 		      && really_expand));
1217e4b17023SJohn Marino     }
1218e4b17023SJohn Marino   if (TREE_CODE (var) != VAR_DECL && TREE_CODE (origvar) != SSA_NAME)
1219e4b17023SJohn Marino     ;
1220e4b17023SJohn Marino   else if (DECL_EXTERNAL (var))
1221e4b17023SJohn Marino     ;
1222e4b17023SJohn Marino   else if (DECL_HAS_VALUE_EXPR_P (var))
1223e4b17023SJohn Marino     ;
1224e4b17023SJohn Marino   else if (TREE_STATIC (var))
1225e4b17023SJohn Marino     ;
1226e4b17023SJohn Marino   else if (TREE_CODE (origvar) != SSA_NAME && DECL_RTL_SET_P (var))
1227e4b17023SJohn Marino     ;
1228e4b17023SJohn Marino   else if (TREE_TYPE (var) == error_mark_node)
1229e4b17023SJohn Marino     {
1230e4b17023SJohn Marino       if (really_expand)
1231e4b17023SJohn Marino         expand_one_error_var (var);
1232e4b17023SJohn Marino     }
1233e4b17023SJohn Marino   else if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var))
1234e4b17023SJohn Marino     {
1235e4b17023SJohn Marino       if (really_expand)
1236e4b17023SJohn Marino         expand_one_hard_reg_var (var);
1237e4b17023SJohn Marino     }
1238e4b17023SJohn Marino   else if (use_register_for_decl (var))
1239e4b17023SJohn Marino     {
1240e4b17023SJohn Marino       if (really_expand)
1241e4b17023SJohn Marino         expand_one_register_var (origvar);
1242e4b17023SJohn Marino     }
1243e4b17023SJohn Marino   else if (!host_integerp (DECL_SIZE_UNIT (var), 1))
1244e4b17023SJohn Marino     {
1245e4b17023SJohn Marino       if (really_expand)
1246e4b17023SJohn Marino 	{
1247e4b17023SJohn Marino 	  error ("size of variable %q+D is too large", var);
1248e4b17023SJohn Marino 	  expand_one_error_var (var);
1249e4b17023SJohn Marino 	}
1250e4b17023SJohn Marino     }
1251e4b17023SJohn Marino   else if (defer_stack_allocation (var, toplevel))
1252e4b17023SJohn Marino     add_stack_var (origvar);
1253e4b17023SJohn Marino   else
1254e4b17023SJohn Marino     {
1255e4b17023SJohn Marino       if (really_expand)
1256e4b17023SJohn Marino         expand_one_stack_var (origvar);
1257e4b17023SJohn Marino       return tree_low_cst (DECL_SIZE_UNIT (var), 1);
1258e4b17023SJohn Marino     }
1259e4b17023SJohn Marino   return 0;
1260e4b17023SJohn Marino }
1261e4b17023SJohn Marino 
1262e4b17023SJohn Marino /* A subroutine of expand_used_vars.  Walk down through the BLOCK tree
1263e4b17023SJohn Marino    expanding variables.  Those variables that can be put into registers
1264e4b17023SJohn Marino    are allocated pseudos; those that can't are put on the stack.
1265e4b17023SJohn Marino 
1266e4b17023SJohn Marino    TOPLEVEL is true if this is the outermost BLOCK.  */
1267e4b17023SJohn Marino 
1268e4b17023SJohn Marino static void
expand_used_vars_for_block(tree block,bool toplevel)1269e4b17023SJohn Marino expand_used_vars_for_block (tree block, bool toplevel)
1270e4b17023SJohn Marino {
1271e4b17023SJohn Marino   tree t;
1272e4b17023SJohn Marino 
1273e4b17023SJohn Marino   /* Expand all variables at this level.  */
1274e4b17023SJohn Marino   for (t = BLOCK_VARS (block); t ; t = DECL_CHAIN (t))
1275e4b17023SJohn Marino     if (TREE_USED (t)
1276e4b17023SJohn Marino         && ((TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != RESULT_DECL)
1277e4b17023SJohn Marino 	    || !DECL_NONSHAREABLE (t)))
1278e4b17023SJohn Marino       expand_one_var (t, toplevel, true);
1279e4b17023SJohn Marino 
1280e4b17023SJohn Marino   /* Expand all variables at containing levels.  */
1281e4b17023SJohn Marino   for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
1282e4b17023SJohn Marino     expand_used_vars_for_block (t, false);
1283e4b17023SJohn Marino }
1284e4b17023SJohn Marino 
1285e4b17023SJohn Marino /* A subroutine of expand_used_vars.  Walk down through the BLOCK tree
1286e4b17023SJohn Marino    and clear TREE_USED on all local variables.  */
1287e4b17023SJohn Marino 
1288e4b17023SJohn Marino static void
clear_tree_used(tree block)1289e4b17023SJohn Marino clear_tree_used (tree block)
1290e4b17023SJohn Marino {
1291e4b17023SJohn Marino   tree t;
1292e4b17023SJohn Marino 
1293e4b17023SJohn Marino   for (t = BLOCK_VARS (block); t ; t = DECL_CHAIN (t))
1294e4b17023SJohn Marino     /* if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) */
1295e4b17023SJohn Marino     if ((TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != RESULT_DECL)
1296e4b17023SJohn Marino 	|| !DECL_NONSHAREABLE (t))
1297e4b17023SJohn Marino       TREE_USED (t) = 0;
1298e4b17023SJohn Marino 
1299e4b17023SJohn Marino   for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
1300e4b17023SJohn Marino     clear_tree_used (t);
1301e4b17023SJohn Marino }
1302e4b17023SJohn Marino 
1303e4b17023SJohn Marino /* Examine TYPE and determine a bit mask of the following features.  */
1304e4b17023SJohn Marino 
1305e4b17023SJohn Marino #define SPCT_HAS_LARGE_CHAR_ARRAY	1
1306e4b17023SJohn Marino #define SPCT_HAS_SMALL_CHAR_ARRAY	2
1307e4b17023SJohn Marino #define SPCT_HAS_ARRAY			4
1308e4b17023SJohn Marino #define SPCT_HAS_AGGREGATE		8
1309e4b17023SJohn Marino 
1310e4b17023SJohn Marino static unsigned int
stack_protect_classify_type(tree type)1311e4b17023SJohn Marino stack_protect_classify_type (tree type)
1312e4b17023SJohn Marino {
1313e4b17023SJohn Marino   unsigned int ret = 0;
1314e4b17023SJohn Marino   tree t;
1315e4b17023SJohn Marino 
1316e4b17023SJohn Marino   switch (TREE_CODE (type))
1317e4b17023SJohn Marino     {
1318e4b17023SJohn Marino     case ARRAY_TYPE:
1319e4b17023SJohn Marino       t = TYPE_MAIN_VARIANT (TREE_TYPE (type));
1320e4b17023SJohn Marino       if (t == char_type_node
1321e4b17023SJohn Marino 	  || t == signed_char_type_node
1322e4b17023SJohn Marino 	  || t == unsigned_char_type_node)
1323e4b17023SJohn Marino 	{
1324e4b17023SJohn Marino 	  unsigned HOST_WIDE_INT max = PARAM_VALUE (PARAM_SSP_BUFFER_SIZE);
1325e4b17023SJohn Marino 	  unsigned HOST_WIDE_INT len;
1326e4b17023SJohn Marino 
1327e4b17023SJohn Marino 	  if (!TYPE_SIZE_UNIT (type)
1328e4b17023SJohn Marino 	      || !host_integerp (TYPE_SIZE_UNIT (type), 1))
1329e4b17023SJohn Marino 	    len = max;
1330e4b17023SJohn Marino 	  else
1331e4b17023SJohn Marino 	    len = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
1332e4b17023SJohn Marino 
1333e4b17023SJohn Marino 	  if (len < max)
1334e4b17023SJohn Marino 	    ret = SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_ARRAY;
1335e4b17023SJohn Marino 	  else
1336e4b17023SJohn Marino 	    ret = SPCT_HAS_LARGE_CHAR_ARRAY | SPCT_HAS_ARRAY;
1337e4b17023SJohn Marino 	}
1338e4b17023SJohn Marino       else
1339e4b17023SJohn Marino 	ret = SPCT_HAS_ARRAY;
1340e4b17023SJohn Marino       break;
1341e4b17023SJohn Marino 
1342e4b17023SJohn Marino     case UNION_TYPE:
1343e4b17023SJohn Marino     case QUAL_UNION_TYPE:
1344e4b17023SJohn Marino     case RECORD_TYPE:
1345e4b17023SJohn Marino       ret = SPCT_HAS_AGGREGATE;
1346e4b17023SJohn Marino       for (t = TYPE_FIELDS (type); t ; t = TREE_CHAIN (t))
1347e4b17023SJohn Marino 	if (TREE_CODE (t) == FIELD_DECL)
1348e4b17023SJohn Marino 	  ret |= stack_protect_classify_type (TREE_TYPE (t));
1349e4b17023SJohn Marino       break;
1350e4b17023SJohn Marino 
1351e4b17023SJohn Marino     default:
1352e4b17023SJohn Marino       break;
1353e4b17023SJohn Marino     }
1354e4b17023SJohn Marino 
1355e4b17023SJohn Marino   return ret;
1356e4b17023SJohn Marino }
1357e4b17023SJohn Marino 
1358e4b17023SJohn Marino /* Return nonzero if DECL should be segregated into the "vulnerable" upper
1359e4b17023SJohn Marino    part of the local stack frame.  Remember if we ever return nonzero for
1360e4b17023SJohn Marino    any variable in this function.  The return value is the phase number in
1361e4b17023SJohn Marino    which the variable should be allocated.  */
1362e4b17023SJohn Marino 
1363e4b17023SJohn Marino static int
stack_protect_decl_phase(tree decl)1364e4b17023SJohn Marino stack_protect_decl_phase (tree decl)
1365e4b17023SJohn Marino {
1366e4b17023SJohn Marino   unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl));
1367e4b17023SJohn Marino   int ret = 0;
1368e4b17023SJohn Marino 
1369e4b17023SJohn Marino   if (bits & SPCT_HAS_SMALL_CHAR_ARRAY)
1370e4b17023SJohn Marino     has_short_buffer = true;
1371e4b17023SJohn Marino 
1372e4b17023SJohn Marino   if (flag_stack_protect == 2)
1373e4b17023SJohn Marino     {
1374e4b17023SJohn Marino       if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
1375e4b17023SJohn Marino 	  && !(bits & SPCT_HAS_AGGREGATE))
1376e4b17023SJohn Marino 	ret = 1;
1377e4b17023SJohn Marino       else if (bits & SPCT_HAS_ARRAY)
1378e4b17023SJohn Marino 	ret = 2;
1379e4b17023SJohn Marino     }
1380e4b17023SJohn Marino   else
1381e4b17023SJohn Marino     ret = (bits & SPCT_HAS_LARGE_CHAR_ARRAY) != 0;
1382e4b17023SJohn Marino 
1383e4b17023SJohn Marino   if (ret)
1384e4b17023SJohn Marino     has_protected_decls = true;
1385e4b17023SJohn Marino 
1386e4b17023SJohn Marino   return ret;
1387e4b17023SJohn Marino }
1388e4b17023SJohn Marino 
1389e4b17023SJohn Marino /* Two helper routines that check for phase 1 and phase 2.  These are used
1390e4b17023SJohn Marino    as callbacks for expand_stack_vars.  */
1391e4b17023SJohn Marino 
1392e4b17023SJohn Marino static bool
stack_protect_decl_phase_1(tree decl)1393e4b17023SJohn Marino stack_protect_decl_phase_1 (tree decl)
1394e4b17023SJohn Marino {
1395e4b17023SJohn Marino   return stack_protect_decl_phase (decl) == 1;
1396e4b17023SJohn Marino }
1397e4b17023SJohn Marino 
1398e4b17023SJohn Marino static bool
stack_protect_decl_phase_2(tree decl)1399e4b17023SJohn Marino stack_protect_decl_phase_2 (tree decl)
1400e4b17023SJohn Marino {
1401e4b17023SJohn Marino   return stack_protect_decl_phase (decl) == 2;
1402e4b17023SJohn Marino }
1403e4b17023SJohn Marino 
1404e4b17023SJohn Marino /* Ensure that variables in different stack protection phases conflict
1405e4b17023SJohn Marino    so that they are not merged and share the same stack slot.  */
1406e4b17023SJohn Marino 
1407e4b17023SJohn Marino static void
add_stack_protection_conflicts(void)1408e4b17023SJohn Marino add_stack_protection_conflicts (void)
1409e4b17023SJohn Marino {
1410e4b17023SJohn Marino   size_t i, j, n = stack_vars_num;
1411e4b17023SJohn Marino   unsigned char *phase;
1412e4b17023SJohn Marino 
1413e4b17023SJohn Marino   phase = XNEWVEC (unsigned char, n);
1414e4b17023SJohn Marino   for (i = 0; i < n; ++i)
1415e4b17023SJohn Marino     phase[i] = stack_protect_decl_phase (stack_vars[i].decl);
1416e4b17023SJohn Marino 
1417e4b17023SJohn Marino   for (i = 0; i < n; ++i)
1418e4b17023SJohn Marino     {
1419e4b17023SJohn Marino       unsigned char ph_i = phase[i];
1420e4b17023SJohn Marino       for (j = 0; j < i; ++j)
1421e4b17023SJohn Marino 	if (ph_i != phase[j])
1422e4b17023SJohn Marino 	  add_stack_var_conflict (i, j);
1423e4b17023SJohn Marino     }
1424e4b17023SJohn Marino 
1425e4b17023SJohn Marino   XDELETEVEC (phase);
1426e4b17023SJohn Marino }
1427e4b17023SJohn Marino 
1428e4b17023SJohn Marino /* Create a decl for the guard at the top of the stack frame.  */
1429e4b17023SJohn Marino 
1430e4b17023SJohn Marino static void
create_stack_guard(void)1431e4b17023SJohn Marino create_stack_guard (void)
1432e4b17023SJohn Marino {
1433e4b17023SJohn Marino   tree guard = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
1434e4b17023SJohn Marino 			   VAR_DECL, NULL, ptr_type_node);
1435e4b17023SJohn Marino   TREE_THIS_VOLATILE (guard) = 1;
1436e4b17023SJohn Marino   TREE_USED (guard) = 1;
1437e4b17023SJohn Marino   expand_one_stack_var (guard);
1438e4b17023SJohn Marino   crtl->stack_protect_guard = guard;
1439e4b17023SJohn Marino }
1440e4b17023SJohn Marino 
1441e4b17023SJohn Marino /* Prepare for expanding variables.  */
1442e4b17023SJohn Marino static void
init_vars_expansion(void)1443e4b17023SJohn Marino init_vars_expansion (void)
1444e4b17023SJohn Marino {
1445e4b17023SJohn Marino   tree t;
1446e4b17023SJohn Marino   unsigned ix;
1447e4b17023SJohn Marino   /* Set TREE_USED on all variables in the local_decls.  */
1448e4b17023SJohn Marino   FOR_EACH_LOCAL_DECL (cfun, ix, t)
1449e4b17023SJohn Marino     TREE_USED (t) = 1;
1450e4b17023SJohn Marino 
1451e4b17023SJohn Marino   /* Clear TREE_USED on all variables associated with a block scope.  */
1452e4b17023SJohn Marino   clear_tree_used (DECL_INITIAL (current_function_decl));
1453e4b17023SJohn Marino 
1454e4b17023SJohn Marino   /* Initialize local stack smashing state.  */
1455e4b17023SJohn Marino   has_protected_decls = false;
1456e4b17023SJohn Marino   has_short_buffer = false;
1457e4b17023SJohn Marino }
1458e4b17023SJohn Marino 
1459e4b17023SJohn Marino /* Free up stack variable graph data.  */
1460e4b17023SJohn Marino static void
fini_vars_expansion(void)1461e4b17023SJohn Marino fini_vars_expansion (void)
1462e4b17023SJohn Marino {
1463e4b17023SJohn Marino   size_t i, n = stack_vars_num;
1464e4b17023SJohn Marino   for (i = 0; i < n; i++)
1465e4b17023SJohn Marino     BITMAP_FREE (stack_vars[i].conflicts);
1466e4b17023SJohn Marino   XDELETEVEC (stack_vars);
1467e4b17023SJohn Marino   XDELETEVEC (stack_vars_sorted);
1468e4b17023SJohn Marino   stack_vars = NULL;
1469e4b17023SJohn Marino   stack_vars_alloc = stack_vars_num = 0;
1470e4b17023SJohn Marino   pointer_map_destroy (decl_to_stack_part);
1471e4b17023SJohn Marino   decl_to_stack_part = NULL;
1472e4b17023SJohn Marino }
1473e4b17023SJohn Marino 
1474e4b17023SJohn Marino /* Make a fair guess for the size of the stack frame of the function
1475e4b17023SJohn Marino    in NODE.  This doesn't have to be exact, the result is only used in
1476e4b17023SJohn Marino    the inline heuristics.  So we don't want to run the full stack var
1477e4b17023SJohn Marino    packing algorithm (which is quadratic in the number of stack vars).
1478e4b17023SJohn Marino    Instead, we calculate the total size of all stack vars.  This turns
1479e4b17023SJohn Marino    out to be a pretty fair estimate -- packing of stack vars doesn't
1480e4b17023SJohn Marino    happen very often.  */
1481e4b17023SJohn Marino 
1482e4b17023SJohn Marino HOST_WIDE_INT
estimated_stack_frame_size(struct cgraph_node * node)1483e4b17023SJohn Marino estimated_stack_frame_size (struct cgraph_node *node)
1484e4b17023SJohn Marino {
1485e4b17023SJohn Marino   HOST_WIDE_INT size = 0;
1486e4b17023SJohn Marino   size_t i;
1487e4b17023SJohn Marino   tree var;
1488e4b17023SJohn Marino   tree old_cur_fun_decl = current_function_decl;
1489e4b17023SJohn Marino   referenced_var_iterator rvi;
1490e4b17023SJohn Marino   struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
1491e4b17023SJohn Marino 
1492e4b17023SJohn Marino   current_function_decl = node->decl;
1493e4b17023SJohn Marino   push_cfun (fn);
1494e4b17023SJohn Marino 
1495e4b17023SJohn Marino   gcc_checking_assert (gimple_referenced_vars (fn));
1496e4b17023SJohn Marino   FOR_EACH_REFERENCED_VAR (fn, var, rvi)
1497e4b17023SJohn Marino     size += expand_one_var (var, true, false);
1498e4b17023SJohn Marino 
1499e4b17023SJohn Marino   if (stack_vars_num > 0)
1500e4b17023SJohn Marino     {
1501e4b17023SJohn Marino       /* Fake sorting the stack vars for account_stack_vars ().  */
1502e4b17023SJohn Marino       stack_vars_sorted = XNEWVEC (size_t, stack_vars_num);
1503e4b17023SJohn Marino       for (i = 0; i < stack_vars_num; ++i)
1504e4b17023SJohn Marino 	stack_vars_sorted[i] = i;
1505e4b17023SJohn Marino       size += account_stack_vars ();
1506e4b17023SJohn Marino       fini_vars_expansion ();
1507e4b17023SJohn Marino     }
1508e4b17023SJohn Marino   pop_cfun ();
1509e4b17023SJohn Marino   current_function_decl = old_cur_fun_decl;
1510e4b17023SJohn Marino   return size;
1511e4b17023SJohn Marino }
1512e4b17023SJohn Marino 
1513e4b17023SJohn Marino /* Expand all variables used in the function.  */
1514e4b17023SJohn Marino 
1515e4b17023SJohn Marino static void
expand_used_vars(void)1516e4b17023SJohn Marino expand_used_vars (void)
1517e4b17023SJohn Marino {
1518e4b17023SJohn Marino   tree var, outer_block = DECL_INITIAL (current_function_decl);
1519e4b17023SJohn Marino   VEC(tree,heap) *maybe_local_decls = NULL;
1520e4b17023SJohn Marino   unsigned i;
1521e4b17023SJohn Marino   unsigned len;
1522e4b17023SJohn Marino 
1523e4b17023SJohn Marino   /* Compute the phase of the stack frame for this function.  */
1524e4b17023SJohn Marino   {
1525e4b17023SJohn Marino     int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
1526e4b17023SJohn Marino     int off = STARTING_FRAME_OFFSET % align;
1527e4b17023SJohn Marino     frame_phase = off ? align - off : 0;
1528e4b17023SJohn Marino   }
1529e4b17023SJohn Marino 
1530e4b17023SJohn Marino   init_vars_expansion ();
1531e4b17023SJohn Marino 
1532e4b17023SJohn Marino   for (i = 0; i < SA.map->num_partitions; i++)
1533e4b17023SJohn Marino     {
1534e4b17023SJohn Marino       tree var = partition_to_var (SA.map, i);
1535e4b17023SJohn Marino 
1536e4b17023SJohn Marino       gcc_assert (is_gimple_reg (var));
1537e4b17023SJohn Marino       if (TREE_CODE (SSA_NAME_VAR (var)) == VAR_DECL)
1538e4b17023SJohn Marino 	expand_one_var (var, true, true);
1539e4b17023SJohn Marino       else
1540e4b17023SJohn Marino 	{
1541e4b17023SJohn Marino 	  /* This is a PARM_DECL or RESULT_DECL.  For those partitions that
1542e4b17023SJohn Marino 	     contain the default def (representing the parm or result itself)
1543e4b17023SJohn Marino 	     we don't do anything here.  But those which don't contain the
1544e4b17023SJohn Marino 	     default def (representing a temporary based on the parm/result)
1545e4b17023SJohn Marino 	     we need to allocate space just like for normal VAR_DECLs.  */
1546e4b17023SJohn Marino 	  if (!bitmap_bit_p (SA.partition_has_default_def, i))
1547e4b17023SJohn Marino 	    {
1548e4b17023SJohn Marino 	      expand_one_var (var, true, true);
1549e4b17023SJohn Marino 	      gcc_assert (SA.partition_to_pseudo[i]);
1550e4b17023SJohn Marino 	    }
1551e4b17023SJohn Marino 	}
1552e4b17023SJohn Marino     }
1553e4b17023SJohn Marino 
1554e4b17023SJohn Marino   /* At this point all variables on the local_decls with TREE_USED
1555e4b17023SJohn Marino      set are not associated with any block scope.  Lay them out.  */
1556e4b17023SJohn Marino 
1557e4b17023SJohn Marino   len = VEC_length (tree, cfun->local_decls);
1558e4b17023SJohn Marino   FOR_EACH_LOCAL_DECL (cfun, i, var)
1559e4b17023SJohn Marino     {
1560e4b17023SJohn Marino       bool expand_now = false;
1561e4b17023SJohn Marino 
1562e4b17023SJohn Marino       /* Expanded above already.  */
1563e4b17023SJohn Marino       if (is_gimple_reg (var))
1564e4b17023SJohn Marino 	{
1565e4b17023SJohn Marino 	  TREE_USED (var) = 0;
1566e4b17023SJohn Marino 	  goto next;
1567e4b17023SJohn Marino 	}
1568e4b17023SJohn Marino       /* We didn't set a block for static or extern because it's hard
1569e4b17023SJohn Marino 	 to tell the difference between a global variable (re)declared
1570e4b17023SJohn Marino 	 in a local scope, and one that's really declared there to
1571e4b17023SJohn Marino 	 begin with.  And it doesn't really matter much, since we're
1572e4b17023SJohn Marino 	 not giving them stack space.  Expand them now.  */
1573e4b17023SJohn Marino       else if (TREE_STATIC (var) || DECL_EXTERNAL (var))
1574e4b17023SJohn Marino 	expand_now = true;
1575e4b17023SJohn Marino 
1576e4b17023SJohn Marino       /* If the variable is not associated with any block, then it
1577e4b17023SJohn Marino 	 was created by the optimizers, and could be live anywhere
1578e4b17023SJohn Marino 	 in the function.  */
1579e4b17023SJohn Marino       else if (TREE_USED (var))
1580e4b17023SJohn Marino 	expand_now = true;
1581e4b17023SJohn Marino 
1582e4b17023SJohn Marino       /* Finally, mark all variables on the list as used.  We'll use
1583e4b17023SJohn Marino 	 this in a moment when we expand those associated with scopes.  */
1584e4b17023SJohn Marino       TREE_USED (var) = 1;
1585e4b17023SJohn Marino 
1586e4b17023SJohn Marino       if (expand_now)
1587e4b17023SJohn Marino 	expand_one_var (var, true, true);
1588e4b17023SJohn Marino 
1589e4b17023SJohn Marino     next:
1590e4b17023SJohn Marino       if (DECL_ARTIFICIAL (var) && !DECL_IGNORED_P (var))
1591e4b17023SJohn Marino 	{
1592e4b17023SJohn Marino 	  rtx rtl = DECL_RTL_IF_SET (var);
1593e4b17023SJohn Marino 
1594e4b17023SJohn Marino 	  /* Keep artificial non-ignored vars in cfun->local_decls
1595e4b17023SJohn Marino 	     chain until instantiate_decls.  */
1596e4b17023SJohn Marino 	  if (rtl && (MEM_P (rtl) || GET_CODE (rtl) == CONCAT))
1597e4b17023SJohn Marino 	    add_local_decl (cfun, var);
1598e4b17023SJohn Marino 	  else if (rtl == NULL_RTX)
1599e4b17023SJohn Marino 	    /* If rtl isn't set yet, which can happen e.g. with
1600e4b17023SJohn Marino 	       -fstack-protector, retry before returning from this
1601e4b17023SJohn Marino 	       function.  */
1602e4b17023SJohn Marino 	    VEC_safe_push (tree, heap, maybe_local_decls, var);
1603e4b17023SJohn Marino 	}
1604e4b17023SJohn Marino     }
1605e4b17023SJohn Marino 
1606e4b17023SJohn Marino   /* We duplicated some of the decls in CFUN->LOCAL_DECLS.
1607e4b17023SJohn Marino 
1608e4b17023SJohn Marino      +-----------------+-----------------+
1609e4b17023SJohn Marino      | ...processed... | ...duplicates...|
1610e4b17023SJohn Marino      +-----------------+-----------------+
1611e4b17023SJohn Marino                        ^
1612e4b17023SJohn Marino 		       +-- LEN points here.
1613e4b17023SJohn Marino 
1614e4b17023SJohn Marino      We just want the duplicates, as those are the artificial
1615e4b17023SJohn Marino      non-ignored vars that we want to keep until instantiate_decls.
1616e4b17023SJohn Marino      Move them down and truncate the array.  */
1617e4b17023SJohn Marino   if (!VEC_empty (tree, cfun->local_decls))
1618e4b17023SJohn Marino     VEC_block_remove (tree, cfun->local_decls, 0, len);
1619e4b17023SJohn Marino 
1620e4b17023SJohn Marino   /* At this point, all variables within the block tree with TREE_USED
1621e4b17023SJohn Marino      set are actually used by the optimized function.  Lay them out.  */
1622e4b17023SJohn Marino   expand_used_vars_for_block (outer_block, true);
1623e4b17023SJohn Marino 
1624e4b17023SJohn Marino   if (stack_vars_num > 0)
1625e4b17023SJohn Marino     {
1626e4b17023SJohn Marino       add_scope_conflicts ();
1627e4b17023SJohn Marino       /* Due to the way alias sets work, no variables with non-conflicting
1628e4b17023SJohn Marino 	 alias sets may be assigned the same address.  Add conflicts to
1629e4b17023SJohn Marino 	 reflect this.  */
1630e4b17023SJohn Marino       add_alias_set_conflicts ();
1631e4b17023SJohn Marino 
1632e4b17023SJohn Marino       /* If stack protection is enabled, we don't share space between
1633e4b17023SJohn Marino 	 vulnerable data and non-vulnerable data.  */
1634e4b17023SJohn Marino       if (flag_stack_protect)
1635e4b17023SJohn Marino 	add_stack_protection_conflicts ();
1636e4b17023SJohn Marino 
1637e4b17023SJohn Marino       /* Now that we have collected all stack variables, and have computed a
1638e4b17023SJohn Marino 	 minimal interference graph, attempt to save some stack space.  */
1639e4b17023SJohn Marino       partition_stack_vars ();
1640e4b17023SJohn Marino       if (dump_file)
1641e4b17023SJohn Marino 	dump_stack_var_partition ();
1642e4b17023SJohn Marino     }
1643e4b17023SJohn Marino 
1644e4b17023SJohn Marino   /* There are several conditions under which we should create a
1645e4b17023SJohn Marino      stack guard: protect-all, alloca used, protected decls present.  */
1646e4b17023SJohn Marino   if (flag_stack_protect == 2
1647e4b17023SJohn Marino       || (flag_stack_protect
1648e4b17023SJohn Marino 	  && (cfun->calls_alloca || has_protected_decls)))
1649e4b17023SJohn Marino     create_stack_guard ();
1650e4b17023SJohn Marino 
1651e4b17023SJohn Marino   /* Assign rtl to each variable based on these partitions.  */
1652e4b17023SJohn Marino   if (stack_vars_num > 0)
1653e4b17023SJohn Marino     {
1654e4b17023SJohn Marino       /* Reorder decls to be protected by iterating over the variables
1655e4b17023SJohn Marino 	 array multiple times, and allocating out of each phase in turn.  */
1656e4b17023SJohn Marino       /* ??? We could probably integrate this into the qsort we did
1657e4b17023SJohn Marino 	 earlier, such that we naturally see these variables first,
1658e4b17023SJohn Marino 	 and thus naturally allocate things in the right order.  */
1659e4b17023SJohn Marino       if (has_protected_decls)
1660e4b17023SJohn Marino 	{
1661e4b17023SJohn Marino 	  /* Phase 1 contains only character arrays.  */
1662e4b17023SJohn Marino 	  expand_stack_vars (stack_protect_decl_phase_1);
1663e4b17023SJohn Marino 
1664e4b17023SJohn Marino 	  /* Phase 2 contains other kinds of arrays.  */
1665e4b17023SJohn Marino 	  if (flag_stack_protect == 2)
1666e4b17023SJohn Marino 	    expand_stack_vars (stack_protect_decl_phase_2);
1667e4b17023SJohn Marino 	}
1668e4b17023SJohn Marino 
1669e4b17023SJohn Marino       expand_stack_vars (NULL);
1670e4b17023SJohn Marino 
1671e4b17023SJohn Marino       fini_vars_expansion ();
1672e4b17023SJohn Marino     }
1673e4b17023SJohn Marino 
1674e4b17023SJohn Marino   /* If there were any artificial non-ignored vars without rtl
1675e4b17023SJohn Marino      found earlier, see if deferred stack allocation hasn't assigned
1676e4b17023SJohn Marino      rtl to them.  */
1677e4b17023SJohn Marino   FOR_EACH_VEC_ELT_REVERSE (tree, maybe_local_decls, i, var)
1678e4b17023SJohn Marino     {
1679e4b17023SJohn Marino       rtx rtl = DECL_RTL_IF_SET (var);
1680e4b17023SJohn Marino 
1681e4b17023SJohn Marino       /* Keep artificial non-ignored vars in cfun->local_decls
1682e4b17023SJohn Marino 	 chain until instantiate_decls.  */
1683e4b17023SJohn Marino       if (rtl && (MEM_P (rtl) || GET_CODE (rtl) == CONCAT))
1684e4b17023SJohn Marino 	add_local_decl (cfun, var);
1685e4b17023SJohn Marino     }
1686e4b17023SJohn Marino   VEC_free (tree, heap, maybe_local_decls);
1687e4b17023SJohn Marino 
1688e4b17023SJohn Marino   /* If the target requires that FRAME_OFFSET be aligned, do it.  */
1689e4b17023SJohn Marino   if (STACK_ALIGNMENT_NEEDED)
1690e4b17023SJohn Marino     {
1691e4b17023SJohn Marino       HOST_WIDE_INT align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
1692e4b17023SJohn Marino       if (!FRAME_GROWS_DOWNWARD)
1693e4b17023SJohn Marino 	frame_offset += align - 1;
1694e4b17023SJohn Marino       frame_offset &= -align;
1695e4b17023SJohn Marino     }
1696e4b17023SJohn Marino }
1697e4b17023SJohn Marino 
1698e4b17023SJohn Marino 
1699e4b17023SJohn Marino /* If we need to produce a detailed dump, print the tree representation
1700e4b17023SJohn Marino    for STMT to the dump file.  SINCE is the last RTX after which the RTL
1701e4b17023SJohn Marino    generated for STMT should have been appended.  */
1702e4b17023SJohn Marino 
1703e4b17023SJohn Marino static void
maybe_dump_rtl_for_gimple_stmt(gimple stmt,rtx since)1704e4b17023SJohn Marino maybe_dump_rtl_for_gimple_stmt (gimple stmt, rtx since)
1705e4b17023SJohn Marino {
1706e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1707e4b17023SJohn Marino     {
1708e4b17023SJohn Marino       fprintf (dump_file, "\n;; ");
1709e4b17023SJohn Marino       print_gimple_stmt (dump_file, stmt, 0,
1710e4b17023SJohn Marino 			 TDF_SLIM | (dump_flags & TDF_LINENO));
1711e4b17023SJohn Marino       fprintf (dump_file, "\n");
1712e4b17023SJohn Marino 
1713e4b17023SJohn Marino       print_rtl (dump_file, since ? NEXT_INSN (since) : since);
1714e4b17023SJohn Marino     }
1715e4b17023SJohn Marino }
1716e4b17023SJohn Marino 
1717e4b17023SJohn Marino /* Maps the blocks that do not contain tree labels to rtx labels.  */
1718e4b17023SJohn Marino 
1719e4b17023SJohn Marino static struct pointer_map_t *lab_rtx_for_bb;
1720e4b17023SJohn Marino 
1721e4b17023SJohn Marino /* Returns the label_rtx expression for a label starting basic block BB.  */
1722e4b17023SJohn Marino 
1723e4b17023SJohn Marino static rtx
label_rtx_for_bb(basic_block bb ATTRIBUTE_UNUSED)1724e4b17023SJohn Marino label_rtx_for_bb (basic_block bb ATTRIBUTE_UNUSED)
1725e4b17023SJohn Marino {
1726e4b17023SJohn Marino   gimple_stmt_iterator gsi;
1727e4b17023SJohn Marino   tree lab;
1728e4b17023SJohn Marino   gimple lab_stmt;
1729e4b17023SJohn Marino   void **elt;
1730e4b17023SJohn Marino 
1731e4b17023SJohn Marino   if (bb->flags & BB_RTL)
1732e4b17023SJohn Marino     return block_label (bb);
1733e4b17023SJohn Marino 
1734e4b17023SJohn Marino   elt = pointer_map_contains (lab_rtx_for_bb, bb);
1735e4b17023SJohn Marino   if (elt)
1736e4b17023SJohn Marino     return (rtx) *elt;
1737e4b17023SJohn Marino 
1738e4b17023SJohn Marino   /* Find the tree label if it is present.  */
1739e4b17023SJohn Marino 
1740e4b17023SJohn Marino   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1741e4b17023SJohn Marino     {
1742e4b17023SJohn Marino       lab_stmt = gsi_stmt (gsi);
1743e4b17023SJohn Marino       if (gimple_code (lab_stmt) != GIMPLE_LABEL)
1744e4b17023SJohn Marino 	break;
1745e4b17023SJohn Marino 
1746e4b17023SJohn Marino       lab = gimple_label_label (lab_stmt);
1747e4b17023SJohn Marino       if (DECL_NONLOCAL (lab))
1748e4b17023SJohn Marino 	break;
1749e4b17023SJohn Marino 
1750e4b17023SJohn Marino       return label_rtx (lab);
1751e4b17023SJohn Marino     }
1752e4b17023SJohn Marino 
1753e4b17023SJohn Marino   elt = pointer_map_insert (lab_rtx_for_bb, bb);
1754e4b17023SJohn Marino   *elt = gen_label_rtx ();
1755e4b17023SJohn Marino   return (rtx) *elt;
1756e4b17023SJohn Marino }
1757e4b17023SJohn Marino 
1758e4b17023SJohn Marino 
1759e4b17023SJohn Marino /* A subroutine of expand_gimple_cond.  Given E, a fallthrough edge
1760e4b17023SJohn Marino    of a basic block where we just expanded the conditional at the end,
1761e4b17023SJohn Marino    possibly clean up the CFG and instruction sequence.  LAST is the
1762e4b17023SJohn Marino    last instruction before the just emitted jump sequence.  */
1763e4b17023SJohn Marino 
1764e4b17023SJohn Marino static void
maybe_cleanup_end_of_block(edge e,rtx last)1765e4b17023SJohn Marino maybe_cleanup_end_of_block (edge e, rtx last)
1766e4b17023SJohn Marino {
1767e4b17023SJohn Marino   /* Special case: when jumpif decides that the condition is
1768e4b17023SJohn Marino      trivial it emits an unconditional jump (and the necessary
1769e4b17023SJohn Marino      barrier).  But we still have two edges, the fallthru one is
1770e4b17023SJohn Marino      wrong.  purge_dead_edges would clean this up later.  Unfortunately
1771e4b17023SJohn Marino      we have to insert insns (and split edges) before
1772e4b17023SJohn Marino      find_many_sub_basic_blocks and hence before purge_dead_edges.
1773e4b17023SJohn Marino      But splitting edges might create new blocks which depend on the
1774e4b17023SJohn Marino      fact that if there are two edges there's no barrier.  So the
1775e4b17023SJohn Marino      barrier would get lost and verify_flow_info would ICE.  Instead
1776e4b17023SJohn Marino      of auditing all edge splitters to care for the barrier (which
1777e4b17023SJohn Marino      normally isn't there in a cleaned CFG), fix it here.  */
1778e4b17023SJohn Marino   if (BARRIER_P (get_last_insn ()))
1779e4b17023SJohn Marino     {
1780e4b17023SJohn Marino       rtx insn;
1781e4b17023SJohn Marino       remove_edge (e);
1782e4b17023SJohn Marino       /* Now, we have a single successor block, if we have insns to
1783e4b17023SJohn Marino 	 insert on the remaining edge we potentially will insert
1784e4b17023SJohn Marino 	 it at the end of this block (if the dest block isn't feasible)
1785e4b17023SJohn Marino 	 in order to avoid splitting the edge.  This insertion will take
1786e4b17023SJohn Marino 	 place in front of the last jump.  But we might have emitted
1787e4b17023SJohn Marino 	 multiple jumps (conditional and one unconditional) to the
1788e4b17023SJohn Marino 	 same destination.  Inserting in front of the last one then
1789e4b17023SJohn Marino 	 is a problem.  See PR 40021.  We fix this by deleting all
1790e4b17023SJohn Marino 	 jumps except the last unconditional one.  */
1791e4b17023SJohn Marino       insn = PREV_INSN (get_last_insn ());
1792e4b17023SJohn Marino       /* Make sure we have an unconditional jump.  Otherwise we're
1793e4b17023SJohn Marino 	 confused.  */
1794e4b17023SJohn Marino       gcc_assert (JUMP_P (insn) && !any_condjump_p (insn));
1795e4b17023SJohn Marino       for (insn = PREV_INSN (insn); insn != last;)
1796e4b17023SJohn Marino 	{
1797e4b17023SJohn Marino 	  insn = PREV_INSN (insn);
1798e4b17023SJohn Marino 	  if (JUMP_P (NEXT_INSN (insn)))
1799e4b17023SJohn Marino 	    {
1800e4b17023SJohn Marino 	      if (!any_condjump_p (NEXT_INSN (insn)))
1801e4b17023SJohn Marino 		{
1802e4b17023SJohn Marino 		  gcc_assert (BARRIER_P (NEXT_INSN (NEXT_INSN (insn))));
1803e4b17023SJohn Marino 		  delete_insn (NEXT_INSN (NEXT_INSN (insn)));
1804e4b17023SJohn Marino 		}
1805e4b17023SJohn Marino 	      delete_insn (NEXT_INSN (insn));
1806e4b17023SJohn Marino 	    }
1807e4b17023SJohn Marino 	}
1808e4b17023SJohn Marino     }
1809e4b17023SJohn Marino }
1810e4b17023SJohn Marino 
1811e4b17023SJohn Marino /* A subroutine of expand_gimple_basic_block.  Expand one GIMPLE_COND.
1812e4b17023SJohn Marino    Returns a new basic block if we've terminated the current basic
1813e4b17023SJohn Marino    block and created a new one.  */
1814e4b17023SJohn Marino 
1815e4b17023SJohn Marino static basic_block
expand_gimple_cond(basic_block bb,gimple stmt)1816e4b17023SJohn Marino expand_gimple_cond (basic_block bb, gimple stmt)
1817e4b17023SJohn Marino {
1818e4b17023SJohn Marino   basic_block new_bb, dest;
1819e4b17023SJohn Marino   edge new_edge;
1820e4b17023SJohn Marino   edge true_edge;
1821e4b17023SJohn Marino   edge false_edge;
1822e4b17023SJohn Marino   rtx last2, last;
1823e4b17023SJohn Marino   enum tree_code code;
1824e4b17023SJohn Marino   tree op0, op1;
1825e4b17023SJohn Marino 
1826e4b17023SJohn Marino   code = gimple_cond_code (stmt);
1827e4b17023SJohn Marino   op0 = gimple_cond_lhs (stmt);
1828e4b17023SJohn Marino   op1 = gimple_cond_rhs (stmt);
1829e4b17023SJohn Marino   /* We're sometimes presented with such code:
1830e4b17023SJohn Marino        D.123_1 = x < y;
1831e4b17023SJohn Marino        if (D.123_1 != 0)
1832e4b17023SJohn Marino          ...
1833e4b17023SJohn Marino      This would expand to two comparisons which then later might
1834e4b17023SJohn Marino      be cleaned up by combine.  But some pattern matchers like if-conversion
1835e4b17023SJohn Marino      work better when there's only one compare, so make up for this
1836e4b17023SJohn Marino      here as special exception if TER would have made the same change.  */
1837e4b17023SJohn Marino   if (gimple_cond_single_var_p (stmt)
1838e4b17023SJohn Marino       && SA.values
1839e4b17023SJohn Marino       && TREE_CODE (op0) == SSA_NAME
1840e4b17023SJohn Marino       && bitmap_bit_p (SA.values, SSA_NAME_VERSION (op0)))
1841e4b17023SJohn Marino     {
1842e4b17023SJohn Marino       gimple second = SSA_NAME_DEF_STMT (op0);
1843e4b17023SJohn Marino       if (gimple_code (second) == GIMPLE_ASSIGN)
1844e4b17023SJohn Marino 	{
1845e4b17023SJohn Marino 	  enum tree_code code2 = gimple_assign_rhs_code (second);
1846e4b17023SJohn Marino 	  if (TREE_CODE_CLASS (code2) == tcc_comparison)
1847e4b17023SJohn Marino 	    {
1848e4b17023SJohn Marino 	      code = code2;
1849e4b17023SJohn Marino 	      op0 = gimple_assign_rhs1 (second);
1850e4b17023SJohn Marino 	      op1 = gimple_assign_rhs2 (second);
1851e4b17023SJohn Marino 	    }
1852e4b17023SJohn Marino 	  /* If jumps are cheap turn some more codes into
1853e4b17023SJohn Marino 	     jumpy sequences.  */
1854e4b17023SJohn Marino 	  else if (BRANCH_COST (optimize_insn_for_speed_p (), false) < 4)
1855e4b17023SJohn Marino 	    {
1856e4b17023SJohn Marino 	      if ((code2 == BIT_AND_EXPR
1857e4b17023SJohn Marino 		   && TYPE_PRECISION (TREE_TYPE (op0)) == 1
1858e4b17023SJohn Marino 		   && TREE_CODE (gimple_assign_rhs2 (second)) != INTEGER_CST)
1859e4b17023SJohn Marino 		  || code2 == TRUTH_AND_EXPR)
1860e4b17023SJohn Marino 		{
1861e4b17023SJohn Marino 		  code = TRUTH_ANDIF_EXPR;
1862e4b17023SJohn Marino 		  op0 = gimple_assign_rhs1 (second);
1863e4b17023SJohn Marino 		  op1 = gimple_assign_rhs2 (second);
1864e4b17023SJohn Marino 		}
1865e4b17023SJohn Marino 	      else if (code2 == BIT_IOR_EXPR || code2 == TRUTH_OR_EXPR)
1866e4b17023SJohn Marino 		{
1867e4b17023SJohn Marino 		  code = TRUTH_ORIF_EXPR;
1868e4b17023SJohn Marino 		  op0 = gimple_assign_rhs1 (second);
1869e4b17023SJohn Marino 		  op1 = gimple_assign_rhs2 (second);
1870e4b17023SJohn Marino 		}
1871e4b17023SJohn Marino 	    }
1872e4b17023SJohn Marino 	}
1873e4b17023SJohn Marino     }
1874e4b17023SJohn Marino 
1875e4b17023SJohn Marino   last2 = last = get_last_insn ();
1876e4b17023SJohn Marino 
1877e4b17023SJohn Marino   extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
1878e4b17023SJohn Marino   set_curr_insn_source_location (gimple_location (stmt));
1879e4b17023SJohn Marino   set_curr_insn_block (gimple_block (stmt));
1880e4b17023SJohn Marino 
1881e4b17023SJohn Marino   /* These flags have no purpose in RTL land.  */
1882e4b17023SJohn Marino   true_edge->flags &= ~EDGE_TRUE_VALUE;
1883e4b17023SJohn Marino   false_edge->flags &= ~EDGE_FALSE_VALUE;
1884e4b17023SJohn Marino 
1885e4b17023SJohn Marino   /* We can either have a pure conditional jump with one fallthru edge or
1886e4b17023SJohn Marino      two-way jump that needs to be decomposed into two basic blocks.  */
1887e4b17023SJohn Marino   if (false_edge->dest == bb->next_bb)
1888e4b17023SJohn Marino     {
1889e4b17023SJohn Marino       jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
1890e4b17023SJohn Marino 		true_edge->probability);
1891e4b17023SJohn Marino       maybe_dump_rtl_for_gimple_stmt (stmt, last);
1892e4b17023SJohn Marino       if (true_edge->goto_locus)
1893e4b17023SJohn Marino 	{
1894e4b17023SJohn Marino 	  set_curr_insn_source_location (true_edge->goto_locus);
1895e4b17023SJohn Marino 	  set_curr_insn_block (true_edge->goto_block);
1896e4b17023SJohn Marino 	  true_edge->goto_locus = curr_insn_locator ();
1897e4b17023SJohn Marino 	}
1898e4b17023SJohn Marino       true_edge->goto_block = NULL;
1899e4b17023SJohn Marino       false_edge->flags |= EDGE_FALLTHRU;
1900e4b17023SJohn Marino       maybe_cleanup_end_of_block (false_edge, last);
1901e4b17023SJohn Marino       return NULL;
1902e4b17023SJohn Marino     }
1903e4b17023SJohn Marino   if (true_edge->dest == bb->next_bb)
1904e4b17023SJohn Marino     {
1905e4b17023SJohn Marino       jumpifnot_1 (code, op0, op1, label_rtx_for_bb (false_edge->dest),
1906e4b17023SJohn Marino 		   false_edge->probability);
1907e4b17023SJohn Marino       maybe_dump_rtl_for_gimple_stmt (stmt, last);
1908e4b17023SJohn Marino       if (false_edge->goto_locus)
1909e4b17023SJohn Marino 	{
1910e4b17023SJohn Marino 	  set_curr_insn_source_location (false_edge->goto_locus);
1911e4b17023SJohn Marino 	  set_curr_insn_block (false_edge->goto_block);
1912e4b17023SJohn Marino 	  false_edge->goto_locus = curr_insn_locator ();
1913e4b17023SJohn Marino 	}
1914e4b17023SJohn Marino       false_edge->goto_block = NULL;
1915e4b17023SJohn Marino       true_edge->flags |= EDGE_FALLTHRU;
1916e4b17023SJohn Marino       maybe_cleanup_end_of_block (true_edge, last);
1917e4b17023SJohn Marino       return NULL;
1918e4b17023SJohn Marino     }
1919e4b17023SJohn Marino 
1920e4b17023SJohn Marino   jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
1921e4b17023SJohn Marino 	    true_edge->probability);
1922e4b17023SJohn Marino   last = get_last_insn ();
1923e4b17023SJohn Marino   if (false_edge->goto_locus)
1924e4b17023SJohn Marino     {
1925e4b17023SJohn Marino       set_curr_insn_source_location (false_edge->goto_locus);
1926e4b17023SJohn Marino       set_curr_insn_block (false_edge->goto_block);
1927e4b17023SJohn Marino       false_edge->goto_locus = curr_insn_locator ();
1928e4b17023SJohn Marino     }
1929e4b17023SJohn Marino   false_edge->goto_block = NULL;
1930e4b17023SJohn Marino   emit_jump (label_rtx_for_bb (false_edge->dest));
1931e4b17023SJohn Marino 
1932e4b17023SJohn Marino   BB_END (bb) = last;
1933e4b17023SJohn Marino   if (BARRIER_P (BB_END (bb)))
1934e4b17023SJohn Marino     BB_END (bb) = PREV_INSN (BB_END (bb));
1935e4b17023SJohn Marino   update_bb_for_insn (bb);
1936e4b17023SJohn Marino 
1937e4b17023SJohn Marino   new_bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb);
1938e4b17023SJohn Marino   dest = false_edge->dest;
1939e4b17023SJohn Marino   redirect_edge_succ (false_edge, new_bb);
1940e4b17023SJohn Marino   false_edge->flags |= EDGE_FALLTHRU;
1941e4b17023SJohn Marino   new_bb->count = false_edge->count;
1942e4b17023SJohn Marino   new_bb->frequency = EDGE_FREQUENCY (false_edge);
1943e4b17023SJohn Marino   new_edge = make_edge (new_bb, dest, 0);
1944e4b17023SJohn Marino   new_edge->probability = REG_BR_PROB_BASE;
1945e4b17023SJohn Marino   new_edge->count = new_bb->count;
1946e4b17023SJohn Marino   if (BARRIER_P (BB_END (new_bb)))
1947e4b17023SJohn Marino     BB_END (new_bb) = PREV_INSN (BB_END (new_bb));
1948e4b17023SJohn Marino   update_bb_for_insn (new_bb);
1949e4b17023SJohn Marino 
1950e4b17023SJohn Marino   maybe_dump_rtl_for_gimple_stmt (stmt, last2);
1951e4b17023SJohn Marino 
1952e4b17023SJohn Marino   if (true_edge->goto_locus)
1953e4b17023SJohn Marino     {
1954e4b17023SJohn Marino       set_curr_insn_source_location (true_edge->goto_locus);
1955e4b17023SJohn Marino       set_curr_insn_block (true_edge->goto_block);
1956e4b17023SJohn Marino       true_edge->goto_locus = curr_insn_locator ();
1957e4b17023SJohn Marino     }
1958e4b17023SJohn Marino   true_edge->goto_block = NULL;
1959e4b17023SJohn Marino 
1960e4b17023SJohn Marino   return new_bb;
1961e4b17023SJohn Marino }
1962e4b17023SJohn Marino 
1963e4b17023SJohn Marino /* Mark all calls that can have a transaction restart.  */
1964e4b17023SJohn Marino 
1965e4b17023SJohn Marino static void
mark_transaction_restart_calls(gimple stmt)1966e4b17023SJohn Marino mark_transaction_restart_calls (gimple stmt)
1967e4b17023SJohn Marino {
1968e4b17023SJohn Marino   struct tm_restart_node dummy;
1969e4b17023SJohn Marino   void **slot;
1970e4b17023SJohn Marino 
1971e4b17023SJohn Marino   if (!cfun->gimple_df->tm_restart)
1972e4b17023SJohn Marino     return;
1973e4b17023SJohn Marino 
1974e4b17023SJohn Marino   dummy.stmt = stmt;
1975e4b17023SJohn Marino   slot = htab_find_slot (cfun->gimple_df->tm_restart, &dummy, NO_INSERT);
1976e4b17023SJohn Marino   if (slot)
1977e4b17023SJohn Marino     {
1978e4b17023SJohn Marino       struct tm_restart_node *n = (struct tm_restart_node *) *slot;
1979e4b17023SJohn Marino       tree list = n->label_or_list;
1980e4b17023SJohn Marino       rtx insn;
1981e4b17023SJohn Marino 
1982e4b17023SJohn Marino       for (insn = next_real_insn (get_last_insn ());
1983e4b17023SJohn Marino 	   !CALL_P (insn);
1984e4b17023SJohn Marino 	   insn = next_real_insn (insn))
1985e4b17023SJohn Marino 	continue;
1986e4b17023SJohn Marino 
1987e4b17023SJohn Marino       if (TREE_CODE (list) == LABEL_DECL)
1988e4b17023SJohn Marino 	add_reg_note (insn, REG_TM, label_rtx (list));
1989e4b17023SJohn Marino       else
1990e4b17023SJohn Marino 	for (; list ; list = TREE_CHAIN (list))
1991e4b17023SJohn Marino 	  add_reg_note (insn, REG_TM, label_rtx (TREE_VALUE (list)));
1992e4b17023SJohn Marino     }
1993e4b17023SJohn Marino }
1994e4b17023SJohn Marino 
1995e4b17023SJohn Marino /* A subroutine of expand_gimple_stmt_1, expanding one GIMPLE_CALL
1996e4b17023SJohn Marino    statement STMT.  */
1997e4b17023SJohn Marino 
1998e4b17023SJohn Marino static void
expand_call_stmt(gimple stmt)1999e4b17023SJohn Marino expand_call_stmt (gimple stmt)
2000e4b17023SJohn Marino {
2001e4b17023SJohn Marino   tree exp, decl, lhs;
2002e4b17023SJohn Marino   bool builtin_p;
2003e4b17023SJohn Marino   size_t i;
2004e4b17023SJohn Marino 
2005e4b17023SJohn Marino   if (gimple_call_internal_p (stmt))
2006e4b17023SJohn Marino     {
2007e4b17023SJohn Marino       expand_internal_call (stmt);
2008e4b17023SJohn Marino       return;
2009e4b17023SJohn Marino     }
2010e4b17023SJohn Marino 
2011e4b17023SJohn Marino   exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
2012e4b17023SJohn Marino 
2013e4b17023SJohn Marino   CALL_EXPR_FN (exp) = gimple_call_fn (stmt);
2014e4b17023SJohn Marino   decl = gimple_call_fndecl (stmt);
2015e4b17023SJohn Marino   builtin_p = decl && DECL_BUILT_IN (decl);
2016e4b17023SJohn Marino 
2017e4b17023SJohn Marino   /* If this is not a builtin function, the function type through which the
2018e4b17023SJohn Marino      call is made may be different from the type of the function.  */
2019e4b17023SJohn Marino   if (!builtin_p)
2020e4b17023SJohn Marino     CALL_EXPR_FN (exp)
2021e4b17023SJohn Marino       = fold_convert (build_pointer_type (gimple_call_fntype (stmt)),
2022e4b17023SJohn Marino 		      CALL_EXPR_FN (exp));
2023e4b17023SJohn Marino 
2024e4b17023SJohn Marino   TREE_TYPE (exp) = gimple_call_return_type (stmt);
2025e4b17023SJohn Marino   CALL_EXPR_STATIC_CHAIN (exp) = gimple_call_chain (stmt);
2026e4b17023SJohn Marino 
2027e4b17023SJohn Marino   for (i = 0; i < gimple_call_num_args (stmt); i++)
2028e4b17023SJohn Marino     {
2029e4b17023SJohn Marino       tree arg = gimple_call_arg (stmt, i);
2030e4b17023SJohn Marino       gimple def;
2031e4b17023SJohn Marino       /* TER addresses into arguments of builtin functions so we have a
2032e4b17023SJohn Marino 	 chance to infer more correct alignment information.  See PR39954.  */
2033e4b17023SJohn Marino       if (builtin_p
2034e4b17023SJohn Marino 	  && TREE_CODE (arg) == SSA_NAME
2035e4b17023SJohn Marino 	  && (def = get_gimple_for_ssa_name (arg))
2036e4b17023SJohn Marino 	  && gimple_assign_rhs_code (def) == ADDR_EXPR)
2037e4b17023SJohn Marino 	arg = gimple_assign_rhs1 (def);
2038e4b17023SJohn Marino       CALL_EXPR_ARG (exp, i) = arg;
2039e4b17023SJohn Marino     }
2040e4b17023SJohn Marino 
2041e4b17023SJohn Marino   if (gimple_has_side_effects (stmt))
2042e4b17023SJohn Marino     TREE_SIDE_EFFECTS (exp) = 1;
2043e4b17023SJohn Marino 
2044e4b17023SJohn Marino   if (gimple_call_nothrow_p (stmt))
2045e4b17023SJohn Marino     TREE_NOTHROW (exp) = 1;
2046e4b17023SJohn Marino 
2047e4b17023SJohn Marino   CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt);
2048e4b17023SJohn Marino   CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt);
2049e4b17023SJohn Marino   if (decl
2050e4b17023SJohn Marino       && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
2051e4b17023SJohn Marino       && (DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA
2052e4b17023SJohn Marino 	  || DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA_WITH_ALIGN))
2053e4b17023SJohn Marino     CALL_ALLOCA_FOR_VAR_P (exp) = gimple_call_alloca_for_var_p (stmt);
2054e4b17023SJohn Marino   else
2055e4b17023SJohn Marino     CALL_FROM_THUNK_P (exp) = gimple_call_from_thunk_p (stmt);
2056e4b17023SJohn Marino   CALL_EXPR_VA_ARG_PACK (exp) = gimple_call_va_arg_pack_p (stmt);
2057e4b17023SJohn Marino   SET_EXPR_LOCATION (exp, gimple_location (stmt));
2058e4b17023SJohn Marino   TREE_BLOCK (exp) = gimple_block (stmt);
2059e4b17023SJohn Marino 
2060e4b17023SJohn Marino   /* Ensure RTL is created for debug args.  */
2061e4b17023SJohn Marino   if (decl && DECL_HAS_DEBUG_ARGS_P (decl))
2062e4b17023SJohn Marino     {
2063e4b17023SJohn Marino       VEC(tree, gc) **debug_args = decl_debug_args_lookup (decl);
2064e4b17023SJohn Marino       unsigned int ix;
2065e4b17023SJohn Marino       tree dtemp;
2066e4b17023SJohn Marino 
2067e4b17023SJohn Marino       if (debug_args)
2068e4b17023SJohn Marino 	for (ix = 1; VEC_iterate (tree, *debug_args, ix, dtemp); ix += 2)
2069e4b17023SJohn Marino 	  {
2070e4b17023SJohn Marino 	    gcc_assert (TREE_CODE (dtemp) == DEBUG_EXPR_DECL);
2071e4b17023SJohn Marino 	    expand_debug_expr (dtemp);
2072e4b17023SJohn Marino 	  }
2073e4b17023SJohn Marino     }
2074e4b17023SJohn Marino 
2075e4b17023SJohn Marino   lhs = gimple_call_lhs (stmt);
2076e4b17023SJohn Marino   if (lhs)
2077e4b17023SJohn Marino     expand_assignment (lhs, exp, false);
2078e4b17023SJohn Marino   else
2079e4b17023SJohn Marino     expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL);
2080e4b17023SJohn Marino 
2081e4b17023SJohn Marino   mark_transaction_restart_calls (stmt);
2082e4b17023SJohn Marino }
2083e4b17023SJohn Marino 
2084e4b17023SJohn Marino /* A subroutine of expand_gimple_stmt, expanding one gimple statement
2085e4b17023SJohn Marino    STMT that doesn't require special handling for outgoing edges.  That
2086e4b17023SJohn Marino    is no tailcalls and no GIMPLE_COND.  */
2087e4b17023SJohn Marino 
2088e4b17023SJohn Marino static void
expand_gimple_stmt_1(gimple stmt)2089e4b17023SJohn Marino expand_gimple_stmt_1 (gimple stmt)
2090e4b17023SJohn Marino {
2091e4b17023SJohn Marino   tree op0;
2092e4b17023SJohn Marino 
2093e4b17023SJohn Marino   set_curr_insn_source_location (gimple_location (stmt));
2094e4b17023SJohn Marino   set_curr_insn_block (gimple_block (stmt));
2095e4b17023SJohn Marino 
2096e4b17023SJohn Marino   switch (gimple_code (stmt))
2097e4b17023SJohn Marino     {
2098e4b17023SJohn Marino     case GIMPLE_GOTO:
2099e4b17023SJohn Marino       op0 = gimple_goto_dest (stmt);
2100e4b17023SJohn Marino       if (TREE_CODE (op0) == LABEL_DECL)
2101e4b17023SJohn Marino 	expand_goto (op0);
2102e4b17023SJohn Marino       else
2103e4b17023SJohn Marino 	expand_computed_goto (op0);
2104e4b17023SJohn Marino       break;
2105e4b17023SJohn Marino     case GIMPLE_LABEL:
2106e4b17023SJohn Marino       expand_label (gimple_label_label (stmt));
2107e4b17023SJohn Marino       break;
2108e4b17023SJohn Marino     case GIMPLE_NOP:
2109e4b17023SJohn Marino     case GIMPLE_PREDICT:
2110e4b17023SJohn Marino       break;
2111e4b17023SJohn Marino     case GIMPLE_SWITCH:
2112e4b17023SJohn Marino       expand_case (stmt);
2113e4b17023SJohn Marino       break;
2114e4b17023SJohn Marino     case GIMPLE_ASM:
2115e4b17023SJohn Marino       expand_asm_stmt (stmt);
2116e4b17023SJohn Marino       break;
2117e4b17023SJohn Marino     case GIMPLE_CALL:
2118e4b17023SJohn Marino       expand_call_stmt (stmt);
2119e4b17023SJohn Marino       break;
2120e4b17023SJohn Marino 
2121e4b17023SJohn Marino     case GIMPLE_RETURN:
2122e4b17023SJohn Marino       op0 = gimple_return_retval (stmt);
2123e4b17023SJohn Marino 
2124e4b17023SJohn Marino       if (op0 && op0 != error_mark_node)
2125e4b17023SJohn Marino 	{
2126e4b17023SJohn Marino 	  tree result = DECL_RESULT (current_function_decl);
2127e4b17023SJohn Marino 
2128e4b17023SJohn Marino 	  /* If we are not returning the current function's RESULT_DECL,
2129e4b17023SJohn Marino 	     build an assignment to it.  */
2130e4b17023SJohn Marino 	  if (op0 != result)
2131e4b17023SJohn Marino 	    {
2132e4b17023SJohn Marino 	      /* I believe that a function's RESULT_DECL is unique.  */
2133e4b17023SJohn Marino 	      gcc_assert (TREE_CODE (op0) != RESULT_DECL);
2134e4b17023SJohn Marino 
2135e4b17023SJohn Marino 	      /* ??? We'd like to use simply expand_assignment here,
2136e4b17023SJohn Marino 	         but this fails if the value is of BLKmode but the return
2137e4b17023SJohn Marino 		 decl is a register.  expand_return has special handling
2138e4b17023SJohn Marino 		 for this combination, which eventually should move
2139e4b17023SJohn Marino 		 to common code.  See comments there.  Until then, let's
2140e4b17023SJohn Marino 		 build a modify expression :-/  */
2141e4b17023SJohn Marino 	      op0 = build2 (MODIFY_EXPR, TREE_TYPE (result),
2142e4b17023SJohn Marino 			    result, op0);
2143e4b17023SJohn Marino 	    }
2144e4b17023SJohn Marino 	}
2145e4b17023SJohn Marino       if (!op0)
2146e4b17023SJohn Marino 	expand_null_return ();
2147e4b17023SJohn Marino       else
2148e4b17023SJohn Marino 	expand_return (op0);
2149e4b17023SJohn Marino       break;
2150e4b17023SJohn Marino 
2151e4b17023SJohn Marino     case GIMPLE_ASSIGN:
2152e4b17023SJohn Marino       {
2153e4b17023SJohn Marino 	tree lhs = gimple_assign_lhs (stmt);
2154e4b17023SJohn Marino 
2155e4b17023SJohn Marino 	/* Tree expand used to fiddle with |= and &= of two bitfield
2156e4b17023SJohn Marino 	   COMPONENT_REFs here.  This can't happen with gimple, the LHS
2157e4b17023SJohn Marino 	   of binary assigns must be a gimple reg.  */
2158e4b17023SJohn Marino 
2159e4b17023SJohn Marino 	if (TREE_CODE (lhs) != SSA_NAME
2160e4b17023SJohn Marino 	    || get_gimple_rhs_class (gimple_expr_code (stmt))
2161e4b17023SJohn Marino 	       == GIMPLE_SINGLE_RHS)
2162e4b17023SJohn Marino 	  {
2163e4b17023SJohn Marino 	    tree rhs = gimple_assign_rhs1 (stmt);
2164e4b17023SJohn Marino 	    gcc_assert (get_gimple_rhs_class (gimple_expr_code (stmt))
2165e4b17023SJohn Marino 			== GIMPLE_SINGLE_RHS);
2166e4b17023SJohn Marino 	    if (gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (rhs))
2167e4b17023SJohn Marino 	      SET_EXPR_LOCATION (rhs, gimple_location (stmt));
2168e4b17023SJohn Marino 	    if (TREE_CLOBBER_P (rhs))
2169e4b17023SJohn Marino 	      /* This is a clobber to mark the going out of scope for
2170e4b17023SJohn Marino 		 this LHS.  */
2171e4b17023SJohn Marino 	      ;
2172e4b17023SJohn Marino 	    else
2173e4b17023SJohn Marino 	      expand_assignment (lhs, rhs,
2174e4b17023SJohn Marino 				 gimple_assign_nontemporal_move_p (stmt));
2175e4b17023SJohn Marino 	  }
2176e4b17023SJohn Marino 	else
2177e4b17023SJohn Marino 	  {
2178e4b17023SJohn Marino 	    rtx target, temp;
2179e4b17023SJohn Marino 	    bool nontemporal = gimple_assign_nontemporal_move_p (stmt);
2180e4b17023SJohn Marino 	    struct separate_ops ops;
2181e4b17023SJohn Marino 	    bool promoted = false;
2182e4b17023SJohn Marino 
2183e4b17023SJohn Marino 	    target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2184e4b17023SJohn Marino 	    if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
2185e4b17023SJohn Marino 	      promoted = true;
2186e4b17023SJohn Marino 
2187e4b17023SJohn Marino 	    ops.code = gimple_assign_rhs_code (stmt);
2188e4b17023SJohn Marino 	    ops.type = TREE_TYPE (lhs);
2189e4b17023SJohn Marino 	    switch (get_gimple_rhs_class (gimple_expr_code (stmt)))
2190e4b17023SJohn Marino 	      {
2191e4b17023SJohn Marino 		case GIMPLE_TERNARY_RHS:
2192e4b17023SJohn Marino 		  ops.op2 = gimple_assign_rhs3 (stmt);
2193e4b17023SJohn Marino 		  /* Fallthru */
2194e4b17023SJohn Marino 		case GIMPLE_BINARY_RHS:
2195e4b17023SJohn Marino 		  ops.op1 = gimple_assign_rhs2 (stmt);
2196e4b17023SJohn Marino 		  /* Fallthru */
2197e4b17023SJohn Marino 		case GIMPLE_UNARY_RHS:
2198e4b17023SJohn Marino 		  ops.op0 = gimple_assign_rhs1 (stmt);
2199e4b17023SJohn Marino 		  break;
2200e4b17023SJohn Marino 		default:
2201e4b17023SJohn Marino 		  gcc_unreachable ();
2202e4b17023SJohn Marino 	      }
2203e4b17023SJohn Marino 	    ops.location = gimple_location (stmt);
2204e4b17023SJohn Marino 
2205e4b17023SJohn Marino 	    /* If we want to use a nontemporal store, force the value to
2206e4b17023SJohn Marino 	       register first.  If we store into a promoted register,
2207e4b17023SJohn Marino 	       don't directly expand to target.  */
2208e4b17023SJohn Marino 	    temp = nontemporal || promoted ? NULL_RTX : target;
2209e4b17023SJohn Marino 	    temp = expand_expr_real_2 (&ops, temp, GET_MODE (target),
2210e4b17023SJohn Marino 				       EXPAND_NORMAL);
2211e4b17023SJohn Marino 
2212e4b17023SJohn Marino 	    if (temp == target)
2213e4b17023SJohn Marino 	      ;
2214e4b17023SJohn Marino 	    else if (promoted)
2215e4b17023SJohn Marino 	      {
2216e4b17023SJohn Marino 		int unsignedp = SUBREG_PROMOTED_UNSIGNED_P (target);
2217e4b17023SJohn Marino 		/* If TEMP is a VOIDmode constant, use convert_modes to make
2218e4b17023SJohn Marino 		   sure that we properly convert it.  */
2219e4b17023SJohn Marino 		if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode)
2220e4b17023SJohn Marino 		  {
2221e4b17023SJohn Marino 		    temp = convert_modes (GET_MODE (target),
2222e4b17023SJohn Marino 					  TYPE_MODE (ops.type),
2223e4b17023SJohn Marino 					  temp, unsignedp);
2224e4b17023SJohn Marino 		    temp = convert_modes (GET_MODE (SUBREG_REG (target)),
2225e4b17023SJohn Marino 					  GET_MODE (target), temp, unsignedp);
2226e4b17023SJohn Marino 		  }
2227e4b17023SJohn Marino 
2228e4b17023SJohn Marino 		convert_move (SUBREG_REG (target), temp, unsignedp);
2229e4b17023SJohn Marino 	      }
2230e4b17023SJohn Marino 	    else if (nontemporal && emit_storent_insn (target, temp))
2231e4b17023SJohn Marino 	      ;
2232e4b17023SJohn Marino 	    else
2233e4b17023SJohn Marino 	      {
2234e4b17023SJohn Marino 		temp = force_operand (temp, target);
2235e4b17023SJohn Marino 		if (temp != target)
2236e4b17023SJohn Marino 		  emit_move_insn (target, temp);
2237e4b17023SJohn Marino 	      }
2238e4b17023SJohn Marino 	  }
2239e4b17023SJohn Marino       }
2240e4b17023SJohn Marino       break;
2241e4b17023SJohn Marino 
2242e4b17023SJohn Marino     default:
2243e4b17023SJohn Marino       gcc_unreachable ();
2244e4b17023SJohn Marino     }
2245e4b17023SJohn Marino }
2246e4b17023SJohn Marino 
2247e4b17023SJohn Marino /* Expand one gimple statement STMT and return the last RTL instruction
2248e4b17023SJohn Marino    before any of the newly generated ones.
2249e4b17023SJohn Marino 
2250e4b17023SJohn Marino    In addition to generating the necessary RTL instructions this also
2251e4b17023SJohn Marino    sets REG_EH_REGION notes if necessary and sets the current source
2252e4b17023SJohn Marino    location for diagnostics.  */
2253e4b17023SJohn Marino 
2254e4b17023SJohn Marino static rtx
expand_gimple_stmt(gimple stmt)2255e4b17023SJohn Marino expand_gimple_stmt (gimple stmt)
2256e4b17023SJohn Marino {
2257e4b17023SJohn Marino   location_t saved_location = input_location;
2258e4b17023SJohn Marino   rtx last = get_last_insn ();
2259e4b17023SJohn Marino   int lp_nr;
2260e4b17023SJohn Marino 
2261e4b17023SJohn Marino   gcc_assert (cfun);
2262e4b17023SJohn Marino 
2263e4b17023SJohn Marino   /* We need to save and restore the current source location so that errors
2264e4b17023SJohn Marino      discovered during expansion are emitted with the right location.  But
2265e4b17023SJohn Marino      it would be better if the diagnostic routines used the source location
2266e4b17023SJohn Marino      embedded in the tree nodes rather than globals.  */
2267e4b17023SJohn Marino   if (gimple_has_location (stmt))
2268e4b17023SJohn Marino     input_location = gimple_location (stmt);
2269e4b17023SJohn Marino 
2270e4b17023SJohn Marino   expand_gimple_stmt_1 (stmt);
2271e4b17023SJohn Marino 
2272e4b17023SJohn Marino   /* Free any temporaries used to evaluate this statement.  */
2273e4b17023SJohn Marino   free_temp_slots ();
2274e4b17023SJohn Marino 
2275e4b17023SJohn Marino   input_location = saved_location;
2276e4b17023SJohn Marino 
2277e4b17023SJohn Marino   /* Mark all insns that may trap.  */
2278e4b17023SJohn Marino   lp_nr = lookup_stmt_eh_lp (stmt);
2279e4b17023SJohn Marino   if (lp_nr)
2280e4b17023SJohn Marino     {
2281e4b17023SJohn Marino       rtx insn;
2282e4b17023SJohn Marino       for (insn = next_real_insn (last); insn;
2283e4b17023SJohn Marino 	   insn = next_real_insn (insn))
2284e4b17023SJohn Marino 	{
2285e4b17023SJohn Marino 	  if (! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
2286e4b17023SJohn Marino 	      /* If we want exceptions for non-call insns, any
2287e4b17023SJohn Marino 		 may_trap_p instruction may throw.  */
2288e4b17023SJohn Marino 	      && GET_CODE (PATTERN (insn)) != CLOBBER
2289e4b17023SJohn Marino 	      && GET_CODE (PATTERN (insn)) != USE
2290e4b17023SJohn Marino 	      && insn_could_throw_p (insn))
2291e4b17023SJohn Marino 	    make_reg_eh_region_note (insn, 0, lp_nr);
2292e4b17023SJohn Marino 	}
2293e4b17023SJohn Marino     }
2294e4b17023SJohn Marino 
2295e4b17023SJohn Marino   return last;
2296e4b17023SJohn Marino }
2297e4b17023SJohn Marino 
2298e4b17023SJohn Marino /* A subroutine of expand_gimple_basic_block.  Expand one GIMPLE_CALL
2299e4b17023SJohn Marino    that has CALL_EXPR_TAILCALL set.  Returns non-null if we actually
2300e4b17023SJohn Marino    generated a tail call (something that might be denied by the ABI
2301e4b17023SJohn Marino    rules governing the call; see calls.c).
2302e4b17023SJohn Marino 
2303e4b17023SJohn Marino    Sets CAN_FALLTHRU if we generated a *conditional* tail call, and
2304e4b17023SJohn Marino    can still reach the rest of BB.  The case here is __builtin_sqrt,
2305e4b17023SJohn Marino    where the NaN result goes through the external function (with a
2306e4b17023SJohn Marino    tailcall) and the normal result happens via a sqrt instruction.  */
2307e4b17023SJohn Marino 
2308e4b17023SJohn Marino static basic_block
expand_gimple_tailcall(basic_block bb,gimple stmt,bool * can_fallthru)2309e4b17023SJohn Marino expand_gimple_tailcall (basic_block bb, gimple stmt, bool *can_fallthru)
2310e4b17023SJohn Marino {
2311e4b17023SJohn Marino   rtx last2, last;
2312e4b17023SJohn Marino   edge e;
2313e4b17023SJohn Marino   edge_iterator ei;
2314e4b17023SJohn Marino   int probability;
2315e4b17023SJohn Marino   gcov_type count;
2316e4b17023SJohn Marino 
2317e4b17023SJohn Marino   last2 = last = expand_gimple_stmt (stmt);
2318e4b17023SJohn Marino 
2319e4b17023SJohn Marino   for (last = NEXT_INSN (last); last; last = NEXT_INSN (last))
2320e4b17023SJohn Marino     if (CALL_P (last) && SIBLING_CALL_P (last))
2321e4b17023SJohn Marino       goto found;
2322e4b17023SJohn Marino 
2323e4b17023SJohn Marino   maybe_dump_rtl_for_gimple_stmt (stmt, last2);
2324e4b17023SJohn Marino 
2325e4b17023SJohn Marino   *can_fallthru = true;
2326e4b17023SJohn Marino   return NULL;
2327e4b17023SJohn Marino 
2328e4b17023SJohn Marino  found:
2329e4b17023SJohn Marino   /* ??? Wouldn't it be better to just reset any pending stack adjust?
2330e4b17023SJohn Marino      Any instructions emitted here are about to be deleted.  */
2331e4b17023SJohn Marino   do_pending_stack_adjust ();
2332e4b17023SJohn Marino 
2333e4b17023SJohn Marino   /* Remove any non-eh, non-abnormal edges that don't go to exit.  */
2334e4b17023SJohn Marino   /* ??? I.e. the fallthrough edge.  HOWEVER!  If there were to be
2335e4b17023SJohn Marino      EH or abnormal edges, we shouldn't have created a tail call in
2336e4b17023SJohn Marino      the first place.  So it seems to me we should just be removing
2337e4b17023SJohn Marino      all edges here, or redirecting the existing fallthru edge to
2338e4b17023SJohn Marino      the exit block.  */
2339e4b17023SJohn Marino 
2340e4b17023SJohn Marino   probability = 0;
2341e4b17023SJohn Marino   count = 0;
2342e4b17023SJohn Marino 
2343e4b17023SJohn Marino   for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
2344e4b17023SJohn Marino     {
2345e4b17023SJohn Marino       if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
2346e4b17023SJohn Marino 	{
2347e4b17023SJohn Marino 	  if (e->dest != EXIT_BLOCK_PTR)
2348e4b17023SJohn Marino 	    {
2349e4b17023SJohn Marino 	      e->dest->count -= e->count;
2350e4b17023SJohn Marino 	      e->dest->frequency -= EDGE_FREQUENCY (e);
2351e4b17023SJohn Marino 	      if (e->dest->count < 0)
2352e4b17023SJohn Marino 		e->dest->count = 0;
2353e4b17023SJohn Marino 	      if (e->dest->frequency < 0)
2354e4b17023SJohn Marino 		e->dest->frequency = 0;
2355e4b17023SJohn Marino 	    }
2356e4b17023SJohn Marino 	  count += e->count;
2357e4b17023SJohn Marino 	  probability += e->probability;
2358e4b17023SJohn Marino 	  remove_edge (e);
2359e4b17023SJohn Marino 	}
2360e4b17023SJohn Marino       else
2361e4b17023SJohn Marino 	ei_next (&ei);
2362e4b17023SJohn Marino     }
2363e4b17023SJohn Marino 
2364e4b17023SJohn Marino   /* This is somewhat ugly: the call_expr expander often emits instructions
2365e4b17023SJohn Marino      after the sibcall (to perform the function return).  These confuse the
2366e4b17023SJohn Marino      find_many_sub_basic_blocks code, so we need to get rid of these.  */
2367e4b17023SJohn Marino   last = NEXT_INSN (last);
2368e4b17023SJohn Marino   gcc_assert (BARRIER_P (last));
2369e4b17023SJohn Marino 
2370e4b17023SJohn Marino   *can_fallthru = false;
2371e4b17023SJohn Marino   while (NEXT_INSN (last))
2372e4b17023SJohn Marino     {
2373e4b17023SJohn Marino       /* For instance an sqrt builtin expander expands if with
2374e4b17023SJohn Marino 	 sibcall in the then and label for `else`.  */
2375e4b17023SJohn Marino       if (LABEL_P (NEXT_INSN (last)))
2376e4b17023SJohn Marino 	{
2377e4b17023SJohn Marino 	  *can_fallthru = true;
2378e4b17023SJohn Marino 	  break;
2379e4b17023SJohn Marino 	}
2380e4b17023SJohn Marino       delete_insn (NEXT_INSN (last));
2381e4b17023SJohn Marino     }
2382e4b17023SJohn Marino 
2383e4b17023SJohn Marino   e = make_edge (bb, EXIT_BLOCK_PTR, EDGE_ABNORMAL | EDGE_SIBCALL);
2384e4b17023SJohn Marino   e->probability += probability;
2385e4b17023SJohn Marino   e->count += count;
2386e4b17023SJohn Marino   BB_END (bb) = last;
2387e4b17023SJohn Marino   update_bb_for_insn (bb);
2388e4b17023SJohn Marino 
2389e4b17023SJohn Marino   if (NEXT_INSN (last))
2390e4b17023SJohn Marino     {
2391e4b17023SJohn Marino       bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb);
2392e4b17023SJohn Marino 
2393e4b17023SJohn Marino       last = BB_END (bb);
2394e4b17023SJohn Marino       if (BARRIER_P (last))
2395e4b17023SJohn Marino 	BB_END (bb) = PREV_INSN (last);
2396e4b17023SJohn Marino     }
2397e4b17023SJohn Marino 
2398e4b17023SJohn Marino   maybe_dump_rtl_for_gimple_stmt (stmt, last2);
2399e4b17023SJohn Marino 
2400e4b17023SJohn Marino   return bb;
2401e4b17023SJohn Marino }
2402e4b17023SJohn Marino 
2403e4b17023SJohn Marino /* Return the difference between the floor and the truncated result of
2404e4b17023SJohn Marino    a signed division by OP1 with remainder MOD.  */
2405e4b17023SJohn Marino static rtx
floor_sdiv_adjust(enum machine_mode mode,rtx mod,rtx op1)2406e4b17023SJohn Marino floor_sdiv_adjust (enum machine_mode mode, rtx mod, rtx op1)
2407e4b17023SJohn Marino {
2408e4b17023SJohn Marino   /* (mod != 0 ? (op1 / mod < 0 ? -1 : 0) : 0) */
2409e4b17023SJohn Marino   return gen_rtx_IF_THEN_ELSE
2410e4b17023SJohn Marino     (mode, gen_rtx_NE (BImode, mod, const0_rtx),
2411e4b17023SJohn Marino      gen_rtx_IF_THEN_ELSE
2412e4b17023SJohn Marino      (mode, gen_rtx_LT (BImode,
2413e4b17023SJohn Marino 			gen_rtx_DIV (mode, op1, mod),
2414e4b17023SJohn Marino 			const0_rtx),
2415e4b17023SJohn Marino       constm1_rtx, const0_rtx),
2416e4b17023SJohn Marino      const0_rtx);
2417e4b17023SJohn Marino }
2418e4b17023SJohn Marino 
2419e4b17023SJohn Marino /* Return the difference between the ceil and the truncated result of
2420e4b17023SJohn Marino    a signed division by OP1 with remainder MOD.  */
2421e4b17023SJohn Marino static rtx
ceil_sdiv_adjust(enum machine_mode mode,rtx mod,rtx op1)2422e4b17023SJohn Marino ceil_sdiv_adjust (enum machine_mode mode, rtx mod, rtx op1)
2423e4b17023SJohn Marino {
2424e4b17023SJohn Marino   /* (mod != 0 ? (op1 / mod > 0 ? 1 : 0) : 0) */
2425e4b17023SJohn Marino   return gen_rtx_IF_THEN_ELSE
2426e4b17023SJohn Marino     (mode, gen_rtx_NE (BImode, mod, const0_rtx),
2427e4b17023SJohn Marino      gen_rtx_IF_THEN_ELSE
2428e4b17023SJohn Marino      (mode, gen_rtx_GT (BImode,
2429e4b17023SJohn Marino 			gen_rtx_DIV (mode, op1, mod),
2430e4b17023SJohn Marino 			const0_rtx),
2431e4b17023SJohn Marino       const1_rtx, const0_rtx),
2432e4b17023SJohn Marino      const0_rtx);
2433e4b17023SJohn Marino }
2434e4b17023SJohn Marino 
2435e4b17023SJohn Marino /* Return the difference between the ceil and the truncated result of
2436e4b17023SJohn Marino    an unsigned division by OP1 with remainder MOD.  */
2437e4b17023SJohn Marino static rtx
ceil_udiv_adjust(enum machine_mode mode,rtx mod,rtx op1 ATTRIBUTE_UNUSED)2438e4b17023SJohn Marino ceil_udiv_adjust (enum machine_mode mode, rtx mod, rtx op1 ATTRIBUTE_UNUSED)
2439e4b17023SJohn Marino {
2440e4b17023SJohn Marino   /* (mod != 0 ? 1 : 0) */
2441e4b17023SJohn Marino   return gen_rtx_IF_THEN_ELSE
2442e4b17023SJohn Marino     (mode, gen_rtx_NE (BImode, mod, const0_rtx),
2443e4b17023SJohn Marino      const1_rtx, const0_rtx);
2444e4b17023SJohn Marino }
2445e4b17023SJohn Marino 
2446e4b17023SJohn Marino /* Return the difference between the rounded and the truncated result
2447e4b17023SJohn Marino    of a signed division by OP1 with remainder MOD.  Halfway cases are
2448e4b17023SJohn Marino    rounded away from zero, rather than to the nearest even number.  */
2449e4b17023SJohn Marino static rtx
round_sdiv_adjust(enum machine_mode mode,rtx mod,rtx op1)2450e4b17023SJohn Marino round_sdiv_adjust (enum machine_mode mode, rtx mod, rtx op1)
2451e4b17023SJohn Marino {
2452e4b17023SJohn Marino   /* (abs (mod) >= abs (op1) - abs (mod)
2453e4b17023SJohn Marino       ? (op1 / mod > 0 ? 1 : -1)
2454e4b17023SJohn Marino       : 0) */
2455e4b17023SJohn Marino   return gen_rtx_IF_THEN_ELSE
2456e4b17023SJohn Marino     (mode, gen_rtx_GE (BImode, gen_rtx_ABS (mode, mod),
2457e4b17023SJohn Marino 		       gen_rtx_MINUS (mode,
2458e4b17023SJohn Marino 				      gen_rtx_ABS (mode, op1),
2459e4b17023SJohn Marino 				      gen_rtx_ABS (mode, mod))),
2460e4b17023SJohn Marino      gen_rtx_IF_THEN_ELSE
2461e4b17023SJohn Marino      (mode, gen_rtx_GT (BImode,
2462e4b17023SJohn Marino 			gen_rtx_DIV (mode, op1, mod),
2463e4b17023SJohn Marino 			const0_rtx),
2464e4b17023SJohn Marino       const1_rtx, constm1_rtx),
2465e4b17023SJohn Marino      const0_rtx);
2466e4b17023SJohn Marino }
2467e4b17023SJohn Marino 
2468e4b17023SJohn Marino /* Return the difference between the rounded and the truncated result
2469e4b17023SJohn Marino    of a unsigned division by OP1 with remainder MOD.  Halfway cases
2470e4b17023SJohn Marino    are rounded away from zero, rather than to the nearest even
2471e4b17023SJohn Marino    number.  */
2472e4b17023SJohn Marino static rtx
round_udiv_adjust(enum machine_mode mode,rtx mod,rtx op1)2473e4b17023SJohn Marino round_udiv_adjust (enum machine_mode mode, rtx mod, rtx op1)
2474e4b17023SJohn Marino {
2475e4b17023SJohn Marino   /* (mod >= op1 - mod ? 1 : 0) */
2476e4b17023SJohn Marino   return gen_rtx_IF_THEN_ELSE
2477e4b17023SJohn Marino     (mode, gen_rtx_GE (BImode, mod,
2478e4b17023SJohn Marino 		       gen_rtx_MINUS (mode, op1, mod)),
2479e4b17023SJohn Marino      const1_rtx, const0_rtx);
2480e4b17023SJohn Marino }
2481e4b17023SJohn Marino 
2482e4b17023SJohn Marino /* Convert X to MODE, that must be Pmode or ptr_mode, without emitting
2483e4b17023SJohn Marino    any rtl.  */
2484e4b17023SJohn Marino 
2485e4b17023SJohn Marino static rtx
convert_debug_memory_address(enum machine_mode mode,rtx x,addr_space_t as)2486e4b17023SJohn Marino convert_debug_memory_address (enum machine_mode mode, rtx x,
2487e4b17023SJohn Marino 			      addr_space_t as)
2488e4b17023SJohn Marino {
2489e4b17023SJohn Marino   enum machine_mode xmode = GET_MODE (x);
2490e4b17023SJohn Marino 
2491e4b17023SJohn Marino #ifndef POINTERS_EXTEND_UNSIGNED
2492e4b17023SJohn Marino   gcc_assert (mode == Pmode
2493e4b17023SJohn Marino 	      || mode == targetm.addr_space.address_mode (as));
2494e4b17023SJohn Marino   gcc_assert (xmode == mode || xmode == VOIDmode);
2495e4b17023SJohn Marino #else
2496e4b17023SJohn Marino   rtx temp;
2497e4b17023SJohn Marino 
2498e4b17023SJohn Marino   gcc_assert (targetm.addr_space.valid_pointer_mode (mode, as));
2499e4b17023SJohn Marino 
2500e4b17023SJohn Marino   if (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode)
2501e4b17023SJohn Marino     return x;
2502e4b17023SJohn Marino 
2503e4b17023SJohn Marino   if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (xmode))
2504e4b17023SJohn Marino     x = simplify_gen_subreg (mode, x, xmode,
2505e4b17023SJohn Marino 			     subreg_lowpart_offset
2506e4b17023SJohn Marino 			     (mode, xmode));
2507e4b17023SJohn Marino   else if (POINTERS_EXTEND_UNSIGNED > 0)
2508e4b17023SJohn Marino     x = gen_rtx_ZERO_EXTEND (mode, x);
2509e4b17023SJohn Marino   else if (!POINTERS_EXTEND_UNSIGNED)
2510e4b17023SJohn Marino     x = gen_rtx_SIGN_EXTEND (mode, x);
2511e4b17023SJohn Marino   else
2512e4b17023SJohn Marino     {
2513e4b17023SJohn Marino       switch (GET_CODE (x))
2514e4b17023SJohn Marino 	{
2515e4b17023SJohn Marino 	case SUBREG:
2516e4b17023SJohn Marino 	  if ((SUBREG_PROMOTED_VAR_P (x)
2517e4b17023SJohn Marino 	       || (REG_P (SUBREG_REG (x)) && REG_POINTER (SUBREG_REG (x)))
2518e4b17023SJohn Marino 	       || (GET_CODE (SUBREG_REG (x)) == PLUS
2519e4b17023SJohn Marino 		   && REG_P (XEXP (SUBREG_REG (x), 0))
2520e4b17023SJohn Marino 		   && REG_POINTER (XEXP (SUBREG_REG (x), 0))
2521e4b17023SJohn Marino 		   && CONST_INT_P (XEXP (SUBREG_REG (x), 1))))
2522e4b17023SJohn Marino 	      && GET_MODE (SUBREG_REG (x)) == mode)
2523e4b17023SJohn Marino 	    return SUBREG_REG (x);
2524e4b17023SJohn Marino 	  break;
2525e4b17023SJohn Marino 	case LABEL_REF:
2526e4b17023SJohn Marino 	  temp = gen_rtx_LABEL_REF (mode, XEXP (x, 0));
2527e4b17023SJohn Marino 	  LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
2528e4b17023SJohn Marino 	  return temp;
2529e4b17023SJohn Marino 	case SYMBOL_REF:
2530e4b17023SJohn Marino 	  temp = shallow_copy_rtx (x);
2531e4b17023SJohn Marino 	  PUT_MODE (temp, mode);
2532e4b17023SJohn Marino 	  return temp;
2533e4b17023SJohn Marino 	case CONST:
2534e4b17023SJohn Marino 	  temp = convert_debug_memory_address (mode, XEXP (x, 0), as);
2535e4b17023SJohn Marino 	  if (temp)
2536e4b17023SJohn Marino 	    temp = gen_rtx_CONST (mode, temp);
2537e4b17023SJohn Marino 	  return temp;
2538e4b17023SJohn Marino 	case PLUS:
2539e4b17023SJohn Marino 	case MINUS:
2540e4b17023SJohn Marino 	  if (CONST_INT_P (XEXP (x, 1)))
2541e4b17023SJohn Marino 	    {
2542e4b17023SJohn Marino 	      temp = convert_debug_memory_address (mode, XEXP (x, 0), as);
2543e4b17023SJohn Marino 	      if (temp)
2544e4b17023SJohn Marino 		return gen_rtx_fmt_ee (GET_CODE (x), mode, temp, XEXP (x, 1));
2545e4b17023SJohn Marino 	    }
2546e4b17023SJohn Marino 	  break;
2547e4b17023SJohn Marino 	default:
2548e4b17023SJohn Marino 	  break;
2549e4b17023SJohn Marino 	}
2550e4b17023SJohn Marino       /* Don't know how to express ptr_extend as operation in debug info.  */
2551e4b17023SJohn Marino       return NULL;
2552e4b17023SJohn Marino     }
2553e4b17023SJohn Marino #endif /* POINTERS_EXTEND_UNSIGNED */
2554e4b17023SJohn Marino 
2555e4b17023SJohn Marino   return x;
2556e4b17023SJohn Marino }
2557e4b17023SJohn Marino 
2558e4b17023SJohn Marino /* Return an RTX equivalent to the value of the parameter DECL.  */
2559e4b17023SJohn Marino 
2560e4b17023SJohn Marino static rtx
expand_debug_parm_decl(tree decl)2561e4b17023SJohn Marino expand_debug_parm_decl (tree decl)
2562e4b17023SJohn Marino {
2563e4b17023SJohn Marino   rtx incoming = DECL_INCOMING_RTL (decl);
2564e4b17023SJohn Marino 
2565e4b17023SJohn Marino   if (incoming
2566e4b17023SJohn Marino       && GET_MODE (incoming) != BLKmode
2567e4b17023SJohn Marino       && ((REG_P (incoming) && HARD_REGISTER_P (incoming))
2568e4b17023SJohn Marino 	  || (MEM_P (incoming)
2569e4b17023SJohn Marino 	      && REG_P (XEXP (incoming, 0))
2570e4b17023SJohn Marino 	      && HARD_REGISTER_P (XEXP (incoming, 0)))))
2571e4b17023SJohn Marino     {
2572e4b17023SJohn Marino       rtx rtl = gen_rtx_ENTRY_VALUE (GET_MODE (incoming));
2573e4b17023SJohn Marino 
2574e4b17023SJohn Marino #ifdef HAVE_window_save
2575e4b17023SJohn Marino       /* DECL_INCOMING_RTL uses the INCOMING_REGNO of parameter registers.
2576e4b17023SJohn Marino 	 If the target machine has an explicit window save instruction, the
2577e4b17023SJohn Marino 	 actual entry value is the corresponding OUTGOING_REGNO instead.  */
2578e4b17023SJohn Marino       if (REG_P (incoming)
2579e4b17023SJohn Marino 	  && OUTGOING_REGNO (REGNO (incoming)) != REGNO (incoming))
2580e4b17023SJohn Marino 	incoming
2581e4b17023SJohn Marino 	  = gen_rtx_REG_offset (incoming, GET_MODE (incoming),
2582e4b17023SJohn Marino 				OUTGOING_REGNO (REGNO (incoming)), 0);
2583e4b17023SJohn Marino       else if (MEM_P (incoming))
2584e4b17023SJohn Marino 	{
2585e4b17023SJohn Marino 	  rtx reg = XEXP (incoming, 0);
2586e4b17023SJohn Marino 	  if (OUTGOING_REGNO (REGNO (reg)) != REGNO (reg))
2587e4b17023SJohn Marino 	    {
2588e4b17023SJohn Marino 	      reg = gen_raw_REG (GET_MODE (reg), OUTGOING_REGNO (REGNO (reg)));
2589e4b17023SJohn Marino 	      incoming = replace_equiv_address_nv (incoming, reg);
2590e4b17023SJohn Marino 	    }
25915ce9237cSJohn Marino 	  else
25925ce9237cSJohn Marino 	    incoming = copy_rtx (incoming);
2593e4b17023SJohn Marino 	}
2594e4b17023SJohn Marino #endif
2595e4b17023SJohn Marino 
2596e4b17023SJohn Marino       ENTRY_VALUE_EXP (rtl) = incoming;
2597e4b17023SJohn Marino       return rtl;
2598e4b17023SJohn Marino     }
2599e4b17023SJohn Marino 
2600e4b17023SJohn Marino   if (incoming
2601e4b17023SJohn Marino       && GET_MODE (incoming) != BLKmode
2602e4b17023SJohn Marino       && !TREE_ADDRESSABLE (decl)
2603e4b17023SJohn Marino       && MEM_P (incoming)
2604e4b17023SJohn Marino       && (XEXP (incoming, 0) == virtual_incoming_args_rtx
2605e4b17023SJohn Marino 	  || (GET_CODE (XEXP (incoming, 0)) == PLUS
2606e4b17023SJohn Marino 	      && XEXP (XEXP (incoming, 0), 0) == virtual_incoming_args_rtx
2607e4b17023SJohn Marino 	      && CONST_INT_P (XEXP (XEXP (incoming, 0), 1)))))
26085ce9237cSJohn Marino     return copy_rtx (incoming);
2609e4b17023SJohn Marino 
2610e4b17023SJohn Marino   return NULL_RTX;
2611e4b17023SJohn Marino }
2612e4b17023SJohn Marino 
2613e4b17023SJohn Marino /* Return an RTX equivalent to the value of the tree expression EXP.  */
2614e4b17023SJohn Marino 
2615e4b17023SJohn Marino static rtx
expand_debug_expr(tree exp)2616e4b17023SJohn Marino expand_debug_expr (tree exp)
2617e4b17023SJohn Marino {
2618e4b17023SJohn Marino   rtx op0 = NULL_RTX, op1 = NULL_RTX, op2 = NULL_RTX;
2619e4b17023SJohn Marino   enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2620e4b17023SJohn Marino   enum machine_mode inner_mode = VOIDmode;
2621e4b17023SJohn Marino   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
2622e4b17023SJohn Marino   addr_space_t as;
2623e4b17023SJohn Marino 
2624e4b17023SJohn Marino   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
2625e4b17023SJohn Marino     {
2626e4b17023SJohn Marino     case tcc_expression:
2627e4b17023SJohn Marino       switch (TREE_CODE (exp))
2628e4b17023SJohn Marino 	{
2629e4b17023SJohn Marino 	case COND_EXPR:
2630e4b17023SJohn Marino 	case DOT_PROD_EXPR:
2631e4b17023SJohn Marino 	case WIDEN_MULT_PLUS_EXPR:
2632e4b17023SJohn Marino 	case WIDEN_MULT_MINUS_EXPR:
2633e4b17023SJohn Marino 	case FMA_EXPR:
2634e4b17023SJohn Marino 	  goto ternary;
2635e4b17023SJohn Marino 
2636e4b17023SJohn Marino 	case TRUTH_ANDIF_EXPR:
2637e4b17023SJohn Marino 	case TRUTH_ORIF_EXPR:
2638e4b17023SJohn Marino 	case TRUTH_AND_EXPR:
2639e4b17023SJohn Marino 	case TRUTH_OR_EXPR:
2640e4b17023SJohn Marino 	case TRUTH_XOR_EXPR:
2641e4b17023SJohn Marino 	  goto binary;
2642e4b17023SJohn Marino 
2643e4b17023SJohn Marino 	case TRUTH_NOT_EXPR:
2644e4b17023SJohn Marino 	  goto unary;
2645e4b17023SJohn Marino 
2646e4b17023SJohn Marino 	default:
2647e4b17023SJohn Marino 	  break;
2648e4b17023SJohn Marino 	}
2649e4b17023SJohn Marino       break;
2650e4b17023SJohn Marino 
2651e4b17023SJohn Marino     ternary:
2652e4b17023SJohn Marino       op2 = expand_debug_expr (TREE_OPERAND (exp, 2));
2653e4b17023SJohn Marino       if (!op2)
2654e4b17023SJohn Marino 	return NULL_RTX;
2655e4b17023SJohn Marino       /* Fall through.  */
2656e4b17023SJohn Marino 
2657e4b17023SJohn Marino     binary:
2658e4b17023SJohn Marino     case tcc_binary:
2659e4b17023SJohn Marino     case tcc_comparison:
2660e4b17023SJohn Marino       op1 = expand_debug_expr (TREE_OPERAND (exp, 1));
2661e4b17023SJohn Marino       if (!op1)
2662e4b17023SJohn Marino 	return NULL_RTX;
2663e4b17023SJohn Marino       /* Fall through.  */
2664e4b17023SJohn Marino 
2665e4b17023SJohn Marino     unary:
2666e4b17023SJohn Marino     case tcc_unary:
2667e4b17023SJohn Marino       inner_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
2668e4b17023SJohn Marino       op0 = expand_debug_expr (TREE_OPERAND (exp, 0));
2669e4b17023SJohn Marino       if (!op0)
2670e4b17023SJohn Marino 	return NULL_RTX;
2671e4b17023SJohn Marino       break;
2672e4b17023SJohn Marino 
2673e4b17023SJohn Marino     case tcc_type:
2674e4b17023SJohn Marino     case tcc_statement:
2675e4b17023SJohn Marino       gcc_unreachable ();
2676e4b17023SJohn Marino 
2677e4b17023SJohn Marino     case tcc_constant:
2678e4b17023SJohn Marino     case tcc_exceptional:
2679e4b17023SJohn Marino     case tcc_declaration:
2680e4b17023SJohn Marino     case tcc_reference:
2681e4b17023SJohn Marino     case tcc_vl_exp:
2682e4b17023SJohn Marino       break;
2683e4b17023SJohn Marino     }
2684e4b17023SJohn Marino 
2685e4b17023SJohn Marino   switch (TREE_CODE (exp))
2686e4b17023SJohn Marino     {
2687e4b17023SJohn Marino     case STRING_CST:
2688e4b17023SJohn Marino       if (!lookup_constant_def (exp))
2689e4b17023SJohn Marino 	{
2690e4b17023SJohn Marino 	  if (strlen (TREE_STRING_POINTER (exp)) + 1
2691e4b17023SJohn Marino 	      != (size_t) TREE_STRING_LENGTH (exp))
2692e4b17023SJohn Marino 	    return NULL_RTX;
2693e4b17023SJohn Marino 	  op0 = gen_rtx_CONST_STRING (Pmode, TREE_STRING_POINTER (exp));
2694e4b17023SJohn Marino 	  op0 = gen_rtx_MEM (BLKmode, op0);
2695e4b17023SJohn Marino 	  set_mem_attributes (op0, exp, 0);
2696e4b17023SJohn Marino 	  return op0;
2697e4b17023SJohn Marino 	}
2698e4b17023SJohn Marino       /* Fall through...  */
2699e4b17023SJohn Marino 
2700e4b17023SJohn Marino     case INTEGER_CST:
2701e4b17023SJohn Marino     case REAL_CST:
2702e4b17023SJohn Marino     case FIXED_CST:
2703e4b17023SJohn Marino       op0 = expand_expr (exp, NULL_RTX, mode, EXPAND_INITIALIZER);
2704e4b17023SJohn Marino       return op0;
2705e4b17023SJohn Marino 
2706e4b17023SJohn Marino     case COMPLEX_CST:
2707e4b17023SJohn Marino       gcc_assert (COMPLEX_MODE_P (mode));
2708e4b17023SJohn Marino       op0 = expand_debug_expr (TREE_REALPART (exp));
2709e4b17023SJohn Marino       op1 = expand_debug_expr (TREE_IMAGPART (exp));
2710e4b17023SJohn Marino       return gen_rtx_CONCAT (mode, op0, op1);
2711e4b17023SJohn Marino 
2712e4b17023SJohn Marino     case DEBUG_EXPR_DECL:
2713e4b17023SJohn Marino       op0 = DECL_RTL_IF_SET (exp);
2714e4b17023SJohn Marino 
2715e4b17023SJohn Marino       if (op0)
2716e4b17023SJohn Marino 	return op0;
2717e4b17023SJohn Marino 
2718e4b17023SJohn Marino       op0 = gen_rtx_DEBUG_EXPR (mode);
2719e4b17023SJohn Marino       DEBUG_EXPR_TREE_DECL (op0) = exp;
2720e4b17023SJohn Marino       SET_DECL_RTL (exp, op0);
2721e4b17023SJohn Marino 
2722e4b17023SJohn Marino       return op0;
2723e4b17023SJohn Marino 
2724e4b17023SJohn Marino     case VAR_DECL:
2725e4b17023SJohn Marino     case PARM_DECL:
2726e4b17023SJohn Marino     case FUNCTION_DECL:
2727e4b17023SJohn Marino     case LABEL_DECL:
2728e4b17023SJohn Marino     case CONST_DECL:
2729e4b17023SJohn Marino     case RESULT_DECL:
2730e4b17023SJohn Marino       op0 = DECL_RTL_IF_SET (exp);
2731e4b17023SJohn Marino 
2732e4b17023SJohn Marino       /* This decl was probably optimized away.  */
2733e4b17023SJohn Marino       if (!op0)
2734e4b17023SJohn Marino 	{
2735e4b17023SJohn Marino 	  if (TREE_CODE (exp) != VAR_DECL
2736e4b17023SJohn Marino 	      || DECL_EXTERNAL (exp)
2737e4b17023SJohn Marino 	      || !TREE_STATIC (exp)
2738e4b17023SJohn Marino 	      || !DECL_NAME (exp)
2739e4b17023SJohn Marino 	      || DECL_HARD_REGISTER (exp)
2740e4b17023SJohn Marino 	      || DECL_IN_CONSTANT_POOL (exp)
2741e4b17023SJohn Marino 	      || mode == VOIDmode)
2742e4b17023SJohn Marino 	    return NULL;
2743e4b17023SJohn Marino 
2744e4b17023SJohn Marino 	  op0 = make_decl_rtl_for_debug (exp);
2745e4b17023SJohn Marino 	  if (!MEM_P (op0)
2746e4b17023SJohn Marino 	      || GET_CODE (XEXP (op0, 0)) != SYMBOL_REF
2747e4b17023SJohn Marino 	      || SYMBOL_REF_DECL (XEXP (op0, 0)) != exp)
2748e4b17023SJohn Marino 	    return NULL;
2749e4b17023SJohn Marino 	}
2750e4b17023SJohn Marino       else
2751e4b17023SJohn Marino 	op0 = copy_rtx (op0);
2752e4b17023SJohn Marino 
2753e4b17023SJohn Marino       if (GET_MODE (op0) == BLKmode
2754e4b17023SJohn Marino 	  /* If op0 is not BLKmode, but BLKmode is, adjust_mode
2755e4b17023SJohn Marino 	     below would ICE.  While it is likely a FE bug,
2756e4b17023SJohn Marino 	     try to be robust here.  See PR43166.  */
2757e4b17023SJohn Marino 	  || mode == BLKmode
2758e4b17023SJohn Marino 	  || (mode == VOIDmode && GET_MODE (op0) != VOIDmode))
2759e4b17023SJohn Marino 	{
2760e4b17023SJohn Marino 	  gcc_assert (MEM_P (op0));
2761e4b17023SJohn Marino 	  op0 = adjust_address_nv (op0, mode, 0);
2762e4b17023SJohn Marino 	  return op0;
2763e4b17023SJohn Marino 	}
2764e4b17023SJohn Marino 
2765e4b17023SJohn Marino       /* Fall through.  */
2766e4b17023SJohn Marino 
2767e4b17023SJohn Marino     adjust_mode:
2768e4b17023SJohn Marino     case PAREN_EXPR:
2769e4b17023SJohn Marino     case NOP_EXPR:
2770e4b17023SJohn Marino     case CONVERT_EXPR:
2771e4b17023SJohn Marino       {
2772e4b17023SJohn Marino 	inner_mode = GET_MODE (op0);
2773e4b17023SJohn Marino 
2774e4b17023SJohn Marino 	if (mode == inner_mode)
2775e4b17023SJohn Marino 	  return op0;
2776e4b17023SJohn Marino 
2777e4b17023SJohn Marino 	if (inner_mode == VOIDmode)
2778e4b17023SJohn Marino 	  {
2779e4b17023SJohn Marino 	    if (TREE_CODE (exp) == SSA_NAME)
2780e4b17023SJohn Marino 	      inner_mode = TYPE_MODE (TREE_TYPE (exp));
2781e4b17023SJohn Marino 	    else
2782e4b17023SJohn Marino 	      inner_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
2783e4b17023SJohn Marino 	    if (mode == inner_mode)
2784e4b17023SJohn Marino 	      return op0;
2785e4b17023SJohn Marino 	  }
2786e4b17023SJohn Marino 
2787e4b17023SJohn Marino 	if (FLOAT_MODE_P (mode) && FLOAT_MODE_P (inner_mode))
2788e4b17023SJohn Marino 	  {
2789e4b17023SJohn Marino 	    if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (inner_mode))
2790e4b17023SJohn Marino 	      op0 = simplify_gen_subreg (mode, op0, inner_mode, 0);
2791e4b17023SJohn Marino 	    else if (GET_MODE_BITSIZE (mode) < GET_MODE_BITSIZE (inner_mode))
2792e4b17023SJohn Marino 	      op0 = simplify_gen_unary (FLOAT_TRUNCATE, mode, op0, inner_mode);
2793e4b17023SJohn Marino 	    else
2794e4b17023SJohn Marino 	      op0 = simplify_gen_unary (FLOAT_EXTEND, mode, op0, inner_mode);
2795e4b17023SJohn Marino 	  }
2796e4b17023SJohn Marino 	else if (FLOAT_MODE_P (mode))
2797e4b17023SJohn Marino 	  {
2798e4b17023SJohn Marino 	    gcc_assert (TREE_CODE (exp) != SSA_NAME);
2799e4b17023SJohn Marino 	    if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))))
2800e4b17023SJohn Marino 	      op0 = simplify_gen_unary (UNSIGNED_FLOAT, mode, op0, inner_mode);
2801e4b17023SJohn Marino 	    else
2802e4b17023SJohn Marino 	      op0 = simplify_gen_unary (FLOAT, mode, op0, inner_mode);
2803e4b17023SJohn Marino 	  }
2804e4b17023SJohn Marino 	else if (FLOAT_MODE_P (inner_mode))
2805e4b17023SJohn Marino 	  {
2806e4b17023SJohn Marino 	    if (unsignedp)
2807e4b17023SJohn Marino 	      op0 = simplify_gen_unary (UNSIGNED_FIX, mode, op0, inner_mode);
2808e4b17023SJohn Marino 	    else
2809e4b17023SJohn Marino 	      op0 = simplify_gen_unary (FIX, mode, op0, inner_mode);
2810e4b17023SJohn Marino 	  }
2811e4b17023SJohn Marino 	else if (CONSTANT_P (op0)
2812e4b17023SJohn Marino 		 || GET_MODE_PRECISION (mode) <= GET_MODE_PRECISION (inner_mode))
2813e4b17023SJohn Marino 	  op0 = simplify_gen_subreg (mode, op0, inner_mode,
2814e4b17023SJohn Marino 				     subreg_lowpart_offset (mode,
2815e4b17023SJohn Marino 							    inner_mode));
2816e4b17023SJohn Marino 	else if (TREE_CODE_CLASS (TREE_CODE (exp)) == tcc_unary
2817e4b17023SJohn Marino 		 ? TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))
2818e4b17023SJohn Marino 		 : unsignedp)
2819e4b17023SJohn Marino 	  op0 = simplify_gen_unary (ZERO_EXTEND, mode, op0, inner_mode);
2820e4b17023SJohn Marino 	else
2821e4b17023SJohn Marino 	  op0 = simplify_gen_unary (SIGN_EXTEND, mode, op0, inner_mode);
2822e4b17023SJohn Marino 
2823e4b17023SJohn Marino 	return op0;
2824e4b17023SJohn Marino       }
2825e4b17023SJohn Marino 
2826e4b17023SJohn Marino     case MEM_REF:
2827e4b17023SJohn Marino       if (!is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
2828e4b17023SJohn Marino 	{
2829e4b17023SJohn Marino 	  tree newexp = fold_binary (MEM_REF, TREE_TYPE (exp),
2830e4b17023SJohn Marino 				     TREE_OPERAND (exp, 0),
2831e4b17023SJohn Marino 				     TREE_OPERAND (exp, 1));
2832e4b17023SJohn Marino 	  if (newexp)
2833e4b17023SJohn Marino 	    return expand_debug_expr (newexp);
2834e4b17023SJohn Marino 	}
2835e4b17023SJohn Marino       /* FALLTHROUGH */
2836e4b17023SJohn Marino     case INDIRECT_REF:
2837e4b17023SJohn Marino       op0 = expand_debug_expr (TREE_OPERAND (exp, 0));
2838e4b17023SJohn Marino       if (!op0)
2839e4b17023SJohn Marino 	return NULL;
2840e4b17023SJohn Marino 
2841e4b17023SJohn Marino       if (TREE_CODE (exp) == MEM_REF)
2842e4b17023SJohn Marino 	{
2843e4b17023SJohn Marino 	  if (GET_CODE (op0) == DEBUG_IMPLICIT_PTR
2844e4b17023SJohn Marino 	      || (GET_CODE (op0) == PLUS
2845e4b17023SJohn Marino 		  && GET_CODE (XEXP (op0, 0)) == DEBUG_IMPLICIT_PTR))
2846e4b17023SJohn Marino 	    /* (mem (debug_implicit_ptr)) might confuse aliasing.
2847e4b17023SJohn Marino 	       Instead just use get_inner_reference.  */
2848e4b17023SJohn Marino 	    goto component_ref;
2849e4b17023SJohn Marino 
2850e4b17023SJohn Marino 	  op1 = expand_debug_expr (TREE_OPERAND (exp, 1));
2851e4b17023SJohn Marino 	  if (!op1 || !CONST_INT_P (op1))
2852e4b17023SJohn Marino 	    return NULL;
2853e4b17023SJohn Marino 
2854e4b17023SJohn Marino 	  op0 = plus_constant (op0, INTVAL (op1));
2855e4b17023SJohn Marino 	}
2856e4b17023SJohn Marino 
2857e4b17023SJohn Marino       if (POINTER_TYPE_P (TREE_TYPE (exp)))
2858e4b17023SJohn Marino 	as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
2859e4b17023SJohn Marino       else
2860e4b17023SJohn Marino 	as = ADDR_SPACE_GENERIC;
2861e4b17023SJohn Marino 
2862e4b17023SJohn Marino       op0 = convert_debug_memory_address (targetm.addr_space.address_mode (as),
2863e4b17023SJohn Marino 					  op0, as);
2864e4b17023SJohn Marino       if (op0 == NULL_RTX)
2865e4b17023SJohn Marino 	return NULL;
2866e4b17023SJohn Marino 
2867e4b17023SJohn Marino       op0 = gen_rtx_MEM (mode, op0);
2868e4b17023SJohn Marino       set_mem_attributes (op0, exp, 0);
2869e4b17023SJohn Marino       if (TREE_CODE (exp) == MEM_REF
2870e4b17023SJohn Marino 	  && !is_gimple_mem_ref_addr (TREE_OPERAND (exp, 0)))
2871e4b17023SJohn Marino 	set_mem_expr (op0, NULL_TREE);
2872e4b17023SJohn Marino       set_mem_addr_space (op0, as);
2873e4b17023SJohn Marino 
2874e4b17023SJohn Marino       return op0;
2875e4b17023SJohn Marino 
2876e4b17023SJohn Marino     case TARGET_MEM_REF:
2877e4b17023SJohn Marino       if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR
2878e4b17023SJohn Marino 	  && !DECL_RTL_SET_P (TREE_OPERAND (TMR_BASE (exp), 0)))
2879e4b17023SJohn Marino 	return NULL;
2880e4b17023SJohn Marino 
2881e4b17023SJohn Marino       op0 = expand_debug_expr
2882e4b17023SJohn Marino 	    (tree_mem_ref_addr (build_pointer_type (TREE_TYPE (exp)), exp));
2883e4b17023SJohn Marino       if (!op0)
2884e4b17023SJohn Marino 	return NULL;
2885e4b17023SJohn Marino 
2886e4b17023SJohn Marino       if (POINTER_TYPE_P (TREE_TYPE (exp)))
2887e4b17023SJohn Marino 	as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
2888e4b17023SJohn Marino       else
2889e4b17023SJohn Marino 	as = ADDR_SPACE_GENERIC;
2890e4b17023SJohn Marino 
2891e4b17023SJohn Marino       op0 = convert_debug_memory_address (targetm.addr_space.address_mode (as),
2892e4b17023SJohn Marino 					  op0, as);
2893e4b17023SJohn Marino       if (op0 == NULL_RTX)
2894e4b17023SJohn Marino 	return NULL;
2895e4b17023SJohn Marino 
2896e4b17023SJohn Marino       op0 = gen_rtx_MEM (mode, op0);
2897e4b17023SJohn Marino 
2898e4b17023SJohn Marino       set_mem_attributes (op0, exp, 0);
2899e4b17023SJohn Marino       set_mem_addr_space (op0, as);
2900e4b17023SJohn Marino 
2901e4b17023SJohn Marino       return op0;
2902e4b17023SJohn Marino 
2903e4b17023SJohn Marino     component_ref:
2904e4b17023SJohn Marino     case ARRAY_REF:
2905e4b17023SJohn Marino     case ARRAY_RANGE_REF:
2906e4b17023SJohn Marino     case COMPONENT_REF:
2907e4b17023SJohn Marino     case BIT_FIELD_REF:
2908e4b17023SJohn Marino     case REALPART_EXPR:
2909e4b17023SJohn Marino     case IMAGPART_EXPR:
2910e4b17023SJohn Marino     case VIEW_CONVERT_EXPR:
2911e4b17023SJohn Marino       {
2912e4b17023SJohn Marino 	enum machine_mode mode1;
2913e4b17023SJohn Marino 	HOST_WIDE_INT bitsize, bitpos;
2914e4b17023SJohn Marino 	tree offset;
2915e4b17023SJohn Marino 	int volatilep = 0;
2916e4b17023SJohn Marino 	tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
2917e4b17023SJohn Marino 					&mode1, &unsignedp, &volatilep, false);
2918e4b17023SJohn Marino 	rtx orig_op0;
2919e4b17023SJohn Marino 
2920e4b17023SJohn Marino 	if (bitsize == 0)
2921e4b17023SJohn Marino 	  return NULL;
2922e4b17023SJohn Marino 
2923e4b17023SJohn Marino 	orig_op0 = op0 = expand_debug_expr (tem);
2924e4b17023SJohn Marino 
2925e4b17023SJohn Marino 	if (!op0)
2926e4b17023SJohn Marino 	  return NULL;
2927e4b17023SJohn Marino 
2928e4b17023SJohn Marino 	if (offset)
2929e4b17023SJohn Marino 	  {
2930e4b17023SJohn Marino 	    enum machine_mode addrmode, offmode;
2931e4b17023SJohn Marino 
2932e4b17023SJohn Marino 	    if (!MEM_P (op0))
2933e4b17023SJohn Marino 	      return NULL;
2934e4b17023SJohn Marino 
2935e4b17023SJohn Marino 	    op0 = XEXP (op0, 0);
2936e4b17023SJohn Marino 	    addrmode = GET_MODE (op0);
2937e4b17023SJohn Marino 	    if (addrmode == VOIDmode)
2938e4b17023SJohn Marino 	      addrmode = Pmode;
2939e4b17023SJohn Marino 
2940e4b17023SJohn Marino 	    op1 = expand_debug_expr (offset);
2941e4b17023SJohn Marino 	    if (!op1)
2942e4b17023SJohn Marino 	      return NULL;
2943e4b17023SJohn Marino 
2944e4b17023SJohn Marino 	    offmode = GET_MODE (op1);
2945e4b17023SJohn Marino 	    if (offmode == VOIDmode)
2946e4b17023SJohn Marino 	      offmode = TYPE_MODE (TREE_TYPE (offset));
2947e4b17023SJohn Marino 
2948e4b17023SJohn Marino 	    if (addrmode != offmode)
2949e4b17023SJohn Marino 	      op1 = simplify_gen_subreg (addrmode, op1, offmode,
2950e4b17023SJohn Marino 					 subreg_lowpart_offset (addrmode,
2951e4b17023SJohn Marino 								offmode));
2952e4b17023SJohn Marino 
2953e4b17023SJohn Marino 	    /* Don't use offset_address here, we don't need a
2954e4b17023SJohn Marino 	       recognizable address, and we don't want to generate
2955e4b17023SJohn Marino 	       code.  */
2956e4b17023SJohn Marino 	    op0 = gen_rtx_MEM (mode, simplify_gen_binary (PLUS, addrmode,
2957e4b17023SJohn Marino 							  op0, op1));
2958e4b17023SJohn Marino 	  }
2959e4b17023SJohn Marino 
2960e4b17023SJohn Marino 	if (MEM_P (op0))
2961e4b17023SJohn Marino 	  {
2962e4b17023SJohn Marino 	    if (mode1 == VOIDmode)
2963e4b17023SJohn Marino 	      /* Bitfield.  */
2964e4b17023SJohn Marino 	      mode1 = smallest_mode_for_size (bitsize, MODE_INT);
2965e4b17023SJohn Marino 	    if (bitpos >= BITS_PER_UNIT)
2966e4b17023SJohn Marino 	      {
2967e4b17023SJohn Marino 		op0 = adjust_address_nv (op0, mode1, bitpos / BITS_PER_UNIT);
2968e4b17023SJohn Marino 		bitpos %= BITS_PER_UNIT;
2969e4b17023SJohn Marino 	      }
2970e4b17023SJohn Marino 	    else if (bitpos < 0)
2971e4b17023SJohn Marino 	      {
2972e4b17023SJohn Marino 		HOST_WIDE_INT units
2973e4b17023SJohn Marino 		  = (-bitpos + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
2974e4b17023SJohn Marino 		op0 = adjust_address_nv (op0, mode1, units);
2975e4b17023SJohn Marino 		bitpos += units * BITS_PER_UNIT;
2976e4b17023SJohn Marino 	      }
2977e4b17023SJohn Marino 	    else if (bitpos == 0 && bitsize == GET_MODE_BITSIZE (mode))
2978e4b17023SJohn Marino 	      op0 = adjust_address_nv (op0, mode, 0);
2979e4b17023SJohn Marino 	    else if (GET_MODE (op0) != mode1)
2980e4b17023SJohn Marino 	      op0 = adjust_address_nv (op0, mode1, 0);
2981e4b17023SJohn Marino 	    else
2982e4b17023SJohn Marino 	      op0 = copy_rtx (op0);
2983e4b17023SJohn Marino 	    if (op0 == orig_op0)
2984e4b17023SJohn Marino 	      op0 = shallow_copy_rtx (op0);
2985e4b17023SJohn Marino 	    set_mem_attributes (op0, exp, 0);
2986e4b17023SJohn Marino 	  }
2987e4b17023SJohn Marino 
2988e4b17023SJohn Marino 	if (bitpos == 0 && mode == GET_MODE (op0))
2989e4b17023SJohn Marino 	  return op0;
2990e4b17023SJohn Marino 
2991e4b17023SJohn Marino         if (bitpos < 0)
2992e4b17023SJohn Marino           return NULL;
2993e4b17023SJohn Marino 
2994e4b17023SJohn Marino 	if (GET_MODE (op0) == BLKmode)
2995e4b17023SJohn Marino 	  return NULL;
2996e4b17023SJohn Marino 
2997e4b17023SJohn Marino 	if ((bitpos % BITS_PER_UNIT) == 0
2998e4b17023SJohn Marino 	    && bitsize == GET_MODE_BITSIZE (mode1))
2999e4b17023SJohn Marino 	  {
3000e4b17023SJohn Marino 	    enum machine_mode opmode = GET_MODE (op0);
3001e4b17023SJohn Marino 
3002e4b17023SJohn Marino 	    if (opmode == VOIDmode)
3003e4b17023SJohn Marino 	      opmode = TYPE_MODE (TREE_TYPE (tem));
3004e4b17023SJohn Marino 
3005e4b17023SJohn Marino 	    /* This condition may hold if we're expanding the address
3006e4b17023SJohn Marino 	       right past the end of an array that turned out not to
3007e4b17023SJohn Marino 	       be addressable (i.e., the address was only computed in
3008e4b17023SJohn Marino 	       debug stmts).  The gen_subreg below would rightfully
3009e4b17023SJohn Marino 	       crash, and the address doesn't really exist, so just
3010e4b17023SJohn Marino 	       drop it.  */
3011e4b17023SJohn Marino 	    if (bitpos >= GET_MODE_BITSIZE (opmode))
3012e4b17023SJohn Marino 	      return NULL;
3013e4b17023SJohn Marino 
3014e4b17023SJohn Marino 	    if ((bitpos % GET_MODE_BITSIZE (mode)) == 0)
3015e4b17023SJohn Marino 	      return simplify_gen_subreg (mode, op0, opmode,
3016e4b17023SJohn Marino 					  bitpos / BITS_PER_UNIT);
3017e4b17023SJohn Marino 	  }
3018e4b17023SJohn Marino 
3019e4b17023SJohn Marino 	return simplify_gen_ternary (SCALAR_INT_MODE_P (GET_MODE (op0))
3020e4b17023SJohn Marino 				     && TYPE_UNSIGNED (TREE_TYPE (exp))
3021e4b17023SJohn Marino 				     ? SIGN_EXTRACT
3022e4b17023SJohn Marino 				     : ZERO_EXTRACT, mode,
3023e4b17023SJohn Marino 				     GET_MODE (op0) != VOIDmode
3024e4b17023SJohn Marino 				     ? GET_MODE (op0)
3025e4b17023SJohn Marino 				     : TYPE_MODE (TREE_TYPE (tem)),
3026e4b17023SJohn Marino 				     op0, GEN_INT (bitsize), GEN_INT (bitpos));
3027e4b17023SJohn Marino       }
3028e4b17023SJohn Marino 
3029e4b17023SJohn Marino     case ABS_EXPR:
3030e4b17023SJohn Marino       return simplify_gen_unary (ABS, mode, op0, mode);
3031e4b17023SJohn Marino 
3032e4b17023SJohn Marino     case NEGATE_EXPR:
3033e4b17023SJohn Marino       return simplify_gen_unary (NEG, mode, op0, mode);
3034e4b17023SJohn Marino 
3035e4b17023SJohn Marino     case BIT_NOT_EXPR:
3036e4b17023SJohn Marino       return simplify_gen_unary (NOT, mode, op0, mode);
3037e4b17023SJohn Marino 
3038e4b17023SJohn Marino     case FLOAT_EXPR:
3039e4b17023SJohn Marino       return simplify_gen_unary (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp,
3040e4b17023SJohn Marino 									 0)))
3041e4b17023SJohn Marino 				 ? UNSIGNED_FLOAT : FLOAT, mode, op0,
3042e4b17023SJohn Marino 				 inner_mode);
3043e4b17023SJohn Marino 
3044e4b17023SJohn Marino     case FIX_TRUNC_EXPR:
3045e4b17023SJohn Marino       return simplify_gen_unary (unsignedp ? UNSIGNED_FIX : FIX, mode, op0,
3046e4b17023SJohn Marino 				 inner_mode);
3047e4b17023SJohn Marino 
3048e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
3049e4b17023SJohn Marino       /* For the rare target where pointers are not the same size as
3050e4b17023SJohn Marino 	 size_t, we need to check for mis-matched modes and correct
3051e4b17023SJohn Marino 	 the addend.  */
3052e4b17023SJohn Marino       if (op0 && op1
3053e4b17023SJohn Marino 	  && GET_MODE (op0) != VOIDmode && GET_MODE (op1) != VOIDmode
3054e4b17023SJohn Marino 	  && GET_MODE (op0) != GET_MODE (op1))
3055e4b17023SJohn Marino 	{
3056e4b17023SJohn Marino 	  if (GET_MODE_BITSIZE (GET_MODE (op0)) < GET_MODE_BITSIZE (GET_MODE (op1)))
3057e4b17023SJohn Marino 	    op1 = simplify_gen_unary (TRUNCATE, GET_MODE (op0), op1,
3058e4b17023SJohn Marino 				      GET_MODE (op1));
3059e4b17023SJohn Marino 	  else
3060e4b17023SJohn Marino 	    /* We always sign-extend, regardless of the signedness of
3061e4b17023SJohn Marino 	       the operand, because the operand is always unsigned
3062e4b17023SJohn Marino 	       here even if the original C expression is signed.  */
3063e4b17023SJohn Marino 	    op1 = simplify_gen_unary (SIGN_EXTEND, GET_MODE (op0), op1,
3064e4b17023SJohn Marino 				      GET_MODE (op1));
3065e4b17023SJohn Marino 	}
3066e4b17023SJohn Marino       /* Fall through.  */
3067e4b17023SJohn Marino     case PLUS_EXPR:
3068e4b17023SJohn Marino       return simplify_gen_binary (PLUS, mode, op0, op1);
3069e4b17023SJohn Marino 
3070e4b17023SJohn Marino     case MINUS_EXPR:
3071e4b17023SJohn Marino       return simplify_gen_binary (MINUS, mode, op0, op1);
3072e4b17023SJohn Marino 
3073e4b17023SJohn Marino     case MULT_EXPR:
3074e4b17023SJohn Marino       return simplify_gen_binary (MULT, mode, op0, op1);
3075e4b17023SJohn Marino 
3076e4b17023SJohn Marino     case RDIV_EXPR:
3077e4b17023SJohn Marino     case TRUNC_DIV_EXPR:
3078e4b17023SJohn Marino     case EXACT_DIV_EXPR:
3079e4b17023SJohn Marino       if (unsignedp)
3080e4b17023SJohn Marino 	return simplify_gen_binary (UDIV, mode, op0, op1);
3081e4b17023SJohn Marino       else
3082e4b17023SJohn Marino 	return simplify_gen_binary (DIV, mode, op0, op1);
3083e4b17023SJohn Marino 
3084e4b17023SJohn Marino     case TRUNC_MOD_EXPR:
3085e4b17023SJohn Marino       return simplify_gen_binary (unsignedp ? UMOD : MOD, mode, op0, op1);
3086e4b17023SJohn Marino 
3087e4b17023SJohn Marino     case FLOOR_DIV_EXPR:
3088e4b17023SJohn Marino       if (unsignedp)
3089e4b17023SJohn Marino 	return simplify_gen_binary (UDIV, mode, op0, op1);
3090e4b17023SJohn Marino       else
3091e4b17023SJohn Marino 	{
3092e4b17023SJohn Marino 	  rtx div = simplify_gen_binary (DIV, mode, op0, op1);
3093e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (MOD, mode, op0, op1);
3094e4b17023SJohn Marino 	  rtx adj = floor_sdiv_adjust (mode, mod, op1);
3095e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, div, adj);
3096e4b17023SJohn Marino 	}
3097e4b17023SJohn Marino 
3098e4b17023SJohn Marino     case FLOOR_MOD_EXPR:
3099e4b17023SJohn Marino       if (unsignedp)
3100e4b17023SJohn Marino 	return simplify_gen_binary (UMOD, mode, op0, op1);
3101e4b17023SJohn Marino       else
3102e4b17023SJohn Marino 	{
3103e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (MOD, mode, op0, op1);
3104e4b17023SJohn Marino 	  rtx adj = floor_sdiv_adjust (mode, mod, op1);
3105e4b17023SJohn Marino 	  adj = simplify_gen_unary (NEG, mode,
3106e4b17023SJohn Marino 				    simplify_gen_binary (MULT, mode, adj, op1),
3107e4b17023SJohn Marino 				    mode);
3108e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, mod, adj);
3109e4b17023SJohn Marino 	}
3110e4b17023SJohn Marino 
3111e4b17023SJohn Marino     case CEIL_DIV_EXPR:
3112e4b17023SJohn Marino       if (unsignedp)
3113e4b17023SJohn Marino 	{
3114e4b17023SJohn Marino 	  rtx div = simplify_gen_binary (UDIV, mode, op0, op1);
3115e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (UMOD, mode, op0, op1);
3116e4b17023SJohn Marino 	  rtx adj = ceil_udiv_adjust (mode, mod, op1);
3117e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, div, adj);
3118e4b17023SJohn Marino 	}
3119e4b17023SJohn Marino       else
3120e4b17023SJohn Marino 	{
3121e4b17023SJohn Marino 	  rtx div = simplify_gen_binary (DIV, mode, op0, op1);
3122e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (MOD, mode, op0, op1);
3123e4b17023SJohn Marino 	  rtx adj = ceil_sdiv_adjust (mode, mod, op1);
3124e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, div, adj);
3125e4b17023SJohn Marino 	}
3126e4b17023SJohn Marino 
3127e4b17023SJohn Marino     case CEIL_MOD_EXPR:
3128e4b17023SJohn Marino       if (unsignedp)
3129e4b17023SJohn Marino 	{
3130e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (UMOD, mode, op0, op1);
3131e4b17023SJohn Marino 	  rtx adj = ceil_udiv_adjust (mode, mod, op1);
3132e4b17023SJohn Marino 	  adj = simplify_gen_unary (NEG, mode,
3133e4b17023SJohn Marino 				    simplify_gen_binary (MULT, mode, adj, op1),
3134e4b17023SJohn Marino 				    mode);
3135e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, mod, adj);
3136e4b17023SJohn Marino 	}
3137e4b17023SJohn Marino       else
3138e4b17023SJohn Marino 	{
3139e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (MOD, mode, op0, op1);
3140e4b17023SJohn Marino 	  rtx adj = ceil_sdiv_adjust (mode, mod, op1);
3141e4b17023SJohn Marino 	  adj = simplify_gen_unary (NEG, mode,
3142e4b17023SJohn Marino 				    simplify_gen_binary (MULT, mode, adj, op1),
3143e4b17023SJohn Marino 				    mode);
3144e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, mod, adj);
3145e4b17023SJohn Marino 	}
3146e4b17023SJohn Marino 
3147e4b17023SJohn Marino     case ROUND_DIV_EXPR:
3148e4b17023SJohn Marino       if (unsignedp)
3149e4b17023SJohn Marino 	{
3150e4b17023SJohn Marino 	  rtx div = simplify_gen_binary (UDIV, mode, op0, op1);
3151e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (UMOD, mode, op0, op1);
3152e4b17023SJohn Marino 	  rtx adj = round_udiv_adjust (mode, mod, op1);
3153e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, div, adj);
3154e4b17023SJohn Marino 	}
3155e4b17023SJohn Marino       else
3156e4b17023SJohn Marino 	{
3157e4b17023SJohn Marino 	  rtx div = simplify_gen_binary (DIV, mode, op0, op1);
3158e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (MOD, mode, op0, op1);
3159e4b17023SJohn Marino 	  rtx adj = round_sdiv_adjust (mode, mod, op1);
3160e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, div, adj);
3161e4b17023SJohn Marino 	}
3162e4b17023SJohn Marino 
3163e4b17023SJohn Marino     case ROUND_MOD_EXPR:
3164e4b17023SJohn Marino       if (unsignedp)
3165e4b17023SJohn Marino 	{
3166e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (UMOD, mode, op0, op1);
3167e4b17023SJohn Marino 	  rtx adj = round_udiv_adjust (mode, mod, op1);
3168e4b17023SJohn Marino 	  adj = simplify_gen_unary (NEG, mode,
3169e4b17023SJohn Marino 				    simplify_gen_binary (MULT, mode, adj, op1),
3170e4b17023SJohn Marino 				    mode);
3171e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, mod, adj);
3172e4b17023SJohn Marino 	}
3173e4b17023SJohn Marino       else
3174e4b17023SJohn Marino 	{
3175e4b17023SJohn Marino 	  rtx mod = simplify_gen_binary (MOD, mode, op0, op1);
3176e4b17023SJohn Marino 	  rtx adj = round_sdiv_adjust (mode, mod, op1);
3177e4b17023SJohn Marino 	  adj = simplify_gen_unary (NEG, mode,
3178e4b17023SJohn Marino 				    simplify_gen_binary (MULT, mode, adj, op1),
3179e4b17023SJohn Marino 				    mode);
3180e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, mod, adj);
3181e4b17023SJohn Marino 	}
3182e4b17023SJohn Marino 
3183e4b17023SJohn Marino     case LSHIFT_EXPR:
3184e4b17023SJohn Marino       return simplify_gen_binary (ASHIFT, mode, op0, op1);
3185e4b17023SJohn Marino 
3186e4b17023SJohn Marino     case RSHIFT_EXPR:
3187e4b17023SJohn Marino       if (unsignedp)
3188e4b17023SJohn Marino 	return simplify_gen_binary (LSHIFTRT, mode, op0, op1);
3189e4b17023SJohn Marino       else
3190e4b17023SJohn Marino 	return simplify_gen_binary (ASHIFTRT, mode, op0, op1);
3191e4b17023SJohn Marino 
3192e4b17023SJohn Marino     case LROTATE_EXPR:
3193e4b17023SJohn Marino       return simplify_gen_binary (ROTATE, mode, op0, op1);
3194e4b17023SJohn Marino 
3195e4b17023SJohn Marino     case RROTATE_EXPR:
3196e4b17023SJohn Marino       return simplify_gen_binary (ROTATERT, mode, op0, op1);
3197e4b17023SJohn Marino 
3198e4b17023SJohn Marino     case MIN_EXPR:
3199e4b17023SJohn Marino       return simplify_gen_binary (unsignedp ? UMIN : SMIN, mode, op0, op1);
3200e4b17023SJohn Marino 
3201e4b17023SJohn Marino     case MAX_EXPR:
3202e4b17023SJohn Marino       return simplify_gen_binary (unsignedp ? UMAX : SMAX, mode, op0, op1);
3203e4b17023SJohn Marino 
3204e4b17023SJohn Marino     case BIT_AND_EXPR:
3205e4b17023SJohn Marino     case TRUTH_AND_EXPR:
3206e4b17023SJohn Marino       return simplify_gen_binary (AND, mode, op0, op1);
3207e4b17023SJohn Marino 
3208e4b17023SJohn Marino     case BIT_IOR_EXPR:
3209e4b17023SJohn Marino     case TRUTH_OR_EXPR:
3210e4b17023SJohn Marino       return simplify_gen_binary (IOR, mode, op0, op1);
3211e4b17023SJohn Marino 
3212e4b17023SJohn Marino     case BIT_XOR_EXPR:
3213e4b17023SJohn Marino     case TRUTH_XOR_EXPR:
3214e4b17023SJohn Marino       return simplify_gen_binary (XOR, mode, op0, op1);
3215e4b17023SJohn Marino 
3216e4b17023SJohn Marino     case TRUTH_ANDIF_EXPR:
3217e4b17023SJohn Marino       return gen_rtx_IF_THEN_ELSE (mode, op0, op1, const0_rtx);
3218e4b17023SJohn Marino 
3219e4b17023SJohn Marino     case TRUTH_ORIF_EXPR:
3220e4b17023SJohn Marino       return gen_rtx_IF_THEN_ELSE (mode, op0, const_true_rtx, op1);
3221e4b17023SJohn Marino 
3222e4b17023SJohn Marino     case TRUTH_NOT_EXPR:
3223e4b17023SJohn Marino       return simplify_gen_relational (EQ, mode, inner_mode, op0, const0_rtx);
3224e4b17023SJohn Marino 
3225e4b17023SJohn Marino     case LT_EXPR:
3226e4b17023SJohn Marino       return simplify_gen_relational (unsignedp ? LTU : LT, mode, inner_mode,
3227e4b17023SJohn Marino 				      op0, op1);
3228e4b17023SJohn Marino 
3229e4b17023SJohn Marino     case LE_EXPR:
3230e4b17023SJohn Marino       return simplify_gen_relational (unsignedp ? LEU : LE, mode, inner_mode,
3231e4b17023SJohn Marino 				      op0, op1);
3232e4b17023SJohn Marino 
3233e4b17023SJohn Marino     case GT_EXPR:
3234e4b17023SJohn Marino       return simplify_gen_relational (unsignedp ? GTU : GT, mode, inner_mode,
3235e4b17023SJohn Marino 				      op0, op1);
3236e4b17023SJohn Marino 
3237e4b17023SJohn Marino     case GE_EXPR:
3238e4b17023SJohn Marino       return simplify_gen_relational (unsignedp ? GEU : GE, mode, inner_mode,
3239e4b17023SJohn Marino 				      op0, op1);
3240e4b17023SJohn Marino 
3241e4b17023SJohn Marino     case EQ_EXPR:
3242e4b17023SJohn Marino       return simplify_gen_relational (EQ, mode, inner_mode, op0, op1);
3243e4b17023SJohn Marino 
3244e4b17023SJohn Marino     case NE_EXPR:
3245e4b17023SJohn Marino       return simplify_gen_relational (NE, mode, inner_mode, op0, op1);
3246e4b17023SJohn Marino 
3247e4b17023SJohn Marino     case UNORDERED_EXPR:
3248e4b17023SJohn Marino       return simplify_gen_relational (UNORDERED, mode, inner_mode, op0, op1);
3249e4b17023SJohn Marino 
3250e4b17023SJohn Marino     case ORDERED_EXPR:
3251e4b17023SJohn Marino       return simplify_gen_relational (ORDERED, mode, inner_mode, op0, op1);
3252e4b17023SJohn Marino 
3253e4b17023SJohn Marino     case UNLT_EXPR:
3254e4b17023SJohn Marino       return simplify_gen_relational (UNLT, mode, inner_mode, op0, op1);
3255e4b17023SJohn Marino 
3256e4b17023SJohn Marino     case UNLE_EXPR:
3257e4b17023SJohn Marino       return simplify_gen_relational (UNLE, mode, inner_mode, op0, op1);
3258e4b17023SJohn Marino 
3259e4b17023SJohn Marino     case UNGT_EXPR:
3260e4b17023SJohn Marino       return simplify_gen_relational (UNGT, mode, inner_mode, op0, op1);
3261e4b17023SJohn Marino 
3262e4b17023SJohn Marino     case UNGE_EXPR:
3263e4b17023SJohn Marino       return simplify_gen_relational (UNGE, mode, inner_mode, op0, op1);
3264e4b17023SJohn Marino 
3265e4b17023SJohn Marino     case UNEQ_EXPR:
3266e4b17023SJohn Marino       return simplify_gen_relational (UNEQ, mode, inner_mode, op0, op1);
3267e4b17023SJohn Marino 
3268e4b17023SJohn Marino     case LTGT_EXPR:
3269e4b17023SJohn Marino       return simplify_gen_relational (LTGT, mode, inner_mode, op0, op1);
3270e4b17023SJohn Marino 
3271e4b17023SJohn Marino     case COND_EXPR:
3272e4b17023SJohn Marino       return gen_rtx_IF_THEN_ELSE (mode, op0, op1, op2);
3273e4b17023SJohn Marino 
3274e4b17023SJohn Marino     case COMPLEX_EXPR:
3275e4b17023SJohn Marino       gcc_assert (COMPLEX_MODE_P (mode));
3276e4b17023SJohn Marino       if (GET_MODE (op0) == VOIDmode)
3277e4b17023SJohn Marino 	op0 = gen_rtx_CONST (GET_MODE_INNER (mode), op0);
3278e4b17023SJohn Marino       if (GET_MODE (op1) == VOIDmode)
3279e4b17023SJohn Marino 	op1 = gen_rtx_CONST (GET_MODE_INNER (mode), op1);
3280e4b17023SJohn Marino       return gen_rtx_CONCAT (mode, op0, op1);
3281e4b17023SJohn Marino 
3282e4b17023SJohn Marino     case CONJ_EXPR:
3283e4b17023SJohn Marino       if (GET_CODE (op0) == CONCAT)
3284e4b17023SJohn Marino 	return gen_rtx_CONCAT (mode, XEXP (op0, 0),
3285e4b17023SJohn Marino 			       simplify_gen_unary (NEG, GET_MODE_INNER (mode),
3286e4b17023SJohn Marino 						   XEXP (op0, 1),
3287e4b17023SJohn Marino 						   GET_MODE_INNER (mode)));
3288e4b17023SJohn Marino       else
3289e4b17023SJohn Marino 	{
3290e4b17023SJohn Marino 	  enum machine_mode imode = GET_MODE_INNER (mode);
3291e4b17023SJohn Marino 	  rtx re, im;
3292e4b17023SJohn Marino 
3293e4b17023SJohn Marino 	  if (MEM_P (op0))
3294e4b17023SJohn Marino 	    {
3295e4b17023SJohn Marino 	      re = adjust_address_nv (op0, imode, 0);
3296e4b17023SJohn Marino 	      im = adjust_address_nv (op0, imode, GET_MODE_SIZE (imode));
3297e4b17023SJohn Marino 	    }
3298e4b17023SJohn Marino 	  else
3299e4b17023SJohn Marino 	    {
3300e4b17023SJohn Marino 	      enum machine_mode ifmode = int_mode_for_mode (mode);
3301e4b17023SJohn Marino 	      enum machine_mode ihmode = int_mode_for_mode (imode);
3302e4b17023SJohn Marino 	      rtx halfsize;
3303e4b17023SJohn Marino 	      if (ifmode == BLKmode || ihmode == BLKmode)
3304e4b17023SJohn Marino 		return NULL;
3305e4b17023SJohn Marino 	      halfsize = GEN_INT (GET_MODE_BITSIZE (ihmode));
3306e4b17023SJohn Marino 	      re = op0;
3307e4b17023SJohn Marino 	      if (mode != ifmode)
3308e4b17023SJohn Marino 		re = gen_rtx_SUBREG (ifmode, re, 0);
3309e4b17023SJohn Marino 	      re = gen_rtx_ZERO_EXTRACT (ihmode, re, halfsize, const0_rtx);
3310e4b17023SJohn Marino 	      if (imode != ihmode)
3311e4b17023SJohn Marino 		re = gen_rtx_SUBREG (imode, re, 0);
3312e4b17023SJohn Marino 	      im = copy_rtx (op0);
3313e4b17023SJohn Marino 	      if (mode != ifmode)
3314e4b17023SJohn Marino 		im = gen_rtx_SUBREG (ifmode, im, 0);
3315e4b17023SJohn Marino 	      im = gen_rtx_ZERO_EXTRACT (ihmode, im, halfsize, halfsize);
3316e4b17023SJohn Marino 	      if (imode != ihmode)
3317e4b17023SJohn Marino 		im = gen_rtx_SUBREG (imode, im, 0);
3318e4b17023SJohn Marino 	    }
3319e4b17023SJohn Marino 	  im = gen_rtx_NEG (imode, im);
3320e4b17023SJohn Marino 	  return gen_rtx_CONCAT (mode, re, im);
3321e4b17023SJohn Marino 	}
3322e4b17023SJohn Marino 
3323e4b17023SJohn Marino     case ADDR_EXPR:
3324e4b17023SJohn Marino       op0 = expand_debug_expr (TREE_OPERAND (exp, 0));
3325e4b17023SJohn Marino       if (!op0 || !MEM_P (op0))
3326e4b17023SJohn Marino 	{
3327e4b17023SJohn Marino 	  if ((TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
3328e4b17023SJohn Marino 	       || TREE_CODE (TREE_OPERAND (exp, 0)) == PARM_DECL
3329e4b17023SJohn Marino 	       || TREE_CODE (TREE_OPERAND (exp, 0)) == RESULT_DECL)
3330e4b17023SJohn Marino 	      && (!TREE_ADDRESSABLE (TREE_OPERAND (exp, 0))
3331e4b17023SJohn Marino 		  || target_for_debug_bind (TREE_OPERAND (exp, 0))))
3332e4b17023SJohn Marino 	    return gen_rtx_DEBUG_IMPLICIT_PTR (mode, TREE_OPERAND (exp, 0));
3333e4b17023SJohn Marino 
3334e4b17023SJohn Marino 	  if (handled_component_p (TREE_OPERAND (exp, 0)))
3335e4b17023SJohn Marino 	    {
3336e4b17023SJohn Marino 	      HOST_WIDE_INT bitoffset, bitsize, maxsize;
3337e4b17023SJohn Marino 	      tree decl
3338e4b17023SJohn Marino 		= get_ref_base_and_extent (TREE_OPERAND (exp, 0),
3339e4b17023SJohn Marino 					   &bitoffset, &bitsize, &maxsize);
3340e4b17023SJohn Marino 	      if ((TREE_CODE (decl) == VAR_DECL
3341e4b17023SJohn Marino 		   || TREE_CODE (decl) == PARM_DECL
3342e4b17023SJohn Marino 		   || TREE_CODE (decl) == RESULT_DECL)
3343e4b17023SJohn Marino 		  && (!TREE_ADDRESSABLE (decl)
3344e4b17023SJohn Marino 		      || target_for_debug_bind (decl))
3345e4b17023SJohn Marino 		  && (bitoffset % BITS_PER_UNIT) == 0
3346e4b17023SJohn Marino 		  && bitsize > 0
3347e4b17023SJohn Marino 		  && bitsize == maxsize)
3348e4b17023SJohn Marino 		return plus_constant (gen_rtx_DEBUG_IMPLICIT_PTR (mode, decl),
3349e4b17023SJohn Marino 				      bitoffset / BITS_PER_UNIT);
3350e4b17023SJohn Marino 	    }
3351e4b17023SJohn Marino 
3352e4b17023SJohn Marino 	  return NULL;
3353e4b17023SJohn Marino 	}
3354e4b17023SJohn Marino 
3355e4b17023SJohn Marino       as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
3356e4b17023SJohn Marino       op0 = convert_debug_memory_address (mode, XEXP (op0, 0), as);
3357e4b17023SJohn Marino 
3358e4b17023SJohn Marino       return op0;
3359e4b17023SJohn Marino 
3360e4b17023SJohn Marino     case VECTOR_CST:
3361e4b17023SJohn Marino       exp = build_constructor_from_list (TREE_TYPE (exp),
3362e4b17023SJohn Marino 					 TREE_VECTOR_CST_ELTS (exp));
3363e4b17023SJohn Marino       /* Fall through.  */
3364e4b17023SJohn Marino 
3365e4b17023SJohn Marino     case CONSTRUCTOR:
3366e4b17023SJohn Marino       if (TREE_CLOBBER_P (exp))
3367e4b17023SJohn Marino 	return NULL;
3368e4b17023SJohn Marino       else if (TREE_CODE (TREE_TYPE (exp)) == VECTOR_TYPE)
3369e4b17023SJohn Marino 	{
3370e4b17023SJohn Marino 	  unsigned i;
3371e4b17023SJohn Marino 	  tree val;
3372e4b17023SJohn Marino 
3373e4b17023SJohn Marino 	  op0 = gen_rtx_CONCATN
3374e4b17023SJohn Marino 	    (mode, rtvec_alloc (TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp))));
3375e4b17023SJohn Marino 
3376e4b17023SJohn Marino 	  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), i, val)
3377e4b17023SJohn Marino 	    {
3378e4b17023SJohn Marino 	      op1 = expand_debug_expr (val);
3379e4b17023SJohn Marino 	      if (!op1)
3380e4b17023SJohn Marino 		return NULL;
3381e4b17023SJohn Marino 	      XVECEXP (op0, 0, i) = op1;
3382e4b17023SJohn Marino 	    }
3383e4b17023SJohn Marino 
3384e4b17023SJohn Marino 	  if (i < TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp)))
3385e4b17023SJohn Marino 	    {
3386e4b17023SJohn Marino 	      op1 = expand_debug_expr
3387e4b17023SJohn Marino 		(build_zero_cst (TREE_TYPE (TREE_TYPE (exp))));
3388e4b17023SJohn Marino 
3389e4b17023SJohn Marino 	      if (!op1)
3390e4b17023SJohn Marino 		return NULL;
3391e4b17023SJohn Marino 
3392e4b17023SJohn Marino 	      for (; i < TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp)); i++)
3393e4b17023SJohn Marino 		XVECEXP (op0, 0, i) = op1;
3394e4b17023SJohn Marino 	    }
3395e4b17023SJohn Marino 
3396e4b17023SJohn Marino 	  return op0;
3397e4b17023SJohn Marino 	}
3398e4b17023SJohn Marino       else
3399e4b17023SJohn Marino 	goto flag_unsupported;
3400e4b17023SJohn Marino 
3401e4b17023SJohn Marino     case CALL_EXPR:
3402e4b17023SJohn Marino       /* ??? Maybe handle some builtins?  */
3403e4b17023SJohn Marino       return NULL;
3404e4b17023SJohn Marino 
3405e4b17023SJohn Marino     case SSA_NAME:
3406e4b17023SJohn Marino       {
3407e4b17023SJohn Marino 	gimple g = get_gimple_for_ssa_name (exp);
3408e4b17023SJohn Marino 	if (g)
3409e4b17023SJohn Marino 	  {
3410e4b17023SJohn Marino 	    op0 = expand_debug_expr (gimple_assign_rhs_to_tree (g));
3411e4b17023SJohn Marino 	    if (!op0)
3412e4b17023SJohn Marino 	      return NULL;
3413e4b17023SJohn Marino 	  }
3414e4b17023SJohn Marino 	else
3415e4b17023SJohn Marino 	  {
3416e4b17023SJohn Marino 	    int part = var_to_partition (SA.map, exp);
3417e4b17023SJohn Marino 
3418e4b17023SJohn Marino 	    if (part == NO_PARTITION)
3419e4b17023SJohn Marino 	      {
3420e4b17023SJohn Marino 		/* If this is a reference to an incoming value of parameter
3421e4b17023SJohn Marino 		   that is never used in the code or where the incoming
3422e4b17023SJohn Marino 		   value is never used in the code, use PARM_DECL's
3423e4b17023SJohn Marino 		   DECL_RTL if set.  */
3424e4b17023SJohn Marino 		if (SSA_NAME_IS_DEFAULT_DEF (exp)
3425e4b17023SJohn Marino 		    && TREE_CODE (SSA_NAME_VAR (exp)) == PARM_DECL)
3426e4b17023SJohn Marino 		  {
3427e4b17023SJohn Marino 		    op0 = expand_debug_parm_decl (SSA_NAME_VAR (exp));
3428e4b17023SJohn Marino 		    if (op0)
3429e4b17023SJohn Marino 		      goto adjust_mode;
3430e4b17023SJohn Marino 		    op0 = expand_debug_expr (SSA_NAME_VAR (exp));
3431e4b17023SJohn Marino 		    if (op0)
3432e4b17023SJohn Marino 		      goto adjust_mode;
3433e4b17023SJohn Marino 		  }
3434e4b17023SJohn Marino 		return NULL;
3435e4b17023SJohn Marino 	      }
3436e4b17023SJohn Marino 
3437e4b17023SJohn Marino 	    gcc_assert (part >= 0 && (unsigned)part < SA.map->num_partitions);
3438e4b17023SJohn Marino 
3439e4b17023SJohn Marino 	    op0 = copy_rtx (SA.partition_to_pseudo[part]);
3440e4b17023SJohn Marino 	  }
3441e4b17023SJohn Marino 	goto adjust_mode;
3442e4b17023SJohn Marino       }
3443e4b17023SJohn Marino 
3444e4b17023SJohn Marino     case ERROR_MARK:
3445e4b17023SJohn Marino       return NULL;
3446e4b17023SJohn Marino 
3447e4b17023SJohn Marino     /* Vector stuff.  For most of the codes we don't have rtl codes.  */
3448e4b17023SJohn Marino     case REALIGN_LOAD_EXPR:
3449e4b17023SJohn Marino     case REDUC_MAX_EXPR:
3450e4b17023SJohn Marino     case REDUC_MIN_EXPR:
3451e4b17023SJohn Marino     case REDUC_PLUS_EXPR:
3452e4b17023SJohn Marino     case VEC_COND_EXPR:
3453e4b17023SJohn Marino     case VEC_LSHIFT_EXPR:
3454e4b17023SJohn Marino     case VEC_PACK_FIX_TRUNC_EXPR:
3455e4b17023SJohn Marino     case VEC_PACK_SAT_EXPR:
3456e4b17023SJohn Marino     case VEC_PACK_TRUNC_EXPR:
3457e4b17023SJohn Marino     case VEC_RSHIFT_EXPR:
3458e4b17023SJohn Marino     case VEC_UNPACK_FLOAT_HI_EXPR:
3459e4b17023SJohn Marino     case VEC_UNPACK_FLOAT_LO_EXPR:
3460e4b17023SJohn Marino     case VEC_UNPACK_HI_EXPR:
3461e4b17023SJohn Marino     case VEC_UNPACK_LO_EXPR:
3462e4b17023SJohn Marino     case VEC_WIDEN_MULT_HI_EXPR:
3463e4b17023SJohn Marino     case VEC_WIDEN_MULT_LO_EXPR:
3464e4b17023SJohn Marino     case VEC_WIDEN_LSHIFT_HI_EXPR:
3465e4b17023SJohn Marino     case VEC_WIDEN_LSHIFT_LO_EXPR:
3466e4b17023SJohn Marino     case VEC_PERM_EXPR:
3467e4b17023SJohn Marino       return NULL;
3468e4b17023SJohn Marino 
3469e4b17023SJohn Marino    /* Misc codes.  */
3470e4b17023SJohn Marino     case ADDR_SPACE_CONVERT_EXPR:
3471e4b17023SJohn Marino     case FIXED_CONVERT_EXPR:
3472e4b17023SJohn Marino     case OBJ_TYPE_REF:
3473e4b17023SJohn Marino     case WITH_SIZE_EXPR:
3474e4b17023SJohn Marino       return NULL;
3475e4b17023SJohn Marino 
3476e4b17023SJohn Marino     case DOT_PROD_EXPR:
3477e4b17023SJohn Marino       if (SCALAR_INT_MODE_P (GET_MODE (op0))
3478e4b17023SJohn Marino 	  && SCALAR_INT_MODE_P (mode))
3479e4b17023SJohn Marino 	{
3480e4b17023SJohn Marino 	  op0
3481e4b17023SJohn Marino 	    = simplify_gen_unary (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp,
3482e4b17023SJohn Marino 									  0)))
3483e4b17023SJohn Marino 				  ? ZERO_EXTEND : SIGN_EXTEND, mode, op0,
3484e4b17023SJohn Marino 				  inner_mode);
3485e4b17023SJohn Marino 	  op1
3486e4b17023SJohn Marino 	    = simplify_gen_unary (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp,
3487e4b17023SJohn Marino 									  1)))
3488e4b17023SJohn Marino 				  ? ZERO_EXTEND : SIGN_EXTEND, mode, op1,
3489e4b17023SJohn Marino 				  inner_mode);
3490e4b17023SJohn Marino 	  op0 = simplify_gen_binary (MULT, mode, op0, op1);
3491e4b17023SJohn Marino 	  return simplify_gen_binary (PLUS, mode, op0, op2);
3492e4b17023SJohn Marino 	}
3493e4b17023SJohn Marino       return NULL;
3494e4b17023SJohn Marino 
3495e4b17023SJohn Marino     case WIDEN_MULT_EXPR:
3496e4b17023SJohn Marino     case WIDEN_MULT_PLUS_EXPR:
3497e4b17023SJohn Marino     case WIDEN_MULT_MINUS_EXPR:
3498e4b17023SJohn Marino       if (SCALAR_INT_MODE_P (GET_MODE (op0))
3499e4b17023SJohn Marino 	  && SCALAR_INT_MODE_P (mode))
3500e4b17023SJohn Marino 	{
3501e4b17023SJohn Marino 	  inner_mode = GET_MODE (op0);
3502e4b17023SJohn Marino 	  if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))))
3503e4b17023SJohn Marino 	    op0 = simplify_gen_unary (ZERO_EXTEND, mode, op0, inner_mode);
3504e4b17023SJohn Marino 	  else
3505e4b17023SJohn Marino 	    op0 = simplify_gen_unary (SIGN_EXTEND, mode, op0, inner_mode);
3506e4b17023SJohn Marino 	  if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))))
3507e4b17023SJohn Marino 	    op1 = simplify_gen_unary (ZERO_EXTEND, mode, op1, inner_mode);
3508e4b17023SJohn Marino 	  else
3509e4b17023SJohn Marino 	    op1 = simplify_gen_unary (SIGN_EXTEND, mode, op1, inner_mode);
3510e4b17023SJohn Marino 	  op0 = simplify_gen_binary (MULT, mode, op0, op1);
3511e4b17023SJohn Marino 	  if (TREE_CODE (exp) == WIDEN_MULT_EXPR)
3512e4b17023SJohn Marino 	    return op0;
3513e4b17023SJohn Marino 	  else if (TREE_CODE (exp) == WIDEN_MULT_PLUS_EXPR)
3514e4b17023SJohn Marino 	    return simplify_gen_binary (PLUS, mode, op0, op2);
3515e4b17023SJohn Marino 	  else
3516e4b17023SJohn Marino 	    return simplify_gen_binary (MINUS, mode, op2, op0);
3517e4b17023SJohn Marino 	}
3518e4b17023SJohn Marino       return NULL;
3519e4b17023SJohn Marino 
3520e4b17023SJohn Marino     case WIDEN_SUM_EXPR:
3521e4b17023SJohn Marino     case WIDEN_LSHIFT_EXPR:
3522e4b17023SJohn Marino       if (SCALAR_INT_MODE_P (GET_MODE (op0))
3523e4b17023SJohn Marino 	  && SCALAR_INT_MODE_P (mode))
3524e4b17023SJohn Marino 	{
3525e4b17023SJohn Marino 	  op0
3526e4b17023SJohn Marino 	    = simplify_gen_unary (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp,
3527e4b17023SJohn Marino 									  0)))
3528e4b17023SJohn Marino 				  ? ZERO_EXTEND : SIGN_EXTEND, mode, op0,
3529e4b17023SJohn Marino 				  inner_mode);
3530e4b17023SJohn Marino 	  return simplify_gen_binary (TREE_CODE (exp) == WIDEN_LSHIFT_EXPR
3531e4b17023SJohn Marino 				      ? ASHIFT : PLUS, mode, op0, op1);
3532e4b17023SJohn Marino 	}
3533e4b17023SJohn Marino       return NULL;
3534e4b17023SJohn Marino 
3535e4b17023SJohn Marino     case FMA_EXPR:
3536e4b17023SJohn Marino       return simplify_gen_ternary (FMA, mode, inner_mode, op0, op1, op2);
3537e4b17023SJohn Marino 
3538e4b17023SJohn Marino     default:
3539e4b17023SJohn Marino     flag_unsupported:
3540e4b17023SJohn Marino #ifdef ENABLE_CHECKING
3541e4b17023SJohn Marino       debug_tree (exp);
3542e4b17023SJohn Marino       gcc_unreachable ();
3543e4b17023SJohn Marino #else
3544e4b17023SJohn Marino       return NULL;
3545e4b17023SJohn Marino #endif
3546e4b17023SJohn Marino     }
3547e4b17023SJohn Marino }
3548e4b17023SJohn Marino 
3549e4b17023SJohn Marino /* Return an RTX equivalent to the source bind value of the tree expression
3550e4b17023SJohn Marino    EXP.  */
3551e4b17023SJohn Marino 
3552e4b17023SJohn Marino static rtx
expand_debug_source_expr(tree exp)3553e4b17023SJohn Marino expand_debug_source_expr (tree exp)
3554e4b17023SJohn Marino {
3555e4b17023SJohn Marino   rtx op0 = NULL_RTX;
3556e4b17023SJohn Marino   enum machine_mode mode = VOIDmode, inner_mode;
3557e4b17023SJohn Marino 
3558e4b17023SJohn Marino   switch (TREE_CODE (exp))
3559e4b17023SJohn Marino     {
3560e4b17023SJohn Marino     case PARM_DECL:
3561e4b17023SJohn Marino       {
3562e4b17023SJohn Marino 	mode = DECL_MODE (exp);
3563e4b17023SJohn Marino 	op0 = expand_debug_parm_decl (exp);
3564e4b17023SJohn Marino 	if (op0)
3565e4b17023SJohn Marino 	   break;
3566e4b17023SJohn Marino 	/* See if this isn't an argument that has been completely
3567e4b17023SJohn Marino 	   optimized out.  */
3568e4b17023SJohn Marino 	if (!DECL_RTL_SET_P (exp)
3569e4b17023SJohn Marino 	    && !DECL_INCOMING_RTL (exp)
3570e4b17023SJohn Marino 	    && DECL_ABSTRACT_ORIGIN (current_function_decl))
3571e4b17023SJohn Marino 	  {
3572e4b17023SJohn Marino 	    tree aexp = exp;
3573e4b17023SJohn Marino 	    if (DECL_ABSTRACT_ORIGIN (exp))
3574e4b17023SJohn Marino 	      aexp = DECL_ABSTRACT_ORIGIN (exp);
3575e4b17023SJohn Marino 	    if (DECL_CONTEXT (aexp)
3576e4b17023SJohn Marino 		== DECL_ABSTRACT_ORIGIN (current_function_decl))
3577e4b17023SJohn Marino 	      {
3578e4b17023SJohn Marino 		VEC(tree, gc) **debug_args;
3579e4b17023SJohn Marino 		unsigned int ix;
3580e4b17023SJohn Marino 		tree ddecl;
3581e4b17023SJohn Marino #ifdef ENABLE_CHECKING
3582e4b17023SJohn Marino 		tree parm;
3583e4b17023SJohn Marino 		for (parm = DECL_ARGUMENTS (current_function_decl);
3584e4b17023SJohn Marino 		     parm; parm = DECL_CHAIN (parm))
3585e4b17023SJohn Marino 		  gcc_assert (parm != exp
3586e4b17023SJohn Marino 			      && DECL_ABSTRACT_ORIGIN (parm) != aexp);
3587e4b17023SJohn Marino #endif
3588e4b17023SJohn Marino 		debug_args = decl_debug_args_lookup (current_function_decl);
3589e4b17023SJohn Marino 		if (debug_args != NULL)
3590e4b17023SJohn Marino 		  {
3591e4b17023SJohn Marino 		    for (ix = 0; VEC_iterate (tree, *debug_args, ix, ddecl);
3592e4b17023SJohn Marino 			 ix += 2)
3593e4b17023SJohn Marino 		      if (ddecl == aexp)
3594e4b17023SJohn Marino 			return gen_rtx_DEBUG_PARAMETER_REF (mode, aexp);
3595e4b17023SJohn Marino 		  }
3596e4b17023SJohn Marino 	      }
3597e4b17023SJohn Marino 	  }
3598e4b17023SJohn Marino 	break;
3599e4b17023SJohn Marino       }
3600e4b17023SJohn Marino     default:
3601e4b17023SJohn Marino       break;
3602e4b17023SJohn Marino     }
3603e4b17023SJohn Marino 
3604e4b17023SJohn Marino   if (op0 == NULL_RTX)
3605e4b17023SJohn Marino     return NULL_RTX;
3606e4b17023SJohn Marino 
3607e4b17023SJohn Marino   inner_mode = GET_MODE (op0);
3608e4b17023SJohn Marino   if (mode == inner_mode)
3609e4b17023SJohn Marino     return op0;
3610e4b17023SJohn Marino 
3611e4b17023SJohn Marino   if (FLOAT_MODE_P (mode) && FLOAT_MODE_P (inner_mode))
3612e4b17023SJohn Marino     {
3613e4b17023SJohn Marino       if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (inner_mode))
3614e4b17023SJohn Marino 	op0 = simplify_gen_subreg (mode, op0, inner_mode, 0);
3615e4b17023SJohn Marino       else if (GET_MODE_BITSIZE (mode) < GET_MODE_BITSIZE (inner_mode))
3616e4b17023SJohn Marino 	op0 = simplify_gen_unary (FLOAT_TRUNCATE, mode, op0, inner_mode);
3617e4b17023SJohn Marino       else
3618e4b17023SJohn Marino 	op0 = simplify_gen_unary (FLOAT_EXTEND, mode, op0, inner_mode);
3619e4b17023SJohn Marino     }
3620e4b17023SJohn Marino   else if (FLOAT_MODE_P (mode))
3621e4b17023SJohn Marino     gcc_unreachable ();
3622e4b17023SJohn Marino   else if (FLOAT_MODE_P (inner_mode))
3623e4b17023SJohn Marino     {
3624e4b17023SJohn Marino       if (TYPE_UNSIGNED (TREE_TYPE (exp)))
3625e4b17023SJohn Marino 	op0 = simplify_gen_unary (UNSIGNED_FIX, mode, op0, inner_mode);
3626e4b17023SJohn Marino       else
3627e4b17023SJohn Marino 	op0 = simplify_gen_unary (FIX, mode, op0, inner_mode);
3628e4b17023SJohn Marino     }
3629e4b17023SJohn Marino   else if (CONSTANT_P (op0)
3630e4b17023SJohn Marino 	   || GET_MODE_BITSIZE (mode) <= GET_MODE_BITSIZE (inner_mode))
3631e4b17023SJohn Marino     op0 = simplify_gen_subreg (mode, op0, inner_mode,
3632e4b17023SJohn Marino 			       subreg_lowpart_offset (mode, inner_mode));
3633e4b17023SJohn Marino   else if (TYPE_UNSIGNED (TREE_TYPE (exp)))
3634e4b17023SJohn Marino     op0 = simplify_gen_unary (ZERO_EXTEND, mode, op0, inner_mode);
3635e4b17023SJohn Marino   else
3636e4b17023SJohn Marino     op0 = simplify_gen_unary (SIGN_EXTEND, mode, op0, inner_mode);
3637e4b17023SJohn Marino 
3638e4b17023SJohn Marino   return op0;
3639e4b17023SJohn Marino }
3640e4b17023SJohn Marino 
36415ce9237cSJohn Marino /* Ensure INSN_VAR_LOCATION_LOC (insn) doesn't have unbound complexity.
36425ce9237cSJohn Marino    Allow 4 levels of rtl nesting for most rtl codes, and if we see anything
36435ce9237cSJohn Marino    deeper than that, create DEBUG_EXPRs and emit DEBUG_INSNs before INSN.  */
36445ce9237cSJohn Marino 
36455ce9237cSJohn Marino static void
avoid_complex_debug_insns(rtx insn,rtx * exp_p,int depth)36465ce9237cSJohn Marino avoid_complex_debug_insns (rtx insn, rtx *exp_p, int depth)
36475ce9237cSJohn Marino {
36485ce9237cSJohn Marino   rtx exp = *exp_p;
3649*95d28233SJohn Marino   const char *format_ptr;
3650*95d28233SJohn Marino   int i, j;
36515ce9237cSJohn Marino 
36525ce9237cSJohn Marino   if (exp == NULL_RTX)
36535ce9237cSJohn Marino     return;
36545ce9237cSJohn Marino 
36555ce9237cSJohn Marino   if ((OBJECT_P (exp) && !MEM_P (exp)) || GET_CODE (exp) == CLOBBER)
36565ce9237cSJohn Marino     return;
36575ce9237cSJohn Marino 
36585ce9237cSJohn Marino   if (depth == 4)
36595ce9237cSJohn Marino     {
36605ce9237cSJohn Marino       /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL).  */
36615ce9237cSJohn Marino       rtx dval = make_debug_expr_from_rtl (exp);
36625ce9237cSJohn Marino 
36635ce9237cSJohn Marino       /* Emit a debug bind insn before INSN.  */
36645ce9237cSJohn Marino       rtx bind = gen_rtx_VAR_LOCATION (GET_MODE (exp),
36655ce9237cSJohn Marino 				       DEBUG_EXPR_TREE_DECL (dval), exp,
36665ce9237cSJohn Marino 				       VAR_INIT_STATUS_INITIALIZED);
36675ce9237cSJohn Marino 
36685ce9237cSJohn Marino       emit_debug_insn_before (bind, insn);
36695ce9237cSJohn Marino       *exp_p = dval;
36705ce9237cSJohn Marino       return;
36715ce9237cSJohn Marino     }
36725ce9237cSJohn Marino 
3673*95d28233SJohn Marino   format_ptr = GET_RTX_FORMAT (GET_CODE (exp));
36745ce9237cSJohn Marino   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
36755ce9237cSJohn Marino     switch (*format_ptr++)
36765ce9237cSJohn Marino       {
36775ce9237cSJohn Marino       case 'e':
36785ce9237cSJohn Marino 	avoid_complex_debug_insns (insn, &XEXP (exp, i), depth + 1);
36795ce9237cSJohn Marino 	break;
36805ce9237cSJohn Marino 
36815ce9237cSJohn Marino       case 'E':
36825ce9237cSJohn Marino       case 'V':
36835ce9237cSJohn Marino 	for (j = 0; j < XVECLEN (exp, i); j++)
36845ce9237cSJohn Marino 	  avoid_complex_debug_insns (insn, &XVECEXP (exp, i, j), depth + 1);
36855ce9237cSJohn Marino 	break;
36865ce9237cSJohn Marino 
36875ce9237cSJohn Marino       default:
36885ce9237cSJohn Marino 	break;
36895ce9237cSJohn Marino       }
36905ce9237cSJohn Marino }
36915ce9237cSJohn Marino 
3692e4b17023SJohn Marino /* Expand the _LOCs in debug insns.  We run this after expanding all
3693e4b17023SJohn Marino    regular insns, so that any variables referenced in the function
3694e4b17023SJohn Marino    will have their DECL_RTLs set.  */
3695e4b17023SJohn Marino 
3696e4b17023SJohn Marino static void
expand_debug_locations(void)3697e4b17023SJohn Marino expand_debug_locations (void)
3698e4b17023SJohn Marino {
3699e4b17023SJohn Marino   rtx insn;
3700e4b17023SJohn Marino   rtx last = get_last_insn ();
3701e4b17023SJohn Marino   int save_strict_alias = flag_strict_aliasing;
3702e4b17023SJohn Marino 
3703e4b17023SJohn Marino   /* New alias sets while setting up memory attributes cause
3704e4b17023SJohn Marino      -fcompare-debug failures, even though it doesn't bring about any
3705e4b17023SJohn Marino      codegen changes.  */
3706e4b17023SJohn Marino   flag_strict_aliasing = 0;
3707e4b17023SJohn Marino 
3708e4b17023SJohn Marino   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3709e4b17023SJohn Marino     if (DEBUG_INSN_P (insn))
3710e4b17023SJohn Marino       {
3711e4b17023SJohn Marino 	tree value = (tree)INSN_VAR_LOCATION_LOC (insn);
37125ce9237cSJohn Marino 	rtx val, prev_insn, insn2;
3713e4b17023SJohn Marino 	enum machine_mode mode;
3714e4b17023SJohn Marino 
3715e4b17023SJohn Marino 	if (value == NULL_TREE)
3716e4b17023SJohn Marino 	  val = NULL_RTX;
3717e4b17023SJohn Marino 	else
3718e4b17023SJohn Marino 	  {
3719e4b17023SJohn Marino 	    if (INSN_VAR_LOCATION_STATUS (insn)
3720e4b17023SJohn Marino 		== VAR_INIT_STATUS_UNINITIALIZED)
3721e4b17023SJohn Marino 	      val = expand_debug_source_expr (value);
3722e4b17023SJohn Marino 	    else
3723e4b17023SJohn Marino 	      val = expand_debug_expr (value);
3724e4b17023SJohn Marino 	    gcc_assert (last == get_last_insn ());
3725e4b17023SJohn Marino 	  }
3726e4b17023SJohn Marino 
3727e4b17023SJohn Marino 	if (!val)
3728e4b17023SJohn Marino 	  val = gen_rtx_UNKNOWN_VAR_LOC ();
3729e4b17023SJohn Marino 	else
3730e4b17023SJohn Marino 	  {
3731e4b17023SJohn Marino 	    mode = GET_MODE (INSN_VAR_LOCATION (insn));
3732e4b17023SJohn Marino 
3733e4b17023SJohn Marino 	    gcc_assert (mode == GET_MODE (val)
3734e4b17023SJohn Marino 			|| (GET_MODE (val) == VOIDmode
3735e4b17023SJohn Marino 			    && (CONST_INT_P (val)
3736e4b17023SJohn Marino 				|| GET_CODE (val) == CONST_FIXED
3737e4b17023SJohn Marino 				|| GET_CODE (val) == CONST_DOUBLE
3738e4b17023SJohn Marino 				|| GET_CODE (val) == LABEL_REF)));
3739e4b17023SJohn Marino 	  }
3740e4b17023SJohn Marino 
3741e4b17023SJohn Marino 	INSN_VAR_LOCATION_LOC (insn) = val;
37425ce9237cSJohn Marino 	prev_insn = PREV_INSN (insn);
37435ce9237cSJohn Marino 	for (insn2 = insn; insn2 != prev_insn; insn2 = PREV_INSN (insn2))
37445ce9237cSJohn Marino 	  avoid_complex_debug_insns (insn2, &INSN_VAR_LOCATION_LOC (insn2), 0);
3745e4b17023SJohn Marino       }
3746e4b17023SJohn Marino 
3747e4b17023SJohn Marino   flag_strict_aliasing = save_strict_alias;
3748e4b17023SJohn Marino }
3749e4b17023SJohn Marino 
3750e4b17023SJohn Marino /* Expand basic block BB from GIMPLE trees to RTL.  */
3751e4b17023SJohn Marino 
3752e4b17023SJohn Marino static basic_block
expand_gimple_basic_block(basic_block bb)3753e4b17023SJohn Marino expand_gimple_basic_block (basic_block bb)
3754e4b17023SJohn Marino {
3755e4b17023SJohn Marino   gimple_stmt_iterator gsi;
3756e4b17023SJohn Marino   gimple_seq stmts;
3757e4b17023SJohn Marino   gimple stmt = NULL;
3758e4b17023SJohn Marino   rtx note, last;
3759e4b17023SJohn Marino   edge e;
3760e4b17023SJohn Marino   edge_iterator ei;
3761e4b17023SJohn Marino   void **elt;
3762e4b17023SJohn Marino 
3763e4b17023SJohn Marino   if (dump_file)
3764e4b17023SJohn Marino     fprintf (dump_file, "\n;; Generating RTL for gimple basic block %d\n",
3765e4b17023SJohn Marino 	     bb->index);
3766e4b17023SJohn Marino 
3767e4b17023SJohn Marino   /* Note that since we are now transitioning from GIMPLE to RTL, we
3768e4b17023SJohn Marino      cannot use the gsi_*_bb() routines because they expect the basic
3769e4b17023SJohn Marino      block to be in GIMPLE, instead of RTL.  Therefore, we need to
3770e4b17023SJohn Marino      access the BB sequence directly.  */
3771e4b17023SJohn Marino   stmts = bb_seq (bb);
3772e4b17023SJohn Marino   bb->il.gimple = NULL;
3773e4b17023SJohn Marino   rtl_profile_for_bb (bb);
3774e4b17023SJohn Marino   init_rtl_bb_info (bb);
3775e4b17023SJohn Marino   bb->flags |= BB_RTL;
3776e4b17023SJohn Marino 
3777e4b17023SJohn Marino   /* Remove the RETURN_EXPR if we may fall though to the exit
3778e4b17023SJohn Marino      instead.  */
3779e4b17023SJohn Marino   gsi = gsi_last (stmts);
3780e4b17023SJohn Marino   if (!gsi_end_p (gsi)
3781e4b17023SJohn Marino       && gimple_code (gsi_stmt (gsi)) == GIMPLE_RETURN)
3782e4b17023SJohn Marino     {
3783e4b17023SJohn Marino       gimple ret_stmt = gsi_stmt (gsi);
3784e4b17023SJohn Marino 
3785e4b17023SJohn Marino       gcc_assert (single_succ_p (bb));
3786e4b17023SJohn Marino       gcc_assert (single_succ (bb) == EXIT_BLOCK_PTR);
3787e4b17023SJohn Marino 
3788e4b17023SJohn Marino       if (bb->next_bb == EXIT_BLOCK_PTR
3789e4b17023SJohn Marino 	  && !gimple_return_retval (ret_stmt))
3790e4b17023SJohn Marino 	{
3791e4b17023SJohn Marino 	  gsi_remove (&gsi, false);
3792e4b17023SJohn Marino 	  single_succ_edge (bb)->flags |= EDGE_FALLTHRU;
3793e4b17023SJohn Marino 	}
3794e4b17023SJohn Marino     }
3795e4b17023SJohn Marino 
3796e4b17023SJohn Marino   gsi = gsi_start (stmts);
3797e4b17023SJohn Marino   if (!gsi_end_p (gsi))
3798e4b17023SJohn Marino     {
3799e4b17023SJohn Marino       stmt = gsi_stmt (gsi);
3800e4b17023SJohn Marino       if (gimple_code (stmt) != GIMPLE_LABEL)
3801e4b17023SJohn Marino 	stmt = NULL;
3802e4b17023SJohn Marino     }
3803e4b17023SJohn Marino 
3804e4b17023SJohn Marino   elt = pointer_map_contains (lab_rtx_for_bb, bb);
3805e4b17023SJohn Marino 
3806e4b17023SJohn Marino   if (stmt || elt)
3807e4b17023SJohn Marino     {
3808e4b17023SJohn Marino       last = get_last_insn ();
3809e4b17023SJohn Marino 
3810e4b17023SJohn Marino       if (stmt)
3811e4b17023SJohn Marino 	{
3812e4b17023SJohn Marino 	  expand_gimple_stmt (stmt);
3813e4b17023SJohn Marino 	  gsi_next (&gsi);
3814e4b17023SJohn Marino 	}
3815e4b17023SJohn Marino 
3816e4b17023SJohn Marino       if (elt)
3817e4b17023SJohn Marino 	emit_label ((rtx) *elt);
3818e4b17023SJohn Marino 
3819e4b17023SJohn Marino       /* Java emits line number notes in the top of labels.
3820e4b17023SJohn Marino 	 ??? Make this go away once line number notes are obsoleted.  */
3821e4b17023SJohn Marino       BB_HEAD (bb) = NEXT_INSN (last);
3822e4b17023SJohn Marino       if (NOTE_P (BB_HEAD (bb)))
3823e4b17023SJohn Marino 	BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb));
3824e4b17023SJohn Marino       note = emit_note_after (NOTE_INSN_BASIC_BLOCK, BB_HEAD (bb));
3825e4b17023SJohn Marino 
3826e4b17023SJohn Marino       maybe_dump_rtl_for_gimple_stmt (stmt, last);
3827e4b17023SJohn Marino     }
3828e4b17023SJohn Marino   else
3829e4b17023SJohn Marino     note = BB_HEAD (bb) = emit_note (NOTE_INSN_BASIC_BLOCK);
3830e4b17023SJohn Marino 
3831e4b17023SJohn Marino   NOTE_BASIC_BLOCK (note) = bb;
3832e4b17023SJohn Marino 
3833e4b17023SJohn Marino   for (; !gsi_end_p (gsi); gsi_next (&gsi))
3834e4b17023SJohn Marino     {
3835e4b17023SJohn Marino       basic_block new_bb;
3836e4b17023SJohn Marino 
3837e4b17023SJohn Marino       stmt = gsi_stmt (gsi);
3838e4b17023SJohn Marino 
3839e4b17023SJohn Marino       /* If this statement is a non-debug one, and we generate debug
3840e4b17023SJohn Marino 	 insns, then this one might be the last real use of a TERed
3841e4b17023SJohn Marino 	 SSA_NAME, but where there are still some debug uses further
3842e4b17023SJohn Marino 	 down.  Expanding the current SSA name in such further debug
3843e4b17023SJohn Marino 	 uses by their RHS might lead to wrong debug info, as coalescing
3844e4b17023SJohn Marino 	 might make the operands of such RHS be placed into the same
3845e4b17023SJohn Marino 	 pseudo as something else.  Like so:
3846e4b17023SJohn Marino 	   a_1 = a_0 + 1;   // Assume a_1 is TERed and a_0 is dead
3847e4b17023SJohn Marino 	   use(a_1);
3848e4b17023SJohn Marino 	   a_2 = ...
3849e4b17023SJohn Marino            #DEBUG ... => a_1
3850e4b17023SJohn Marino 	 As a_0 and a_2 don't overlap in lifetime, assume they are coalesced.
3851e4b17023SJohn Marino 	 If we now would expand a_1 by it's RHS (a_0 + 1) in the debug use,
3852e4b17023SJohn Marino 	 the write to a_2 would actually have clobbered the place which
3853e4b17023SJohn Marino 	 formerly held a_0.
3854e4b17023SJohn Marino 
3855e4b17023SJohn Marino 	 So, instead of that, we recognize the situation, and generate
3856e4b17023SJohn Marino 	 debug temporaries at the last real use of TERed SSA names:
3857e4b17023SJohn Marino 	   a_1 = a_0 + 1;
3858e4b17023SJohn Marino            #DEBUG #D1 => a_1
3859e4b17023SJohn Marino 	   use(a_1);
3860e4b17023SJohn Marino 	   a_2 = ...
3861e4b17023SJohn Marino            #DEBUG ... => #D1
3862e4b17023SJohn Marino 	 */
3863e4b17023SJohn Marino       if (MAY_HAVE_DEBUG_INSNS
3864e4b17023SJohn Marino 	  && SA.values
3865e4b17023SJohn Marino 	  && !is_gimple_debug (stmt))
3866e4b17023SJohn Marino 	{
3867e4b17023SJohn Marino 	  ssa_op_iter iter;
3868e4b17023SJohn Marino 	  tree op;
3869e4b17023SJohn Marino 	  gimple def;
3870e4b17023SJohn Marino 
3871e4b17023SJohn Marino 	  location_t sloc = get_curr_insn_source_location ();
3872e4b17023SJohn Marino 	  tree sblock = get_curr_insn_block ();
3873e4b17023SJohn Marino 
3874e4b17023SJohn Marino 	  /* Look for SSA names that have their last use here (TERed
3875e4b17023SJohn Marino 	     names always have only one real use).  */
3876e4b17023SJohn Marino 	  FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
3877e4b17023SJohn Marino 	    if ((def = get_gimple_for_ssa_name (op)))
3878e4b17023SJohn Marino 	      {
3879e4b17023SJohn Marino 		imm_use_iterator imm_iter;
3880e4b17023SJohn Marino 		use_operand_p use_p;
3881e4b17023SJohn Marino 		bool have_debug_uses = false;
3882e4b17023SJohn Marino 
3883e4b17023SJohn Marino 		FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
3884e4b17023SJohn Marino 		  {
3885e4b17023SJohn Marino 		    if (gimple_debug_bind_p (USE_STMT (use_p)))
3886e4b17023SJohn Marino 		      {
3887e4b17023SJohn Marino 			have_debug_uses = true;
3888e4b17023SJohn Marino 			break;
3889e4b17023SJohn Marino 		      }
3890e4b17023SJohn Marino 		  }
3891e4b17023SJohn Marino 
3892e4b17023SJohn Marino 		if (have_debug_uses)
3893e4b17023SJohn Marino 		  {
3894e4b17023SJohn Marino 		    /* OP is a TERed SSA name, with DEF it's defining
3895e4b17023SJohn Marino 		       statement, and where OP is used in further debug
3896e4b17023SJohn Marino 		       instructions.  Generate a debug temporary, and
3897e4b17023SJohn Marino 		       replace all uses of OP in debug insns with that
3898e4b17023SJohn Marino 		       temporary.  */
3899e4b17023SJohn Marino 		    gimple debugstmt;
3900e4b17023SJohn Marino 		    tree value = gimple_assign_rhs_to_tree (def);
3901e4b17023SJohn Marino 		    tree vexpr = make_node (DEBUG_EXPR_DECL);
3902e4b17023SJohn Marino 		    rtx val;
3903e4b17023SJohn Marino 		    enum machine_mode mode;
3904e4b17023SJohn Marino 
3905e4b17023SJohn Marino 		    set_curr_insn_source_location (gimple_location (def));
3906e4b17023SJohn Marino 		    set_curr_insn_block (gimple_block (def));
3907e4b17023SJohn Marino 
3908e4b17023SJohn Marino 		    DECL_ARTIFICIAL (vexpr) = 1;
3909e4b17023SJohn Marino 		    TREE_TYPE (vexpr) = TREE_TYPE (value);
3910e4b17023SJohn Marino 		    if (DECL_P (value))
3911e4b17023SJohn Marino 		      mode = DECL_MODE (value);
3912e4b17023SJohn Marino 		    else
3913e4b17023SJohn Marino 		      mode = TYPE_MODE (TREE_TYPE (value));
3914e4b17023SJohn Marino 		    DECL_MODE (vexpr) = mode;
3915e4b17023SJohn Marino 
3916e4b17023SJohn Marino 		    val = gen_rtx_VAR_LOCATION
3917e4b17023SJohn Marino 			(mode, vexpr, (rtx)value, VAR_INIT_STATUS_INITIALIZED);
3918e4b17023SJohn Marino 
3919e4b17023SJohn Marino 		    emit_debug_insn (val);
3920e4b17023SJohn Marino 
3921e4b17023SJohn Marino 		    FOR_EACH_IMM_USE_STMT (debugstmt, imm_iter, op)
3922e4b17023SJohn Marino 		      {
3923e4b17023SJohn Marino 			if (!gimple_debug_bind_p (debugstmt))
3924e4b17023SJohn Marino 			  continue;
3925e4b17023SJohn Marino 
3926e4b17023SJohn Marino 			FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
3927e4b17023SJohn Marino 			  SET_USE (use_p, vexpr);
3928e4b17023SJohn Marino 
3929e4b17023SJohn Marino 			update_stmt (debugstmt);
3930e4b17023SJohn Marino 		      }
3931e4b17023SJohn Marino 		  }
3932e4b17023SJohn Marino 	      }
3933e4b17023SJohn Marino 	  set_curr_insn_source_location (sloc);
3934e4b17023SJohn Marino 	  set_curr_insn_block (sblock);
3935e4b17023SJohn Marino 	}
3936e4b17023SJohn Marino 
3937e4b17023SJohn Marino       currently_expanding_gimple_stmt = stmt;
3938e4b17023SJohn Marino 
3939e4b17023SJohn Marino       /* Expand this statement, then evaluate the resulting RTL and
3940e4b17023SJohn Marino 	 fixup the CFG accordingly.  */
3941e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_COND)
3942e4b17023SJohn Marino 	{
3943e4b17023SJohn Marino 	  new_bb = expand_gimple_cond (bb, stmt);
3944e4b17023SJohn Marino 	  if (new_bb)
3945e4b17023SJohn Marino 	    return new_bb;
3946e4b17023SJohn Marino 	}
3947e4b17023SJohn Marino       else if (gimple_debug_bind_p (stmt))
3948e4b17023SJohn Marino 	{
3949e4b17023SJohn Marino 	  location_t sloc = get_curr_insn_source_location ();
3950e4b17023SJohn Marino 	  tree sblock = get_curr_insn_block ();
3951e4b17023SJohn Marino 	  gimple_stmt_iterator nsi = gsi;
3952e4b17023SJohn Marino 
3953e4b17023SJohn Marino 	  for (;;)
3954e4b17023SJohn Marino 	    {
3955e4b17023SJohn Marino 	      tree var = gimple_debug_bind_get_var (stmt);
3956e4b17023SJohn Marino 	      tree value;
3957e4b17023SJohn Marino 	      rtx val;
3958e4b17023SJohn Marino 	      enum machine_mode mode;
3959e4b17023SJohn Marino 
3960e4b17023SJohn Marino 	      if (TREE_CODE (var) != DEBUG_EXPR_DECL
3961e4b17023SJohn Marino 		  && TREE_CODE (var) != LABEL_DECL
3962e4b17023SJohn Marino 		  && !target_for_debug_bind (var))
3963e4b17023SJohn Marino 		goto delink_debug_stmt;
3964e4b17023SJohn Marino 
3965e4b17023SJohn Marino 	      if (gimple_debug_bind_has_value_p (stmt))
3966e4b17023SJohn Marino 		value = gimple_debug_bind_get_value (stmt);
3967e4b17023SJohn Marino 	      else
3968e4b17023SJohn Marino 		value = NULL_TREE;
3969e4b17023SJohn Marino 
3970e4b17023SJohn Marino 	      last = get_last_insn ();
3971e4b17023SJohn Marino 
3972e4b17023SJohn Marino 	      set_curr_insn_source_location (gimple_location (stmt));
3973e4b17023SJohn Marino 	      set_curr_insn_block (gimple_block (stmt));
3974e4b17023SJohn Marino 
3975e4b17023SJohn Marino 	      if (DECL_P (var))
3976e4b17023SJohn Marino 		mode = DECL_MODE (var);
3977e4b17023SJohn Marino 	      else
3978e4b17023SJohn Marino 		mode = TYPE_MODE (TREE_TYPE (var));
3979e4b17023SJohn Marino 
3980e4b17023SJohn Marino 	      val = gen_rtx_VAR_LOCATION
3981e4b17023SJohn Marino 		(mode, var, (rtx)value, VAR_INIT_STATUS_INITIALIZED);
3982e4b17023SJohn Marino 
3983e4b17023SJohn Marino 	      emit_debug_insn (val);
3984e4b17023SJohn Marino 
3985e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3986e4b17023SJohn Marino 		{
3987e4b17023SJohn Marino 		  /* We can't dump the insn with a TREE where an RTX
3988e4b17023SJohn Marino 		     is expected.  */
3989e4b17023SJohn Marino 		  PAT_VAR_LOCATION_LOC (val) = const0_rtx;
3990e4b17023SJohn Marino 		  maybe_dump_rtl_for_gimple_stmt (stmt, last);
3991e4b17023SJohn Marino 		  PAT_VAR_LOCATION_LOC (val) = (rtx)value;
3992e4b17023SJohn Marino 		}
3993e4b17023SJohn Marino 
3994e4b17023SJohn Marino 	    delink_debug_stmt:
3995e4b17023SJohn Marino 	      /* In order not to generate too many debug temporaries,
3996e4b17023SJohn Marino 	         we delink all uses of debug statements we already expanded.
3997e4b17023SJohn Marino 		 Therefore debug statements between definition and real
3998e4b17023SJohn Marino 		 use of TERed SSA names will continue to use the SSA name,
3999e4b17023SJohn Marino 		 and not be replaced with debug temps.  */
4000e4b17023SJohn Marino 	      delink_stmt_imm_use (stmt);
4001e4b17023SJohn Marino 
4002e4b17023SJohn Marino 	      gsi = nsi;
4003e4b17023SJohn Marino 	      gsi_next (&nsi);
4004e4b17023SJohn Marino 	      if (gsi_end_p (nsi))
4005e4b17023SJohn Marino 		break;
4006e4b17023SJohn Marino 	      stmt = gsi_stmt (nsi);
4007e4b17023SJohn Marino 	      if (!gimple_debug_bind_p (stmt))
4008e4b17023SJohn Marino 		break;
4009e4b17023SJohn Marino 	    }
4010e4b17023SJohn Marino 
4011e4b17023SJohn Marino 	  set_curr_insn_source_location (sloc);
4012e4b17023SJohn Marino 	  set_curr_insn_block (sblock);
4013e4b17023SJohn Marino 	}
4014e4b17023SJohn Marino       else if (gimple_debug_source_bind_p (stmt))
4015e4b17023SJohn Marino 	{
4016e4b17023SJohn Marino 	  location_t sloc = get_curr_insn_source_location ();
4017e4b17023SJohn Marino 	  tree sblock = get_curr_insn_block ();
4018e4b17023SJohn Marino 	  tree var = gimple_debug_source_bind_get_var (stmt);
4019e4b17023SJohn Marino 	  tree value = gimple_debug_source_bind_get_value (stmt);
4020e4b17023SJohn Marino 	  rtx val;
4021e4b17023SJohn Marino 	  enum machine_mode mode;
4022e4b17023SJohn Marino 
4023e4b17023SJohn Marino 	  last = get_last_insn ();
4024e4b17023SJohn Marino 
4025e4b17023SJohn Marino 	  set_curr_insn_source_location (gimple_location (stmt));
4026e4b17023SJohn Marino 	  set_curr_insn_block (gimple_block (stmt));
4027e4b17023SJohn Marino 
4028e4b17023SJohn Marino 	  mode = DECL_MODE (var);
4029e4b17023SJohn Marino 
4030e4b17023SJohn Marino 	  val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value,
4031e4b17023SJohn Marino 				      VAR_INIT_STATUS_UNINITIALIZED);
4032e4b17023SJohn Marino 
4033e4b17023SJohn Marino 	  emit_debug_insn (val);
4034e4b17023SJohn Marino 
4035e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
4036e4b17023SJohn Marino 	    {
4037e4b17023SJohn Marino 	      /* We can't dump the insn with a TREE where an RTX
4038e4b17023SJohn Marino 		 is expected.  */
4039e4b17023SJohn Marino 	      PAT_VAR_LOCATION_LOC (val) = const0_rtx;
4040e4b17023SJohn Marino 	      maybe_dump_rtl_for_gimple_stmt (stmt, last);
4041e4b17023SJohn Marino 	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
4042e4b17023SJohn Marino 	    }
4043e4b17023SJohn Marino 
4044e4b17023SJohn Marino 	  set_curr_insn_source_location (sloc);
4045e4b17023SJohn Marino 	  set_curr_insn_block (sblock);
4046e4b17023SJohn Marino 	}
4047e4b17023SJohn Marino       else
4048e4b17023SJohn Marino 	{
4049e4b17023SJohn Marino 	  if (is_gimple_call (stmt) && gimple_call_tail_p (stmt))
4050e4b17023SJohn Marino 	    {
4051e4b17023SJohn Marino 	      bool can_fallthru;
4052e4b17023SJohn Marino 	      new_bb = expand_gimple_tailcall (bb, stmt, &can_fallthru);
4053e4b17023SJohn Marino 	      if (new_bb)
4054e4b17023SJohn Marino 		{
4055e4b17023SJohn Marino 		  if (can_fallthru)
4056e4b17023SJohn Marino 		    bb = new_bb;
4057e4b17023SJohn Marino 		  else
4058e4b17023SJohn Marino 		    return new_bb;
4059e4b17023SJohn Marino 		}
4060e4b17023SJohn Marino 	    }
4061e4b17023SJohn Marino 	  else
4062e4b17023SJohn Marino 	    {
4063e4b17023SJohn Marino 	      def_operand_p def_p;
4064e4b17023SJohn Marino 	      def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
4065e4b17023SJohn Marino 
4066e4b17023SJohn Marino 	      if (def_p != NULL)
4067e4b17023SJohn Marino 		{
4068e4b17023SJohn Marino 		  /* Ignore this stmt if it is in the list of
4069e4b17023SJohn Marino 		     replaceable expressions.  */
4070e4b17023SJohn Marino 		  if (SA.values
4071e4b17023SJohn Marino 		      && bitmap_bit_p (SA.values,
4072e4b17023SJohn Marino 				       SSA_NAME_VERSION (DEF_FROM_PTR (def_p))))
4073e4b17023SJohn Marino 		    continue;
4074e4b17023SJohn Marino 		}
4075e4b17023SJohn Marino 	      last = expand_gimple_stmt (stmt);
4076e4b17023SJohn Marino 	      maybe_dump_rtl_for_gimple_stmt (stmt, last);
4077e4b17023SJohn Marino 	    }
4078e4b17023SJohn Marino 	}
4079e4b17023SJohn Marino     }
4080e4b17023SJohn Marino 
4081e4b17023SJohn Marino   currently_expanding_gimple_stmt = NULL;
4082e4b17023SJohn Marino 
4083e4b17023SJohn Marino   /* Expand implicit goto and convert goto_locus.  */
4084e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, bb->succs)
4085e4b17023SJohn Marino     {
4086e4b17023SJohn Marino       if (e->goto_locus && e->goto_block)
4087e4b17023SJohn Marino 	{
4088e4b17023SJohn Marino 	  set_curr_insn_source_location (e->goto_locus);
4089e4b17023SJohn Marino 	  set_curr_insn_block (e->goto_block);
4090e4b17023SJohn Marino 	  e->goto_locus = curr_insn_locator ();
4091e4b17023SJohn Marino 	}
4092e4b17023SJohn Marino       e->goto_block = NULL;
4093e4b17023SJohn Marino       if ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
4094e4b17023SJohn Marino 	{
4095e4b17023SJohn Marino 	  emit_jump (label_rtx_for_bb (e->dest));
4096e4b17023SJohn Marino 	  e->flags &= ~EDGE_FALLTHRU;
4097e4b17023SJohn Marino 	}
4098e4b17023SJohn Marino     }
4099e4b17023SJohn Marino 
4100e4b17023SJohn Marino   /* Expanded RTL can create a jump in the last instruction of block.
4101e4b17023SJohn Marino      This later might be assumed to be a jump to successor and break edge insertion.
4102e4b17023SJohn Marino      We need to insert dummy move to prevent this. PR41440. */
4103e4b17023SJohn Marino   if (single_succ_p (bb)
4104e4b17023SJohn Marino       && (single_succ_edge (bb)->flags & EDGE_FALLTHRU)
4105e4b17023SJohn Marino       && (last = get_last_insn ())
4106e4b17023SJohn Marino       && JUMP_P (last))
4107e4b17023SJohn Marino     {
4108e4b17023SJohn Marino       rtx dummy = gen_reg_rtx (SImode);
4109e4b17023SJohn Marino       emit_insn_after_noloc (gen_move_insn (dummy, dummy), last, NULL);
4110e4b17023SJohn Marino     }
4111e4b17023SJohn Marino 
4112e4b17023SJohn Marino   do_pending_stack_adjust ();
4113e4b17023SJohn Marino 
4114e4b17023SJohn Marino   /* Find the block tail.  The last insn in the block is the insn
4115e4b17023SJohn Marino      before a barrier and/or table jump insn.  */
4116e4b17023SJohn Marino   last = get_last_insn ();
4117e4b17023SJohn Marino   if (BARRIER_P (last))
4118e4b17023SJohn Marino     last = PREV_INSN (last);
4119e4b17023SJohn Marino   if (JUMP_TABLE_DATA_P (last))
4120e4b17023SJohn Marino     last = PREV_INSN (PREV_INSN (last));
4121e4b17023SJohn Marino   BB_END (bb) = last;
4122e4b17023SJohn Marino 
4123e4b17023SJohn Marino   update_bb_for_insn (bb);
4124e4b17023SJohn Marino 
4125e4b17023SJohn Marino   return bb;
4126e4b17023SJohn Marino }
4127e4b17023SJohn Marino 
4128e4b17023SJohn Marino 
4129e4b17023SJohn Marino /* Create a basic block for initialization code.  */
4130e4b17023SJohn Marino 
4131e4b17023SJohn Marino static basic_block
construct_init_block(void)4132e4b17023SJohn Marino construct_init_block (void)
4133e4b17023SJohn Marino {
4134e4b17023SJohn Marino   basic_block init_block, first_block;
4135e4b17023SJohn Marino   edge e = NULL;
4136e4b17023SJohn Marino   int flags;
4137e4b17023SJohn Marino 
4138e4b17023SJohn Marino   /* Multiple entry points not supported yet.  */
4139e4b17023SJohn Marino   gcc_assert (EDGE_COUNT (ENTRY_BLOCK_PTR->succs) == 1);
4140e4b17023SJohn Marino   init_rtl_bb_info (ENTRY_BLOCK_PTR);
4141e4b17023SJohn Marino   init_rtl_bb_info (EXIT_BLOCK_PTR);
4142e4b17023SJohn Marino   ENTRY_BLOCK_PTR->flags |= BB_RTL;
4143e4b17023SJohn Marino   EXIT_BLOCK_PTR->flags |= BB_RTL;
4144e4b17023SJohn Marino 
4145e4b17023SJohn Marino   e = EDGE_SUCC (ENTRY_BLOCK_PTR, 0);
4146e4b17023SJohn Marino 
4147e4b17023SJohn Marino   /* When entry edge points to first basic block, we don't need jump,
4148e4b17023SJohn Marino      otherwise we have to jump into proper target.  */
4149e4b17023SJohn Marino   if (e && e->dest != ENTRY_BLOCK_PTR->next_bb)
4150e4b17023SJohn Marino     {
4151e4b17023SJohn Marino       tree label = gimple_block_label (e->dest);
4152e4b17023SJohn Marino 
4153e4b17023SJohn Marino       emit_jump (label_rtx (label));
4154e4b17023SJohn Marino       flags = 0;
4155e4b17023SJohn Marino     }
4156e4b17023SJohn Marino   else
4157e4b17023SJohn Marino     flags = EDGE_FALLTHRU;
4158e4b17023SJohn Marino 
4159e4b17023SJohn Marino   init_block = create_basic_block (NEXT_INSN (get_insns ()),
4160e4b17023SJohn Marino 				   get_last_insn (),
4161e4b17023SJohn Marino 				   ENTRY_BLOCK_PTR);
4162e4b17023SJohn Marino   init_block->frequency = ENTRY_BLOCK_PTR->frequency;
4163e4b17023SJohn Marino   init_block->count = ENTRY_BLOCK_PTR->count;
4164e4b17023SJohn Marino   if (e)
4165e4b17023SJohn Marino     {
4166e4b17023SJohn Marino       first_block = e->dest;
4167e4b17023SJohn Marino       redirect_edge_succ (e, init_block);
4168e4b17023SJohn Marino       e = make_edge (init_block, first_block, flags);
4169e4b17023SJohn Marino     }
4170e4b17023SJohn Marino   else
4171e4b17023SJohn Marino     e = make_edge (init_block, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
4172e4b17023SJohn Marino   e->probability = REG_BR_PROB_BASE;
4173e4b17023SJohn Marino   e->count = ENTRY_BLOCK_PTR->count;
4174e4b17023SJohn Marino 
4175e4b17023SJohn Marino   update_bb_for_insn (init_block);
4176e4b17023SJohn Marino   return init_block;
4177e4b17023SJohn Marino }
4178e4b17023SJohn Marino 
4179e4b17023SJohn Marino /* For each lexical block, set BLOCK_NUMBER to the depth at which it is
4180e4b17023SJohn Marino    found in the block tree.  */
4181e4b17023SJohn Marino 
4182e4b17023SJohn Marino static void
set_block_levels(tree block,int level)4183e4b17023SJohn Marino set_block_levels (tree block, int level)
4184e4b17023SJohn Marino {
4185e4b17023SJohn Marino   while (block)
4186e4b17023SJohn Marino     {
4187e4b17023SJohn Marino       BLOCK_NUMBER (block) = level;
4188e4b17023SJohn Marino       set_block_levels (BLOCK_SUBBLOCKS (block), level + 1);
4189e4b17023SJohn Marino       block = BLOCK_CHAIN (block);
4190e4b17023SJohn Marino     }
4191e4b17023SJohn Marino }
4192e4b17023SJohn Marino 
4193e4b17023SJohn Marino /* Create a block containing landing pads and similar stuff.  */
4194e4b17023SJohn Marino 
4195e4b17023SJohn Marino static void
construct_exit_block(void)4196e4b17023SJohn Marino construct_exit_block (void)
4197e4b17023SJohn Marino {
4198e4b17023SJohn Marino   rtx head = get_last_insn ();
4199e4b17023SJohn Marino   rtx end;
4200e4b17023SJohn Marino   basic_block exit_block;
4201e4b17023SJohn Marino   edge e, e2;
4202e4b17023SJohn Marino   unsigned ix;
4203e4b17023SJohn Marino   edge_iterator ei;
4204e4b17023SJohn Marino   rtx orig_end = BB_END (EXIT_BLOCK_PTR->prev_bb);
4205e4b17023SJohn Marino 
4206e4b17023SJohn Marino   rtl_profile_for_bb (EXIT_BLOCK_PTR);
4207e4b17023SJohn Marino 
4208e4b17023SJohn Marino   /* Make sure the locus is set to the end of the function, so that
4209e4b17023SJohn Marino      epilogue line numbers and warnings are set properly.  */
4210e4b17023SJohn Marino   if (cfun->function_end_locus != UNKNOWN_LOCATION)
4211e4b17023SJohn Marino     input_location = cfun->function_end_locus;
4212e4b17023SJohn Marino 
4213e4b17023SJohn Marino   /* The following insns belong to the top scope.  */
4214e4b17023SJohn Marino   set_curr_insn_block (DECL_INITIAL (current_function_decl));
4215e4b17023SJohn Marino 
4216e4b17023SJohn Marino   /* Generate rtl for function exit.  */
4217e4b17023SJohn Marino   expand_function_end ();
4218e4b17023SJohn Marino 
4219e4b17023SJohn Marino   end = get_last_insn ();
4220e4b17023SJohn Marino   if (head == end)
4221e4b17023SJohn Marino     return;
4222e4b17023SJohn Marino   /* While emitting the function end we could move end of the last basic block.
4223e4b17023SJohn Marino    */
4224e4b17023SJohn Marino   BB_END (EXIT_BLOCK_PTR->prev_bb) = orig_end;
4225e4b17023SJohn Marino   while (NEXT_INSN (head) && NOTE_P (NEXT_INSN (head)))
4226e4b17023SJohn Marino     head = NEXT_INSN (head);
4227e4b17023SJohn Marino   exit_block = create_basic_block (NEXT_INSN (head), end,
4228e4b17023SJohn Marino 				   EXIT_BLOCK_PTR->prev_bb);
4229e4b17023SJohn Marino   exit_block->frequency = EXIT_BLOCK_PTR->frequency;
4230e4b17023SJohn Marino   exit_block->count = EXIT_BLOCK_PTR->count;
4231e4b17023SJohn Marino 
4232e4b17023SJohn Marino   ix = 0;
4233e4b17023SJohn Marino   while (ix < EDGE_COUNT (EXIT_BLOCK_PTR->preds))
4234e4b17023SJohn Marino     {
4235e4b17023SJohn Marino       e = EDGE_PRED (EXIT_BLOCK_PTR, ix);
4236e4b17023SJohn Marino       if (!(e->flags & EDGE_ABNORMAL))
4237e4b17023SJohn Marino 	redirect_edge_succ (e, exit_block);
4238e4b17023SJohn Marino       else
4239e4b17023SJohn Marino 	ix++;
4240e4b17023SJohn Marino     }
4241e4b17023SJohn Marino 
4242e4b17023SJohn Marino   e = make_edge (exit_block, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
4243e4b17023SJohn Marino   e->probability = REG_BR_PROB_BASE;
4244e4b17023SJohn Marino   e->count = EXIT_BLOCK_PTR->count;
4245e4b17023SJohn Marino   FOR_EACH_EDGE (e2, ei, EXIT_BLOCK_PTR->preds)
4246e4b17023SJohn Marino     if (e2 != e)
4247e4b17023SJohn Marino       {
4248e4b17023SJohn Marino 	e->count -= e2->count;
4249e4b17023SJohn Marino 	exit_block->count -= e2->count;
4250e4b17023SJohn Marino 	exit_block->frequency -= EDGE_FREQUENCY (e2);
4251e4b17023SJohn Marino       }
4252e4b17023SJohn Marino   if (e->count < 0)
4253e4b17023SJohn Marino     e->count = 0;
4254e4b17023SJohn Marino   if (exit_block->count < 0)
4255e4b17023SJohn Marino     exit_block->count = 0;
4256e4b17023SJohn Marino   if (exit_block->frequency < 0)
4257e4b17023SJohn Marino     exit_block->frequency = 0;
4258e4b17023SJohn Marino   update_bb_for_insn (exit_block);
4259e4b17023SJohn Marino }
4260e4b17023SJohn Marino 
4261e4b17023SJohn Marino /* Helper function for discover_nonconstant_array_refs.
4262e4b17023SJohn Marino    Look for ARRAY_REF nodes with non-constant indexes and mark them
4263e4b17023SJohn Marino    addressable.  */
4264e4b17023SJohn Marino 
4265e4b17023SJohn Marino static tree
discover_nonconstant_array_refs_r(tree * tp,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)4266e4b17023SJohn Marino discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
4267e4b17023SJohn Marino 				   void *data ATTRIBUTE_UNUSED)
4268e4b17023SJohn Marino {
4269e4b17023SJohn Marino   tree t = *tp;
4270e4b17023SJohn Marino 
4271e4b17023SJohn Marino   if (IS_TYPE_OR_DECL_P (t))
4272e4b17023SJohn Marino     *walk_subtrees = 0;
4273e4b17023SJohn Marino   else if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
4274e4b17023SJohn Marino     {
4275e4b17023SJohn Marino       while (((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
4276e4b17023SJohn Marino 	      && is_gimple_min_invariant (TREE_OPERAND (t, 1))
4277e4b17023SJohn Marino 	      && (!TREE_OPERAND (t, 2)
4278e4b17023SJohn Marino 		  || is_gimple_min_invariant (TREE_OPERAND (t, 2))))
4279e4b17023SJohn Marino 	     || (TREE_CODE (t) == COMPONENT_REF
4280e4b17023SJohn Marino 		 && (!TREE_OPERAND (t,2)
4281e4b17023SJohn Marino 		     || is_gimple_min_invariant (TREE_OPERAND (t, 2))))
4282e4b17023SJohn Marino 	     || TREE_CODE (t) == BIT_FIELD_REF
4283e4b17023SJohn Marino 	     || TREE_CODE (t) == REALPART_EXPR
4284e4b17023SJohn Marino 	     || TREE_CODE (t) == IMAGPART_EXPR
4285e4b17023SJohn Marino 	     || TREE_CODE (t) == VIEW_CONVERT_EXPR
4286e4b17023SJohn Marino 	     || CONVERT_EXPR_P (t))
4287e4b17023SJohn Marino 	t = TREE_OPERAND (t, 0);
4288e4b17023SJohn Marino 
4289e4b17023SJohn Marino       if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
4290e4b17023SJohn Marino 	{
4291e4b17023SJohn Marino 	  t = get_base_address (t);
4292e4b17023SJohn Marino 	  if (t && DECL_P (t)
4293e4b17023SJohn Marino               && DECL_MODE (t) != BLKmode)
4294e4b17023SJohn Marino 	    TREE_ADDRESSABLE (t) = 1;
4295e4b17023SJohn Marino 	}
4296e4b17023SJohn Marino 
4297e4b17023SJohn Marino       *walk_subtrees = 0;
4298e4b17023SJohn Marino     }
4299e4b17023SJohn Marino 
4300e4b17023SJohn Marino   return NULL_TREE;
4301e4b17023SJohn Marino }
4302e4b17023SJohn Marino 
4303e4b17023SJohn Marino /* RTL expansion is not able to compile array references with variable
4304e4b17023SJohn Marino    offsets for arrays stored in single register.  Discover such
4305e4b17023SJohn Marino    expressions and mark variables as addressable to avoid this
4306e4b17023SJohn Marino    scenario.  */
4307e4b17023SJohn Marino 
4308e4b17023SJohn Marino static void
discover_nonconstant_array_refs(void)4309e4b17023SJohn Marino discover_nonconstant_array_refs (void)
4310e4b17023SJohn Marino {
4311e4b17023SJohn Marino   basic_block bb;
4312e4b17023SJohn Marino   gimple_stmt_iterator gsi;
4313e4b17023SJohn Marino 
4314e4b17023SJohn Marino   FOR_EACH_BB (bb)
4315e4b17023SJohn Marino     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4316e4b17023SJohn Marino       {
4317e4b17023SJohn Marino 	gimple stmt = gsi_stmt (gsi);
4318e4b17023SJohn Marino 	if (!is_gimple_debug (stmt))
4319e4b17023SJohn Marino 	  walk_gimple_op (stmt, discover_nonconstant_array_refs_r, NULL);
4320e4b17023SJohn Marino       }
4321e4b17023SJohn Marino }
4322e4b17023SJohn Marino 
4323e4b17023SJohn Marino /* This function sets crtl->args.internal_arg_pointer to a virtual
4324e4b17023SJohn Marino    register if DRAP is needed.  Local register allocator will replace
4325e4b17023SJohn Marino    virtual_incoming_args_rtx with the virtual register.  */
4326e4b17023SJohn Marino 
4327e4b17023SJohn Marino static void
expand_stack_alignment(void)4328e4b17023SJohn Marino expand_stack_alignment (void)
4329e4b17023SJohn Marino {
4330e4b17023SJohn Marino   rtx drap_rtx;
4331e4b17023SJohn Marino   unsigned int preferred_stack_boundary;
4332e4b17023SJohn Marino 
4333e4b17023SJohn Marino   if (! SUPPORTS_STACK_ALIGNMENT)
4334e4b17023SJohn Marino     return;
4335e4b17023SJohn Marino 
4336e4b17023SJohn Marino   if (cfun->calls_alloca
4337e4b17023SJohn Marino       || cfun->has_nonlocal_label
4338e4b17023SJohn Marino       || crtl->has_nonlocal_goto)
4339e4b17023SJohn Marino     crtl->need_drap = true;
4340e4b17023SJohn Marino 
4341e4b17023SJohn Marino   /* Call update_stack_boundary here again to update incoming stack
4342e4b17023SJohn Marino      boundary.  It may set incoming stack alignment to a different
4343e4b17023SJohn Marino      value after RTL expansion.  TARGET_FUNCTION_OK_FOR_SIBCALL may
4344e4b17023SJohn Marino      use the minimum incoming stack alignment to check if it is OK
4345e4b17023SJohn Marino      to perform sibcall optimization since sibcall optimization will
4346e4b17023SJohn Marino      only align the outgoing stack to incoming stack boundary.  */
4347e4b17023SJohn Marino   if (targetm.calls.update_stack_boundary)
4348e4b17023SJohn Marino     targetm.calls.update_stack_boundary ();
4349e4b17023SJohn Marino 
4350e4b17023SJohn Marino   /* The incoming stack frame has to be aligned at least at
4351e4b17023SJohn Marino      parm_stack_boundary.  */
4352e4b17023SJohn Marino   gcc_assert (crtl->parm_stack_boundary <= INCOMING_STACK_BOUNDARY);
4353e4b17023SJohn Marino 
4354e4b17023SJohn Marino   /* Update crtl->stack_alignment_estimated and use it later to align
4355e4b17023SJohn Marino      stack.  We check PREFERRED_STACK_BOUNDARY if there may be non-call
4356e4b17023SJohn Marino      exceptions since callgraph doesn't collect incoming stack alignment
4357e4b17023SJohn Marino      in this case.  */
4358e4b17023SJohn Marino   if (cfun->can_throw_non_call_exceptions
4359e4b17023SJohn Marino       && PREFERRED_STACK_BOUNDARY > crtl->preferred_stack_boundary)
4360e4b17023SJohn Marino     preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
4361e4b17023SJohn Marino   else
4362e4b17023SJohn Marino     preferred_stack_boundary = crtl->preferred_stack_boundary;
4363e4b17023SJohn Marino   if (preferred_stack_boundary > crtl->stack_alignment_estimated)
4364e4b17023SJohn Marino     crtl->stack_alignment_estimated = preferred_stack_boundary;
4365e4b17023SJohn Marino   if (preferred_stack_boundary > crtl->stack_alignment_needed)
4366e4b17023SJohn Marino     crtl->stack_alignment_needed = preferred_stack_boundary;
4367e4b17023SJohn Marino 
4368e4b17023SJohn Marino   gcc_assert (crtl->stack_alignment_needed
4369e4b17023SJohn Marino 	      <= crtl->stack_alignment_estimated);
4370e4b17023SJohn Marino 
4371e4b17023SJohn Marino   crtl->stack_realign_needed
4372e4b17023SJohn Marino     = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
4373e4b17023SJohn Marino   crtl->stack_realign_tried = crtl->stack_realign_needed;
4374e4b17023SJohn Marino 
4375e4b17023SJohn Marino   crtl->stack_realign_processed = true;
4376e4b17023SJohn Marino 
4377e4b17023SJohn Marino   /* Target has to redefine TARGET_GET_DRAP_RTX to support stack
4378e4b17023SJohn Marino      alignment.  */
4379e4b17023SJohn Marino   gcc_assert (targetm.calls.get_drap_rtx != NULL);
4380e4b17023SJohn Marino   drap_rtx = targetm.calls.get_drap_rtx ();
4381e4b17023SJohn Marino 
4382e4b17023SJohn Marino   /* stack_realign_drap and drap_rtx must match.  */
4383e4b17023SJohn Marino   gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL));
4384e4b17023SJohn Marino 
4385e4b17023SJohn Marino   /* Do nothing if NULL is returned, which means DRAP is not needed.  */
4386e4b17023SJohn Marino   if (NULL != drap_rtx)
4387e4b17023SJohn Marino     {
4388e4b17023SJohn Marino       crtl->args.internal_arg_pointer = drap_rtx;
4389e4b17023SJohn Marino 
4390e4b17023SJohn Marino       /* Call fixup_tail_calls to clean up REG_EQUIV note if DRAP is
4391e4b17023SJohn Marino          needed. */
4392e4b17023SJohn Marino       fixup_tail_calls ();
4393e4b17023SJohn Marino     }
4394e4b17023SJohn Marino }
4395e4b17023SJohn Marino 
4396e4b17023SJohn Marino /* Translate the intermediate representation contained in the CFG
4397e4b17023SJohn Marino    from GIMPLE trees to RTL.
4398e4b17023SJohn Marino 
4399e4b17023SJohn Marino    We do conversion per basic block and preserve/update the tree CFG.
4400e4b17023SJohn Marino    This implies we have to do some magic as the CFG can simultaneously
4401e4b17023SJohn Marino    consist of basic blocks containing RTL and GIMPLE trees.  This can
4402e4b17023SJohn Marino    confuse the CFG hooks, so be careful to not manipulate CFG during
4403e4b17023SJohn Marino    the expansion.  */
4404e4b17023SJohn Marino 
4405e4b17023SJohn Marino static unsigned int
gimple_expand_cfg(void)4406e4b17023SJohn Marino gimple_expand_cfg (void)
4407e4b17023SJohn Marino {
4408e4b17023SJohn Marino   basic_block bb, init_block;
4409e4b17023SJohn Marino   sbitmap blocks;
4410e4b17023SJohn Marino   edge_iterator ei;
4411e4b17023SJohn Marino   edge e;
4412e4b17023SJohn Marino   rtx var_seq;
4413e4b17023SJohn Marino   unsigned i;
4414e4b17023SJohn Marino 
4415e4b17023SJohn Marino   timevar_push (TV_OUT_OF_SSA);
4416e4b17023SJohn Marino   rewrite_out_of_ssa (&SA);
4417e4b17023SJohn Marino   timevar_pop (TV_OUT_OF_SSA);
4418e4b17023SJohn Marino   SA.partition_to_pseudo = (rtx *)xcalloc (SA.map->num_partitions,
4419e4b17023SJohn Marino 					   sizeof (rtx));
4420e4b17023SJohn Marino 
4421e4b17023SJohn Marino   /* Some backends want to know that we are expanding to RTL.  */
4422e4b17023SJohn Marino   currently_expanding_to_rtl = 1;
4423e4b17023SJohn Marino 
4424e4b17023SJohn Marino   rtl_profile_for_bb (ENTRY_BLOCK_PTR);
4425e4b17023SJohn Marino 
4426e4b17023SJohn Marino   insn_locators_alloc ();
4427e4b17023SJohn Marino   if (!DECL_IS_BUILTIN (current_function_decl))
4428e4b17023SJohn Marino     {
4429e4b17023SJohn Marino       /* Eventually, all FEs should explicitly set function_start_locus.  */
4430e4b17023SJohn Marino       if (cfun->function_start_locus == UNKNOWN_LOCATION)
4431e4b17023SJohn Marino        set_curr_insn_source_location
4432e4b17023SJohn Marino          (DECL_SOURCE_LOCATION (current_function_decl));
4433e4b17023SJohn Marino       else
4434e4b17023SJohn Marino        set_curr_insn_source_location (cfun->function_start_locus);
4435e4b17023SJohn Marino     }
4436e4b17023SJohn Marino   else
4437e4b17023SJohn Marino     set_curr_insn_source_location (UNKNOWN_LOCATION);
4438e4b17023SJohn Marino   set_curr_insn_block (DECL_INITIAL (current_function_decl));
4439e4b17023SJohn Marino   prologue_locator = curr_insn_locator ();
4440e4b17023SJohn Marino 
4441e4b17023SJohn Marino #ifdef INSN_SCHEDULING
4442e4b17023SJohn Marino   init_sched_attrs ();
4443e4b17023SJohn Marino #endif
4444e4b17023SJohn Marino 
4445e4b17023SJohn Marino   /* Make sure first insn is a note even if we don't want linenums.
4446e4b17023SJohn Marino      This makes sure the first insn will never be deleted.
4447e4b17023SJohn Marino      Also, final expects a note to appear there.  */
4448e4b17023SJohn Marino   emit_note (NOTE_INSN_DELETED);
4449e4b17023SJohn Marino 
4450e4b17023SJohn Marino   /* Mark arrays indexed with non-constant indices with TREE_ADDRESSABLE.  */
4451e4b17023SJohn Marino   discover_nonconstant_array_refs ();
4452e4b17023SJohn Marino 
4453e4b17023SJohn Marino   targetm.expand_to_rtl_hook ();
4454e4b17023SJohn Marino   crtl->stack_alignment_needed = STACK_BOUNDARY;
4455e4b17023SJohn Marino   crtl->max_used_stack_slot_alignment = STACK_BOUNDARY;
4456e4b17023SJohn Marino   crtl->stack_alignment_estimated = 0;
4457e4b17023SJohn Marino   crtl->preferred_stack_boundary = STACK_BOUNDARY;
4458e4b17023SJohn Marino   cfun->cfg->max_jumptable_ents = 0;
4459e4b17023SJohn Marino 
4460e4b17023SJohn Marino   /* Resovle the function section.  Some targets, like ARM EABI rely on knowledge
4461e4b17023SJohn Marino      of the function section at exapnsion time to predict distance of calls.  */
4462e4b17023SJohn Marino   resolve_unique_section (current_function_decl, 0, flag_function_sections);
4463e4b17023SJohn Marino 
4464e4b17023SJohn Marino   /* Expand the variables recorded during gimple lowering.  */
4465e4b17023SJohn Marino   timevar_push (TV_VAR_EXPAND);
4466e4b17023SJohn Marino   start_sequence ();
4467e4b17023SJohn Marino 
4468e4b17023SJohn Marino   expand_used_vars ();
4469e4b17023SJohn Marino 
4470e4b17023SJohn Marino   var_seq = get_insns ();
4471e4b17023SJohn Marino   end_sequence ();
4472e4b17023SJohn Marino   timevar_pop (TV_VAR_EXPAND);
4473e4b17023SJohn Marino 
4474e4b17023SJohn Marino   /* Honor stack protection warnings.  */
4475e4b17023SJohn Marino   if (warn_stack_protect)
4476e4b17023SJohn Marino     {
4477e4b17023SJohn Marino       if (cfun->calls_alloca)
4478e4b17023SJohn Marino 	warning (OPT_Wstack_protector,
4479e4b17023SJohn Marino 		 "stack protector not protecting local variables: "
4480e4b17023SJohn Marino                  "variable length buffer");
4481e4b17023SJohn Marino       if (has_short_buffer && !crtl->stack_protect_guard)
4482e4b17023SJohn Marino 	warning (OPT_Wstack_protector,
4483e4b17023SJohn Marino 		 "stack protector not protecting function: "
4484e4b17023SJohn Marino                  "all local arrays are less than %d bytes long",
4485e4b17023SJohn Marino 		 (int) PARAM_VALUE (PARAM_SSP_BUFFER_SIZE));
4486e4b17023SJohn Marino     }
4487e4b17023SJohn Marino 
4488e4b17023SJohn Marino   /* Set up parameters and prepare for return, for the function.  */
4489e4b17023SJohn Marino   expand_function_start (current_function_decl);
4490e4b17023SJohn Marino 
4491e4b17023SJohn Marino   /* If we emitted any instructions for setting up the variables,
4492e4b17023SJohn Marino      emit them before the FUNCTION_START note.  */
4493e4b17023SJohn Marino   if (var_seq)
4494e4b17023SJohn Marino     {
4495e4b17023SJohn Marino       emit_insn_before (var_seq, parm_birth_insn);
4496e4b17023SJohn Marino 
4497e4b17023SJohn Marino       /* In expand_function_end we'll insert the alloca save/restore
4498e4b17023SJohn Marino 	 before parm_birth_insn.  We've just insertted an alloca call.
4499e4b17023SJohn Marino 	 Adjust the pointer to match.  */
4500e4b17023SJohn Marino       parm_birth_insn = var_seq;
4501e4b17023SJohn Marino     }
4502e4b17023SJohn Marino 
4503e4b17023SJohn Marino   /* Now that we also have the parameter RTXs, copy them over to our
4504e4b17023SJohn Marino      partitions.  */
4505e4b17023SJohn Marino   for (i = 0; i < SA.map->num_partitions; i++)
4506e4b17023SJohn Marino     {
4507e4b17023SJohn Marino       tree var = SSA_NAME_VAR (partition_to_var (SA.map, i));
4508e4b17023SJohn Marino 
4509e4b17023SJohn Marino       if (TREE_CODE (var) != VAR_DECL
4510e4b17023SJohn Marino 	  && !SA.partition_to_pseudo[i])
4511e4b17023SJohn Marino 	SA.partition_to_pseudo[i] = DECL_RTL_IF_SET (var);
4512e4b17023SJohn Marino       gcc_assert (SA.partition_to_pseudo[i]);
4513e4b17023SJohn Marino 
4514e4b17023SJohn Marino       /* If this decl was marked as living in multiple places, reset
4515e4b17023SJohn Marino          this now to NULL.  */
4516e4b17023SJohn Marino       if (DECL_RTL_IF_SET (var) == pc_rtx)
4517e4b17023SJohn Marino 	SET_DECL_RTL (var, NULL);
4518e4b17023SJohn Marino 
4519e4b17023SJohn Marino       /* Some RTL parts really want to look at DECL_RTL(x) when x
4520e4b17023SJohn Marino          was a decl marked in REG_ATTR or MEM_ATTR.  We could use
4521e4b17023SJohn Marino 	 SET_DECL_RTL here making this available, but that would mean
4522e4b17023SJohn Marino 	 to select one of the potentially many RTLs for one DECL.  Instead
4523e4b17023SJohn Marino 	 of doing that we simply reset the MEM_EXPR of the RTL in question,
4524e4b17023SJohn Marino 	 then nobody can get at it and hence nobody can call DECL_RTL on it.  */
4525e4b17023SJohn Marino       if (!DECL_RTL_SET_P (var))
4526e4b17023SJohn Marino 	{
4527e4b17023SJohn Marino 	  if (MEM_P (SA.partition_to_pseudo[i]))
4528e4b17023SJohn Marino 	    set_mem_expr (SA.partition_to_pseudo[i], NULL);
4529e4b17023SJohn Marino 	}
4530e4b17023SJohn Marino     }
4531e4b17023SJohn Marino 
4532e4b17023SJohn Marino   /* If we have a class containing differently aligned pointers
4533e4b17023SJohn Marino      we need to merge those into the corresponding RTL pointer
4534e4b17023SJohn Marino      alignment.  */
4535e4b17023SJohn Marino   for (i = 1; i < num_ssa_names; i++)
4536e4b17023SJohn Marino     {
4537e4b17023SJohn Marino       tree name = ssa_name (i);
4538e4b17023SJohn Marino       int part;
4539e4b17023SJohn Marino       rtx r;
4540e4b17023SJohn Marino 
4541e4b17023SJohn Marino       if (!name
4542e4b17023SJohn Marino 	  || !POINTER_TYPE_P (TREE_TYPE (name))
4543e4b17023SJohn Marino 	  /* We might have generated new SSA names in
4544e4b17023SJohn Marino 	     update_alias_info_with_stack_vars.  They will have a NULL
4545e4b17023SJohn Marino 	     defining statements, and won't be part of the partitioning,
4546e4b17023SJohn Marino 	     so ignore those.  */
4547e4b17023SJohn Marino 	  || !SSA_NAME_DEF_STMT (name))
4548e4b17023SJohn Marino 	continue;
4549e4b17023SJohn Marino       part = var_to_partition (SA.map, name);
4550e4b17023SJohn Marino       if (part == NO_PARTITION)
4551e4b17023SJohn Marino 	continue;
4552e4b17023SJohn Marino       r = SA.partition_to_pseudo[part];
4553e4b17023SJohn Marino       if (REG_P (r))
4554e4b17023SJohn Marino 	mark_reg_pointer (r, get_pointer_alignment (name));
4555e4b17023SJohn Marino     }
4556e4b17023SJohn Marino 
4557e4b17023SJohn Marino   /* If this function is `main', emit a call to `__main'
4558e4b17023SJohn Marino      to run global initializers, etc.  */
4559e4b17023SJohn Marino   if (DECL_NAME (current_function_decl)
4560e4b17023SJohn Marino       && MAIN_NAME_P (DECL_NAME (current_function_decl))
4561e4b17023SJohn Marino       && DECL_FILE_SCOPE_P (current_function_decl))
4562e4b17023SJohn Marino     expand_main_function ();
4563e4b17023SJohn Marino 
4564e4b17023SJohn Marino   /* Initialize the stack_protect_guard field.  This must happen after the
4565e4b17023SJohn Marino      call to __main (if any) so that the external decl is initialized.  */
4566e4b17023SJohn Marino   if (crtl->stack_protect_guard)
4567e4b17023SJohn Marino     stack_protect_prologue ();
4568e4b17023SJohn Marino 
4569e4b17023SJohn Marino   expand_phi_nodes (&SA);
4570e4b17023SJohn Marino 
4571e4b17023SJohn Marino   /* Register rtl specific functions for cfg.  */
4572e4b17023SJohn Marino   rtl_register_cfg_hooks ();
4573e4b17023SJohn Marino 
4574e4b17023SJohn Marino   init_block = construct_init_block ();
4575e4b17023SJohn Marino 
4576e4b17023SJohn Marino   /* Clear EDGE_EXECUTABLE on the entry edge(s).  It is cleaned from the
4577e4b17023SJohn Marino      remaining edges later.  */
4578e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
4579e4b17023SJohn Marino     e->flags &= ~EDGE_EXECUTABLE;
4580e4b17023SJohn Marino 
4581e4b17023SJohn Marino   lab_rtx_for_bb = pointer_map_create ();
4582e4b17023SJohn Marino   FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR, next_bb)
4583e4b17023SJohn Marino     bb = expand_gimple_basic_block (bb);
4584e4b17023SJohn Marino 
4585e4b17023SJohn Marino   if (MAY_HAVE_DEBUG_INSNS)
4586e4b17023SJohn Marino     expand_debug_locations ();
4587e4b17023SJohn Marino 
4588e4b17023SJohn Marino   execute_free_datastructures ();
4589e4b17023SJohn Marino   timevar_push (TV_OUT_OF_SSA);
4590e4b17023SJohn Marino   finish_out_of_ssa (&SA);
4591e4b17023SJohn Marino   timevar_pop (TV_OUT_OF_SSA);
4592e4b17023SJohn Marino 
4593e4b17023SJohn Marino   timevar_push (TV_POST_EXPAND);
4594e4b17023SJohn Marino   /* We are no longer in SSA form.  */
4595e4b17023SJohn Marino   cfun->gimple_df->in_ssa_p = false;
4596e4b17023SJohn Marino 
4597e4b17023SJohn Marino   /* Expansion is used by optimization passes too, set maybe_hot_insn_p
4598e4b17023SJohn Marino      conservatively to true until they are all profile aware.  */
4599e4b17023SJohn Marino   pointer_map_destroy (lab_rtx_for_bb);
4600e4b17023SJohn Marino   free_histograms ();
4601e4b17023SJohn Marino 
4602e4b17023SJohn Marino   construct_exit_block ();
4603e4b17023SJohn Marino   set_curr_insn_block (DECL_INITIAL (current_function_decl));
4604e4b17023SJohn Marino   insn_locators_finalize ();
4605e4b17023SJohn Marino 
4606e4b17023SJohn Marino   /* Zap the tree EH table.  */
4607e4b17023SJohn Marino   set_eh_throw_stmt_table (cfun, NULL);
4608e4b17023SJohn Marino 
4609e4b17023SJohn Marino   /* We need JUMP_LABEL be set in order to redirect jumps, and hence
4610e4b17023SJohn Marino      split edges which edge insertions might do.  */
4611e4b17023SJohn Marino   rebuild_jump_labels (get_insns ());
4612e4b17023SJohn Marino 
4613e4b17023SJohn Marino   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
4614e4b17023SJohn Marino     {
4615e4b17023SJohn Marino       edge e;
4616e4b17023SJohn Marino       edge_iterator ei;
4617e4b17023SJohn Marino       for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
4618e4b17023SJohn Marino 	{
4619e4b17023SJohn Marino 	  if (e->insns.r)
4620e4b17023SJohn Marino 	    {
4621e4b17023SJohn Marino 	      rebuild_jump_labels_chain (e->insns.r);
4622e4b17023SJohn Marino 	      /* Avoid putting insns before parm_birth_insn.  */
4623e4b17023SJohn Marino 	      if (e->src == ENTRY_BLOCK_PTR
4624e4b17023SJohn Marino 		  && single_succ_p (ENTRY_BLOCK_PTR)
4625e4b17023SJohn Marino 		  && parm_birth_insn)
4626e4b17023SJohn Marino 		{
4627e4b17023SJohn Marino 		  rtx insns = e->insns.r;
4628e4b17023SJohn Marino 		  e->insns.r = NULL_RTX;
4629e4b17023SJohn Marino 		  emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
4630e4b17023SJohn Marino 		}
4631e4b17023SJohn Marino 	      else
4632e4b17023SJohn Marino 		commit_one_edge_insertion (e);
4633e4b17023SJohn Marino 	    }
4634e4b17023SJohn Marino 	  else
4635e4b17023SJohn Marino 	    ei_next (&ei);
4636e4b17023SJohn Marino 	}
4637e4b17023SJohn Marino     }
4638e4b17023SJohn Marino 
4639e4b17023SJohn Marino   /* We're done expanding trees to RTL.  */
4640e4b17023SJohn Marino   currently_expanding_to_rtl = 0;
4641e4b17023SJohn Marino 
4642e4b17023SJohn Marino   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR, next_bb)
4643e4b17023SJohn Marino     {
4644e4b17023SJohn Marino       edge e;
4645e4b17023SJohn Marino       edge_iterator ei;
4646e4b17023SJohn Marino       for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
4647e4b17023SJohn Marino 	{
4648e4b17023SJohn Marino 	  /* Clear EDGE_EXECUTABLE.  This flag is never used in the backend.  */
4649e4b17023SJohn Marino 	  e->flags &= ~EDGE_EXECUTABLE;
4650e4b17023SJohn Marino 
4651e4b17023SJohn Marino 	  /* At the moment not all abnormal edges match the RTL
4652e4b17023SJohn Marino 	     representation.  It is safe to remove them here as
4653e4b17023SJohn Marino 	     find_many_sub_basic_blocks will rediscover them.
4654e4b17023SJohn Marino 	     In the future we should get this fixed properly.  */
4655e4b17023SJohn Marino 	  if ((e->flags & EDGE_ABNORMAL)
4656e4b17023SJohn Marino 	      && !(e->flags & EDGE_SIBCALL))
4657e4b17023SJohn Marino 	    remove_edge (e);
4658e4b17023SJohn Marino 	  else
4659e4b17023SJohn Marino 	    ei_next (&ei);
4660e4b17023SJohn Marino 	}
4661e4b17023SJohn Marino     }
4662e4b17023SJohn Marino 
4663e4b17023SJohn Marino   blocks = sbitmap_alloc (last_basic_block);
4664e4b17023SJohn Marino   sbitmap_ones (blocks);
4665e4b17023SJohn Marino   find_many_sub_basic_blocks (blocks);
4666e4b17023SJohn Marino   sbitmap_free (blocks);
4667e4b17023SJohn Marino   purge_all_dead_edges ();
4668e4b17023SJohn Marino 
4669e4b17023SJohn Marino   compact_blocks ();
4670e4b17023SJohn Marino 
4671e4b17023SJohn Marino   expand_stack_alignment ();
4672e4b17023SJohn Marino 
4673e4b17023SJohn Marino #ifdef ENABLE_CHECKING
4674e4b17023SJohn Marino   verify_flow_info ();
4675e4b17023SJohn Marino #endif
4676e4b17023SJohn Marino 
4677e4b17023SJohn Marino   /* There's no need to defer outputting this function any more; we
4678e4b17023SJohn Marino      know we want to output it.  */
4679e4b17023SJohn Marino   DECL_DEFER_OUTPUT (current_function_decl) = 0;
4680e4b17023SJohn Marino 
4681e4b17023SJohn Marino   /* Now that we're done expanding trees to RTL, we shouldn't have any
4682e4b17023SJohn Marino      more CONCATs anywhere.  */
4683e4b17023SJohn Marino   generating_concat_p = 0;
4684e4b17023SJohn Marino 
4685e4b17023SJohn Marino   if (dump_file)
4686e4b17023SJohn Marino     {
4687e4b17023SJohn Marino       fprintf (dump_file,
4688e4b17023SJohn Marino 	       "\n\n;;\n;; Full RTL generated for this function:\n;;\n");
4689e4b17023SJohn Marino       /* And the pass manager will dump RTL for us.  */
4690e4b17023SJohn Marino     }
4691e4b17023SJohn Marino 
4692e4b17023SJohn Marino   /* If we're emitting a nested function, make sure its parent gets
4693e4b17023SJohn Marino      emitted as well.  Doing otherwise confuses debug info.  */
4694e4b17023SJohn Marino   {
4695e4b17023SJohn Marino     tree parent;
4696e4b17023SJohn Marino     for (parent = DECL_CONTEXT (current_function_decl);
4697e4b17023SJohn Marino 	 parent != NULL_TREE;
4698e4b17023SJohn Marino 	 parent = get_containing_scope (parent))
4699e4b17023SJohn Marino       if (TREE_CODE (parent) == FUNCTION_DECL)
4700e4b17023SJohn Marino 	TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1;
4701e4b17023SJohn Marino   }
4702e4b17023SJohn Marino 
4703e4b17023SJohn Marino   /* We are now committed to emitting code for this function.  Do any
4704e4b17023SJohn Marino      preparation, such as emitting abstract debug info for the inline
4705e4b17023SJohn Marino      before it gets mangled by optimization.  */
4706e4b17023SJohn Marino   if (cgraph_function_possibly_inlined_p (current_function_decl))
4707e4b17023SJohn Marino     (*debug_hooks->outlining_inline_function) (current_function_decl);
4708e4b17023SJohn Marino 
4709e4b17023SJohn Marino   TREE_ASM_WRITTEN (current_function_decl) = 1;
4710e4b17023SJohn Marino 
4711e4b17023SJohn Marino   /* After expanding, the return labels are no longer needed. */
4712e4b17023SJohn Marino   return_label = NULL;
4713e4b17023SJohn Marino   naked_return_label = NULL;
4714e4b17023SJohn Marino 
4715e4b17023SJohn Marino   /* After expanding, the tm_restart map is no longer needed.  */
4716e4b17023SJohn Marino   if (cfun->gimple_df->tm_restart)
4717e4b17023SJohn Marino     {
4718e4b17023SJohn Marino       htab_delete (cfun->gimple_df->tm_restart);
4719e4b17023SJohn Marino       cfun->gimple_df->tm_restart = NULL;
4720e4b17023SJohn Marino     }
4721e4b17023SJohn Marino 
4722e4b17023SJohn Marino   /* Tag the blocks with a depth number so that change_scope can find
4723e4b17023SJohn Marino      the common parent easily.  */
4724e4b17023SJohn Marino   set_block_levels (DECL_INITIAL (cfun->decl), 0);
4725e4b17023SJohn Marino   default_rtl_profile ();
4726e4b17023SJohn Marino   timevar_pop (TV_POST_EXPAND);
4727e4b17023SJohn Marino   return 0;
4728e4b17023SJohn Marino }
4729e4b17023SJohn Marino 
4730e4b17023SJohn Marino struct rtl_opt_pass pass_expand =
4731e4b17023SJohn Marino {
4732e4b17023SJohn Marino  {
4733e4b17023SJohn Marino   RTL_PASS,
4734e4b17023SJohn Marino   "expand",				/* name */
4735e4b17023SJohn Marino   NULL,                                 /* gate */
4736e4b17023SJohn Marino   gimple_expand_cfg,			/* execute */
4737e4b17023SJohn Marino   NULL,                                 /* sub */
4738e4b17023SJohn Marino   NULL,                                 /* next */
4739e4b17023SJohn Marino   0,                                    /* static_pass_number */
4740e4b17023SJohn Marino   TV_EXPAND,				/* tv_id */
4741e4b17023SJohn Marino   PROP_ssa | PROP_gimple_leh | PROP_cfg
4742e4b17023SJohn Marino     | PROP_gimple_lcx,			/* properties_required */
4743e4b17023SJohn Marino   PROP_rtl,                             /* properties_provided */
4744e4b17023SJohn Marino   PROP_ssa | PROP_trees,		/* properties_destroyed */
4745e4b17023SJohn Marino   TODO_verify_ssa | TODO_verify_flow
4746e4b17023SJohn Marino     | TODO_verify_stmts,		/* todo_flags_start */
4747e4b17023SJohn Marino   TODO_ggc_collect			/* todo_flags_finish */
4748e4b17023SJohn Marino  }
4749e4b17023SJohn Marino };
4750