PIPS
trivial_test_elimination.c
Go to the documentation of this file.
1 /*
2 
3  $Id: trivial_test_elimination.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 
25 // do not compile unless required
26 #include "phases.h"
27 #ifdef BUILDER_SUPPRESS_TRIVIAL_TEST
28 
29 #ifdef HAVE_CONFIG_H
30  #include "pips_config.h"
31 #endif
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "genC.h"
37 #include "linear.h"
38 
39 #include "misc.h"
40 #include "pipsdbm.h"
41 
42 #include "ri.h"
43 #include "ri-util.h"
44 #include "prettyprint.h" // for debugging
45 
46 #include "text-util.h" // used
47 #include "control.h" // clean_up_sequences, module_reorder
48 
49 /* Statistiques parametres */
50 static int trivial_test_removed;
51 static int trivial_test_unstructured_removed;
52 
53 
54 /*
55  Afficher les résultats des statistiques de la Suppress Trivial Test.
56  */
57 static void
58 display_trivial_test_statistics()
59 {
60  int elimination_count = trivial_test_removed + trivial_test_unstructured_removed ;
61  if (elimination_count > 0) {
62  user_log("* %d trivial test part%s %s been discarded. *\n",
63  elimination_count,
64  elimination_count > 1 ? "s" : "",
65  elimination_count > 1 ? "have" : "has");
66  user_log("Structured trivial tests: %d\n" ,
67  trivial_test_removed);
68 
69  user_log("Unstructured trivial tests: %d\n" ,
70  trivial_test_unstructured_removed);
71  /* Display also the statistics about clean_up_sequences
72  that is called in suppress_trivial_test: */
74  }
75  else
76  pips_debug(8, "There is not any trivial test in this program !\n");
77 }
78 
79 
80 
81 /*
82  Determiner l'expression inverse de l'expression e.
83  */
84 static expression
85 MakeInvertExpression(expression e)
86 {
89 
90  if (logical_expression_p(e)) {
95  if (!ENDP(args)) {
96  e1 = EXPRESSION(CAR(args));
97  if (!ENDP(CDR(args)))
98  e2 = EXPRESSION(CAR(CDR(args)));
99  }
100 
101  if (relational_expression_p(e)) {
104  pips_debug(8, "The expression %s is a relational expression\n",
106 
107  if (normalized_linear_p(n1) && normalized_linear_p(n2)) {
108 
109  if (ENTITY_NON_EQUAL_P(op)) {
110  nc = eq_expression(e1, e2);
111  }
112  else if (ENTITY_EQUAL_P(op)) {
113  nc = ne_expression(e1, e2);
114  }
115  else if (ENTITY_GREATER_OR_EQUAL_P(op)) {
116  nc = lt_expression(e1, e2);
117  }
118  else if (ENTITY_LESS_OR_EQUAL_P(op)) {
119  nc = gt_expression(e1, e2);
120  }
121  else if (ENTITY_LESS_THAN_P(op)) {
122  nc = ge_expression(e1, e2);
123  }
124  else if (ENTITY_GREATER_THAN_P(op)) {
125  nc = le_expression(e1, e2);
126  }
127  }
128  }
129  else if (logical_operator_expression_p(e)) {
130  pips_debug(8, "The expression %s is a logical expression\n",
132 
133  if (ENTITY_NOT_P(op)) {
134  tmpc = copy_expression(e1);
135  }
136  else if (ENTITY_AND_P(op)) {
137  expression tmpc1 = MakeInvertExpression(e1);
138  expression tmpc2 = MakeInvertExpression(e2);
139  tmpc = or_expression(tmpc1, tmpc2);
140  }
141  else if (ENTITY_OR_P(op)) {
142  expression tmpc1 = MakeInvertExpression(e1);
143  expression tmpc2 = MakeInvertExpression(e2);
144  tmpc = and_expression(tmpc1, tmpc2);
145  }
146  else if (ENTITY_EQUIV_P(op)) {
147  // expression tmpc1 = MakeInvertExpression(e1);
148  // expression tmpc2 = MakeInvertExpression(e2);
150  }
151  else if (ENTITY_NON_EQUIV_P(op)) {
152  // expression tmpc1 = MakeInvertExpression(e1);
153  // expression tmpc2 = MakeInvertExpression(e2);
155  }
156 
157  if (true_expression_p(tmpc))
158  nc = make_false_expression();
159  else if (false_expression_p(tmpc))
160  nc = make_true_expression();
161  else
162  nc = copy_expression(tmpc);
163  }
164  }
165 
166  return (nc) ;
167 }
168 
169 
170 
171 /*
172  Construire une nouvelle conditionelle instruction à partir de la conditionelle instruction vide
173  du statement s dans le cas elle est bien structurée ("structured instruction").
174  La conditionelle instruction vient d'être crée sera remplacer l'ancienne dans s.
175  */
176 static void
177 trivial_test_deal_with_test(statement s)
178 {
180  test t = instruction_test(i);
181  expression cond = test_condition(t);
182  expression ncond = MakeInvertExpression(cond);
183 
184  test new = make_test(copy_expression(ncond),
188 
189  free_instruction(i);
190  trivial_test_removed++;
191 }
192 
193 
194 
195 /*
196  Cette fonction sera appelée dans le cas où la conditionelle instruction vide du statement s n'est
197  pas structurée ("unstructured instruction"). Donc, avant de la remplacer par une nouvelle conditionelle
198  instruction, il faut enlever tous les successeurs et predecesseurs correspondants de se control.
199  */
200 static void
201 trivial_test_deal_with_unstructured(persistant_statement_to_control m, statement s)
202 {
204  test t = instruction_test(i);
205  expression cond = test_condition(t);
206  expression ncond = MakeInvertExpression(cond);
207 
209  control ctrue = CONTROL(CAR(control_successors(c)));
210  // control false = CONTROL(CAR(CDR(control_successors(c))));
211 
212  // control tmp = copy_control(false);
213  // false = copy_control(ctrue);
214  // ctrue = copy_control(tmp);
215  // free_control(tmp);
216 
217  // update_control_lists(c, m);
218  // UPDATE_CONTROL(c, s, control_predecessors(c), control_successors(c));
219 
220  // statement new_ctrue = control_statement(false);
221 
222  // make new test with control
223  // test new = make_test(copy_expression(ncond),
224  // make_continue_statement(statement_label(new_ctrue)),
225  // copy_statement(new_ctrue),
226  // make_block_statement(NIL));
227 
228 
229  // make new test with test_false()
230 
231  test new = make_test(copy_expression(ncond),
234 
235  gen_remove(&control_successors(c), ctrue);
236  gen_remove(&control_predecessors(ctrue), c);
237 
239 
240  free_instruction(i);
241  trivial_test_unstructured_removed++;
242 }
243 
244 
245 
246 static void
247 trivial_test_statement_rewrite(statement s, persistant_statement_to_control m)
248 {
250  tag t = instruction_tag(i);
251 
252  switch(t) {
253  case is_instruction_test:
254  {
255  test t ;
256  statement strue ;
257 
258  debug(2, "trivial_test_statement_rewrite", "is_instruction_test\n", "\n");
259  ifdebug(9) {
260  print_statement(s);
261  }
262 
263  t = instruction_test(i) ;
264  strue = test_true(t) ;
265  if (empty_statement_or_continue_p(strue)) {
266  pips_debug(8,"The branch true of this test instruction is empty!\n");
268  pips_debug(8, "This instruction is unstructured instruction\n");
269  trivial_test_deal_with_unstructured(m, s);
270  }
271  else {
272  pips_debug(8, "This instruction is structured instruction\n");
273  trivial_test_deal_with_test(s);
274  }
275  }
276  break;
277  }
278  case is_instruction_call:
281  case is_instruction_loop:
283  break;
284  default:
285  pips_internal_error("Unexpected instruction tag %d", t);
286  break;
287  }
288 }
289 
290 
291 
293 {
295  return true;
296 }
297 
298 
299 
300 static void
301 suppress_trivial_test_statement(statement mod_stmt)
302 {
304 
307  statement_domain, gen_true, trivial_test_statement_rewrite, NULL);
309 }
310 
311 
312 
313 /*
314  * Trivial test elimination
315  * mod_name : MODule NAME, nom du programme Fortran
316  * mod_stmt : MODule STateMenT
317 
318  * Elimination des branches de conditionnelles vides du programme en simplifiant et améliorant des
319  expressions des tests logiques des conditionnelles dans le module mod_name.
320  */
321 bool suppress_trivial_test(const string mod_name)
322 {
323  statement mod_stmt;
325  mod_stmt= (statement) db_get_memory_resource(DBR_CODE, mod_name, true);
327  set_ordering_to_statement(mod_stmt);
328 
329  debug_on("TRIVIAL_TEST_DEBUG_LEVEL");
330 
331  ifdebug(1) {
332  debug(1,"trivial_test_elimination", "Begin for %s\n", mod_name);
333  pips_assert("Inconsistent statements ...", statement_consistent_p(mod_stmt));
334  }
335 
336  trivial_test_removed = 0 ;
337  trivial_test_unstructured_removed = 0;
338 
339  suppress_trivial_test_statement(mod_stmt);
340  display_trivial_test_statistics();
341 
342  debug_off();
343 
344  module_reorder(mod_stmt);
345 
346  DB_PUT_MEMORY_RESOURCE(DBR_CODE, mod_name, mod_stmt);
347 
351 
352  debug(1,"trivial_test_elimination", "End for %s\n", mod_name);
353 
354  ifdebug(1)
355  pips_assert("Inconsistent statements ...", statement_consistent_p(mod_stmt));
356 
357  return true;
358 }
359 
360 #endif // BUILDER_SUPPRESS_TRIVIAL_TEST
361 
362 
363 
void user_log(const char *format,...)
Definition: message.c:234
persistant_statement_to_control make_persistant_statement_to_control(void)
Definition: ri.c:1594
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
bool statement_consistent_p(statement p)
Definition: ri.c:2195
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
control apply_persistant_statement_to_control(persistant_statement_to_control f, statement k)
Definition: ri.c:1597
void free_instruction(instruction p)
Definition: ri.c:1118
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
bool bound_persistant_statement_to_control_p(persistant_statement_to_control f, statement k)
Definition: ri.c:1609
void extend_persistant_statement_to_control(persistant_statement_to_control f, statement k, control v)
Definition: ri.c:1603
void free_persistant_statement_to_control(persistant_statement_to_control p)
Definition: ri.c:1561
static bool store_mapping(control c, bottom_up_abc_context_p context)
void display_clean_up_sequences_statistics(void)
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#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
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
bool empty_statement_or_continue_p(statement)
Return true if the statement is an empty instruction block or a continue or a recursive combination o...
Definition: statement.c:474
#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
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
int tag
TAG.
Definition: newgen_types.h:92
#define true
Definition: newgen_types.h:81
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
string expression_to_string(expression e)
Definition: expression.c:77
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define ENTITY_OR_P(e)
#define ENTITY_AND_P(e)
#define ENTITY_NON_EQUAL_P(e)
#define ENTITY_EQUAL_P(e)
#define EQUIV_OPERATOR_NAME
#define ENTITY_LESS_THAN_P(e)
#define NORMALIZE_EXPRESSION(e)
#define gt_expression(e1, e2)
#define NON_EQUIV_OPERATOR_NAME
#define and_expression(e1, e2)
#define ENTITY_NOT_P(e)
#define binary_intrinsic_expression(name, e1, e2)
#define ne_expression(e1, e2)
#define ENTITY_GREATER_THAN_P(e)
#define ge_expression(e1, e2)
#define le_expression(e1, e2)
#define eq_expression(e1, e2)
#define ENTITY_NON_EQUIV_P(e)
#define ENTITY_LESS_OR_EQUAL_P(e)
#define ENTITY_GREATER_OR_EQUAL_P(e)
#define lt_expression(e1, e2)
#define or_expression(e1, e2)
#define ENTITY_EQUIV_P(e)
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool false_expression_p(expression e)
Definition: expression.c:1118
bool logical_operator_expression_p(expression e)
C xor is missing.
Definition: expression.c:573
bool true_expression_p(expression e)
Definition: expression.c:1113
bool logical_expression_p(expression e)
Definition: expression.c:610
expression make_false_expression()
Definition: expression.c:1108
bool relational_expression_p(expression e)
Definition: expression.c:587
expression make_true_expression()
Definition: expression.c:1103
#define normalized_linear_p(x)
Definition: ri.h:1779
#define call_function(x)
Definition: ri.h:709
#define control_predecessors(x)
Definition: ri.h:943
#define test_false(x)
Definition: ri.h:2837
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define control_domain
newgen_controlmap_domain_defined
Definition: ri.h:98
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define test_true(x)
Definition: ri.h:2835
#define syntax_call(x)
Definition: ri.h:2736
#define control_successors(x)
Definition: ri.h:945
#define test_condition(x)
Definition: ri.h:2833
#define statement_instruction(x)
Definition: ri.h:2458
#define call_arguments(x)
Definition: ri.h:711
#define control_statement(x)
Definition: ri.h:941
#define instruction_test(x)
Definition: ri.h:1517
#define expression_syntax(x)
Definition: ri.h:1247
return(s1)
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
bool suppress_trivial_test(const string)
trivial_test_elimination.c