xref: /NextBSD/contrib/gcc/tree-ssa-loop-ch.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
1 /* Loop header copying on trees.
2    Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "tm_p.h"
28 #include "hard-reg-set.h"
29 #include "basic-block.h"
30 #include "output.h"
31 #include "diagnostic.h"
32 #include "tree-flow.h"
33 #include "tree-dump.h"
34 #include "tree-pass.h"
35 #include "timevar.h"
36 #include "cfgloop.h"
37 #include "tree-inline.h"
38 #include "flags.h"
39 #include "tree-inline.h"
40 
41 /* Duplicates headers of loops if they are small enough, so that the statements
42    in the loop body are always executed when the loop is entered.  This
43    increases effectiveness of code motion optimizations, and reduces the need
44    for loop preconditioning.  */
45 
46 /* Check whether we should duplicate HEADER of LOOP.  At most *LIMIT
47    instructions should be duplicated, limit is decreased by the actual
48    amount.  */
49 
50 static bool
should_duplicate_loop_header_p(basic_block header,struct loop * loop,int * limit)51 should_duplicate_loop_header_p (basic_block header, struct loop *loop,
52 				int *limit)
53 {
54   block_stmt_iterator bsi;
55   tree last;
56 
57   /* Do not copy one block more than once (we do not really want to do
58      loop peeling here).  */
59   if (header->aux)
60     return false;
61 
62   gcc_assert (EDGE_COUNT (header->succs) > 0);
63   if (single_succ_p (header))
64     return false;
65   if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest)
66       && flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 1)->dest))
67     return false;
68 
69   /* If this is not the original loop header, we want it to have just
70      one predecessor in order to match the && pattern.  */
71   if (header != loop->header && !single_pred_p (header))
72     return false;
73 
74   last = last_stmt (header);
75   if (TREE_CODE (last) != COND_EXPR)
76     return false;
77 
78   /* Approximately copy the conditions that used to be used in jump.c --
79      at most 20 insns and no calls.  */
80   for (bsi = bsi_start (header); !bsi_end_p (bsi); bsi_next (&bsi))
81     {
82       last = bsi_stmt (bsi);
83 
84       if (TREE_CODE (last) == LABEL_EXPR)
85 	continue;
86 
87       if (get_call_expr_in (last))
88 	return false;
89 
90       *limit -= estimate_num_insns (last);
91       if (*limit < 0)
92 	return false;
93     }
94 
95   return true;
96 }
97 
98 /* Checks whether LOOP is a do-while style loop.  */
99 
100 static bool
do_while_loop_p(struct loop * loop)101 do_while_loop_p (struct loop *loop)
102 {
103   tree stmt = last_stmt (loop->latch);
104 
105   /* If the latch of the loop is not empty, it is not a do-while loop.  */
106   if (stmt
107       && TREE_CODE (stmt) != LABEL_EXPR)
108     return false;
109 
110   /* If the header contains just a condition, it is not a do-while loop.  */
111   stmt = last_and_only_stmt (loop->header);
112   if (stmt
113       && TREE_CODE (stmt) == COND_EXPR)
114     return false;
115 
116   return true;
117 }
118 
119 /* For all loops, copy the condition at the end of the loop body in front
120    of the loop.  This is beneficial since it increases efficiency of
121    code motion optimizations.  It also saves one jump on entry to the loop.  */
122 
123 static unsigned int
copy_loop_headers(void)124 copy_loop_headers (void)
125 {
126   struct loops *loops;
127   unsigned i;
128   struct loop *loop;
129   basic_block header;
130   edge exit, entry;
131   basic_block *bbs, *copied_bbs;
132   unsigned n_bbs;
133   unsigned bbs_size;
134 
135   loops = loop_optimizer_init (LOOPS_HAVE_PREHEADERS
136 			       | LOOPS_HAVE_SIMPLE_LATCHES);
137   if (!loops)
138     return 0;
139 
140 #ifdef ENABLE_CHECKING
141   verify_loop_structure (loops);
142 #endif
143 
144   bbs = XNEWVEC (basic_block, n_basic_blocks);
145   copied_bbs = XNEWVEC (basic_block, n_basic_blocks);
146   bbs_size = n_basic_blocks;
147 
148   for (i = 1; i < loops->num; i++)
149     {
150       /* Copy at most 20 insns.  */
151       int limit = 20;
152 
153       loop = loops->parray[i];
154       if (!loop)
155 	continue;
156       header = loop->header;
157 
158       /* If the loop is already a do-while style one (either because it was
159 	 written as such, or because jump threading transformed it into one),
160 	 we might be in fact peeling the first iteration of the loop.  This
161 	 in general is not a good idea.  */
162       if (do_while_loop_p (loop))
163 	continue;
164 
165       /* Iterate the header copying up to limit; this takes care of the cases
166 	 like while (a && b) {...}, where we want to have both of the conditions
167 	 copied.  TODO -- handle while (a || b) - like cases, by not requiring
168 	 the header to have just a single successor and copying up to
169 	 postdominator.  */
170 
171       exit = NULL;
172       n_bbs = 0;
173       while (should_duplicate_loop_header_p (header, loop, &limit))
174 	{
175 	  /* Find a successor of header that is inside a loop; i.e. the new
176 	     header after the condition is copied.  */
177 	  if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
178 	    exit = EDGE_SUCC (header, 0);
179 	  else
180 	    exit = EDGE_SUCC (header, 1);
181 	  bbs[n_bbs++] = header;
182 	  gcc_assert (bbs_size > n_bbs);
183 	  header = exit->dest;
184 	}
185 
186       if (!exit)
187 	continue;
188 
189       if (dump_file && (dump_flags & TDF_DETAILS))
190 	fprintf (dump_file,
191 		 "Duplicating header of the loop %d up to edge %d->%d.\n",
192 		 loop->num, exit->src->index, exit->dest->index);
193 
194       /* Ensure that the header will have just the latch as a predecessor
195 	 inside the loop.  */
196       if (!single_pred_p (exit->dest))
197 	exit = single_pred_edge (loop_split_edge_with (exit, NULL));
198 
199       entry = loop_preheader_edge (loop);
200 
201       if (!tree_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs))
202 	{
203 	  fprintf (dump_file, "Duplication failed.\n");
204 	  continue;
205 	}
206 
207       /* If the loop has the form "for (i = j; i < j + 10; i++)" then
208 	 this copying can introduce a case where we rely on undefined
209 	 signed overflow to eliminate the preheader condition, because
210 	 we assume that "j < j + 10" is true.  We don't want to warn
211 	 about that case for -Wstrict-overflow, because in general we
212 	 don't warn about overflow involving loops.  Prevent the
213 	 warning by setting TREE_NO_WARNING.  */
214       if (warn_strict_overflow > 0)
215 	{
216 	  unsigned int i;
217 
218 	  for (i = 0; i < n_bbs; ++i)
219 	    {
220 	      tree last;
221 
222 	      last = last_stmt (copied_bbs[i]);
223 	      if (TREE_CODE (last) == COND_EXPR)
224 		TREE_NO_WARNING (last) = 1;
225 	    }
226 	}
227 
228       /* Ensure that the latch and the preheader is simple (we know that they
229 	 are not now, since there was the loop exit condition.  */
230       loop_split_edge_with (loop_preheader_edge (loop), NULL);
231       loop_split_edge_with (loop_latch_edge (loop), NULL);
232     }
233 
234   free (bbs);
235   free (copied_bbs);
236 
237   loop_optimizer_finalize (loops);
238   return 0;
239 }
240 
241 static bool
gate_ch(void)242 gate_ch (void)
243 {
244   return flag_tree_ch != 0;
245 }
246 
247 struct tree_opt_pass pass_ch =
248 {
249   "ch",					/* name */
250   gate_ch,				/* gate */
251   copy_loop_headers,			/* execute */
252   NULL,					/* sub */
253   NULL,					/* next */
254   0,					/* static_pass_number */
255   TV_TREE_CH,				/* tv_id */
256   PROP_cfg | PROP_ssa,			/* properties_required */
257   0,					/* properties_provided */
258   0,					/* properties_destroyed */
259   0,					/* todo_flags_start */
260   TODO_cleanup_cfg | TODO_dump_func
261   | TODO_verify_ssa,			/* todo_flags_finish */
262   0					/* letter */
263 };
264