PIPS
unreachable.c
Go to the documentation of this file.
1 /*
2 
3  $Id: unreachable.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /*
28  * Detection of unreachable code, from the control flow point of view.
29  */
30 
31 #include <stdio.h>
32 #include <string.h>
33 
34 #include "linear.h"
35 
36 #include "genC.h"
37 #include "misc.h"
38 #include "ri.h"
39 #include "ri-util.h"
40 
41 /******************************************************** REACHED STATEMENTS */
42 
43 /* A mapping to store if a given statement is reachable from the control
44  flow point of view: */
46 
47 
49 
50 #define reached_p(s) (bound_reached_p(s))
51 #define continued_p(s) (load_continued(s))
52 
53 static bool propagate(statement);
54 
55 #define check_recursion(s) \
56  do { \
57  if (reached_p(s)) { \
58  if (bound_continued_p(s)) { \
59  pips_debug(5, "Statement %p already seen, thus stop recursion.\n", s); \
60  return continued_p(s); /* already computed */ \
61  } \
62  else { \
63  pips_debug(5, "Statement %p marked as reached but the execution does not continue on afterwards.\n\tSo return FALSE.\n", s); \
64  return false; /* avoids an infinite recursion... */ \
65  } \
66  } \
67  else { \
68  pips_debug(5, "New statement %p marked as reached.\n", s); \
69  store_reached(s, true); \
70  } \
71  } while (false) /* Pattern to be able to use this macro like an instruction. */
72 
73 static bool
75 {
76  list lc = control_successors(c);
77  int len = gen_length(lc);
79  pips_assert("max 2 successors", len<=2);
80  pips_debug(1, "Entering control_propagate for control %p\n", c);
81 
82  /* If we already have dealt with the current control node, stop the
83  recursion: */
84  if (reached_p(s) && bound_continued_p(s)) {
85  /* already computed */
86  pips_debug(5, "Statement %p already seen, thus stop recursion.\n", s);
87  return continued_p(s);
88  } \
89  /* Investigate about the continuation status of the statement: */
90  bool continued = propagate(s);
91 
92  if (continued) {
93  /* Investigate the control successors only if the current one
94  continues afterwards */
95  if (len==2) {
96  bool ctrue, cfalse;
97  ctrue = control_propagate(CONTROL(CAR(lc)));
98  cfalse = control_propagate(CONTROL(CAR(CDR(lc))));
99  // Continue after the test only if at leat one branch goes on:
100  continued = ctrue || cfalse;
101  }
102  else if (len==1) {
103  control cn = CONTROL(CAR(lc));
104  if (cn!=c) continued = control_propagate(cn);
105  /* It seems like a fallacy here. It is not semantically different if
106  we have a cycle with more than 1 goto... It does not work for
107  irreductible graphs either but it is detected anyway now in
108  proagate(). RK */
109  else continued = false; /* 1 GO TO 1 */
110  }
111  }
112  pips_debug(1, "Ending control_propagate for control %p and statement %p returning continued %d\n",
113  c, s, continued);
114  // store_continued(control_statement(c), continued);
115  return continued;
116 }
117 
118 /* returns whether propagation is continued after s.
119  * (that is no STOP or infinite loop encountered ??? ).
120  * It is a MAY information. If there is no propagation, it
121  * is a MUST information.
122  */
123 static bool
125  bool continued = true;
126  instruction i;
127 
128  pips_assert("defined statement", !statement_undefined_p(s));
129  /* ifdebug(5) { */
130  /* pips_debug(1, "Dealing with statement %p\n", s); */
131  /* print_statement(s); */
132  /* } */
133 
134  check_recursion(s);
135 
136  i = statement_instruction(s);
137  switch (instruction_tag(i))
138  {
140  {
142  while (l && (continued=propagate(STATEMENT(CAR(l)))))
143  POP(l);
144  break;
145  }
146  case is_instruction_loop:
147  {
149  break;
150  }
152  {
153  /* Undecidable implies "propagate" by default */
155  break;
156  }
158  {
159  /* Undecidable implies "propagate" by default */
161  break;
162  }
163  case is_instruction_test:
164  {
165  test t = instruction_test(i);
166  bool ctrue, cfalse;
167  ctrue = propagate(test_true(t));
168  cfalse = propagate(test_false(t));
169  continued = ctrue || cfalse;
170  break;
171  }
173  {
176  // Investigate inside the unstructured control graph:
177  continued = control_propagate(c);
178  if (continued) {
179  /* If the unstructured is seen as going on, test if the exit node
180  as been marked as reachable */
182  if (!reached_p(exit))
183  /* Since the exit node is not reached, that means that there is
184  an infinite loop is the unstructured, so globally it is not
185  continued: */
186  continued = false;
187  }
188  break;
189  }
190  case is_instruction_call:
191  {
192  /* FI: not satisfying; interprocedural control effects required here */
195  break;
196  }
198  {
199  continued = true; /* FI: interprocedural exit possible:-( */
200  break;
201  }
203  {
204  pips_internal_error("Not implemented yet"); /* FI: undone by the controlizer? */
205  break;
206  }
207  case is_instruction_goto:
208  pips_internal_error("GOTO should have been eliminated by the controlizer");
209  break;
210  default:
211  pips_internal_error("unexpected instruction tag");
212  }
213 
214  pips_debug(1, "Continued for statement %p = %d\n", s, continued);
215  store_continued(s, continued);
216  return continued;
217 }
218 
219 
220 /***************************************************************** INTERFACE */
221 
222 /* Compute reachable infomation from the @param start statement. */
224  debug_on("REACHABLE_DEBUG_LEVEL");
225  init_reached();
226  init_continued();
227  propagate(start);
228  debug_off();
229 }
230 
231 /* Test if the given statement is reachable from some statements given at
232  init_reachable(start) */
233 bool
235 {
236  return reached_p(s);
237 }
238 
239 /* Test if the execution goes on after the given statement. For example it
240  is false after a "return" in C */
241 bool
243 {
244  if (bound_continued_p(s))
245  return continued_p(s);
246  else
247  return false;
248 }
249 
250 /* Remove reachability information about previously checked statements */
251 void
253 {
254  close_reached();
255  close_continued();
256 }
static char start[1024]
The name of the variable from which to start counting domain numbers.
Definition: genLisp.c:55
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
size_t gen_length(const list l)
Definition: list.c:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define exit(code)
Definition: misc-local.h:54
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define ENTITY_STOP_P(e)
#define ENTITY_EXIT_SYSTEM_P(e)
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define ENTITY_ABORT_SYSTEM_P(e)
#define loop_body(x)
Definition: ri.h:1644
#define call_function(x)
Definition: ri.h:709
#define instruction_loop(x)
Definition: ri.h:1520
#define test_false(x)
Definition: ri.h:2837
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_expression
Definition: ri.h:1478
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_multitest
Definition: ri.h:1476
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define instruction_sequence(x)
Definition: ri.h:1514
#define instruction_forloop(x)
Definition: ri.h:1538
#define control_successors(x)
Definition: ri.h:945
#define unstructured_exit(x)
Definition: ri.h:3006
#define instruction_whileloop(x)
Definition: ri.h:1523
#define whileloop_body(x)
Definition: ri.h:3162
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define control_statement(x)
Definition: ri.h:941
#define instruction_test(x)
Definition: ri.h:1517
#define statement_undefined_p(x)
Definition: ri.h:2420
#define forloop_body(x)
Definition: ri.h:1372
#define instruction_unstructured(x)
Definition: ri.h:1532
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
GENERIC_LOCAL_FUNCTION(directives, step_directives)
Copyright 2007, 2008, 2009 Alain Muller, Frederique Silber-Chaussumier.
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
bool statement_reachable_p(statement s)
Test if the given statement is reachable from some statements given at init_reachable(start)
Definition: unreachable.c:234
static bool propagate(statement)
returns whether propagation is continued after s.
Definition: unreachable.c:124
bool statement_continued_p(statement s)
Test if the execution goes on after the given statement.
Definition: unreachable.c:242
static bool control_propagate(control c)
Definition: unreachable.c:74
#define check_recursion(s)
Definition: unreachable.c:55
#define continued_p(s)
Definition: unreachable.c:51
void init_reachable(statement start)
Compute reachable infomation from the.
Definition: unreachable.c:223
void close_reachable(void)
Remove reachability information about previously checked statements.
Definition: unreachable.c:252
#define reached_p(s)
A mapping to store if a given statement is reachable from the control flow point of view:
Definition: unreachable.c:50