PIPS
identity_elimination.c
Go to the documentation of this file.
1 /*
2 
3  $Id: identity_elimination.c 23643 2021-03-10 09:42:49Z 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 #if defined(BUILDER_IDENTITY_ELIMINATION) || \
28  defined(BUILDER_IDENTITY_ELIMINATION_WITH_POINTS_TO)
29 
30 #ifdef HAVE_CONFIG_H
31  #include "pips_config.h"
32 #endif
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 
37 #include "genC.h"
38 #include "linear.h"
39 
40 #include "pipsdbm.h"
41 #include "misc.h"
42 
43 #include "ri.h"
44 #include "ri-util.h"
45 #include "prettyprint.h"
46 
47 #include "effects-generic.h" // used
48 #include "effects-simple.h" // expression_with_side_effect_p
49 #include "control.h" // module_reorder
50 
51 /*
52  * Identity elimination, done by Nelson LOSSING
53  * Pass : Identity elimination :
54  * We want to eliminate identity instruction like "x=x;", or "a[i]=a[i];"
55  * We need the effects to verify that there is no side effect in the affectation.
56  * We don't want to eliminate "a[i++]=a[i++];"
57  *
58  * This pass can eliminate some raising exception.
59  * For instance, with "p=p;", if p is an invalid memory cell an exception can be raise.
60  * After the identity elimination, this instruction will be eliminate, so no more exception can be raise.
61  *
62  * An enhancement can be make to consider pointer/array :
63  * int x, *p;
64  * p=&x;
65  * x=*p; //can be delete
66  * *p=x; //can be delete
67  * need effect for this
68  */
69 
70 
71 
72 //static bool is_assign_satement(statement
73 // print_statement(s);
74 // instruction i = statement_instruction(s);
75 // if (instruction_call_p(i)) {
76 // call c = instruction_call(i);
77 // if (call_intrinsic_p(c)) {
78 // entity e = call_function(c);
79 // return ENTITY_ASSIGN_P(e);
80 // }
81 // }
82 //
83 // return false;
84 //}
85 
86 /**
87  * remove identity statement like x=x, but conserve a[i++]=a[i++]
88  * \param s statement to consider
89  */
90 static void identity_statement_remove(statement s) {
92  ifdebug(5) {
93  pips_debug(5, "begin\n");
94  pips_debug(5, "study statement :\n");
95  print_statement(s);
96  }
97  if (instruction_call_p(i)) {
98  call c = instruction_call(i);
99  if (call_intrinsic_p(c)) {
100  entity e = call_function(c);
101  cons *pc = call_arguments(c);
102  if (ENTITY_ASSIGN_P(e)) {
103  pips_assert("2 args to assign", CDR(CDR(pc))==NIL);
104 
105  expression lhs = EXPRESSION(CAR(pc));
106  expression rhs = EXPRESSION(CAR(CDR(pc)));
107 
108  // - we want to determinate if lhs and rhs are the same expressions
109  // - we also need to be sure that there is no side effect in lhs, or rhs
110  // in fact only need to check side effect in lhs or rhs and not in the two expression
111  // because lhs and rhs have to be the same expressions
112  if (expression_equal_p(lhs, rhs) &&
113  //!expression_with_side_effect_p(lhs) &&
115  ) {
116  pips_debug(5, "The statement is deleted\n");
117  // Free old instruction
119 
120  // Replace statement with a continue, so that we keep label
126  }
127  }
128  }
129  }
130  pips_debug(5, "end\n");
131 }
132 
133 /**
134  * TODO
135  * remove identity statement like *p=x, or x=*p when p=&x
136  * \param s statement to consider
137  */
138 /*
139 static void identity_statement_remove_with_points_to(_UNUSED_ statement s) {
140 // instruction i = statement_instruction(s);
141 // if (instruction_call_p(i)) {
142 // call c = instruction_call(i);
143 // if (call_intrinsic_p(c)) {
144 // entity e = call_function(c);
145 // cons *pc = call_arguments(c);
146 // if (ENTITY_ASSIGN_P(e)) {
147 // print_statement(s);
148 //
149 // expression lhs = EXPRESSION(CAR(pc));
150 // expression rhs = EXPRESSION(CAR(CDR(pc)));
151 //
152 // pips_assert("2 args to assign", CDR(CDR(pc))==NIL);
153 //
154 // // TODO
155 // if (false
156 // ) {
157 // // Free old instruction
158 // free_instruction(statement_instruction(s));
159 //
160 // // Replace statement with a continue, so that we keep label && comments
161 // statement_instruction(s) = make_continue_instruction();
162 // }
163 // }
164 // }
165 // }
166 }
167 */
168 
169 /**
170  * generic_identity_elimination
171  * get the environment, dependencies and launch the elimination
172  * \param module_name module to work on
173  * \param use_points_to if we also consider pointer (*p=x, with p=&x)
174  */
175 static bool generic_identity_elimination(
176  const char* module_name,
177  bool use_points_to)
178 {
180  bool good_result_p = true;
181 
182  debug_on("IDENTITY_ELIMINATION_DEBUG_LEVEL");
183  pips_debug(1, "begin\n");
184 
185  //-- configure environment --//
187  // entity module = get_current_module_entity();
188 
190  db_get_memory_resource(DBR_CODE, module_name, true) );
192 
193  pips_assert("Statement should be OK before...",
195 
197 
198  //-- get dependencies --//
199  if(use_points_to) {
201  }
202 
204  db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true));
205 
206  //-- Make the job -- //
207  gen_recurse(module_statement, statement_domain, gen_true, identity_statement_remove);
208  if(use_points_to) {
209  //TODO
210  //gen_recurse(module_statement, statement_domain, gen_true, identity_statement_remove_with_points_to);
211  }
212 
213  /* Reorder the module, because some statements have been deleted.
214  Well, the order on the remaining statements should be the same,
215  but by reordering the statements, the number are consecutive. Just
216  for pretty print... :-) */
218 
219  pips_assert("Statement should be OK after...",
221 
222  //-- Save modified code to database --//
224 // DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, module_name,
225 // compute_callees(module_statement));
226 
231 
232  pips_debug(1, "end\n");
233  debug_off();
234 
235  return (good_result_p);
236 }
237 
238 /**
239  * PIPS pass
240  */
241 bool identity_elimination(const char* module_name)
242 {
243  return generic_identity_elimination(module_name, false);
244 }
245 
246 /**
247  * PIPS pass
248  * TODO Not implemented
249  */
251 {
252  pips_user_warning("identity_elimination_with_points_to not implemented, identity_elimination was done instead.");
253  return generic_identity_elimination(module_name, true);
254 }
255 
256 #endif // BUILDER_IDENTITY_ELIMINATION*
bool statement_consistent_p(statement p)
Definition: ri.c:2195
void free_instruction(instruction p)
Definition: ri.c:1118
static statement module_statement
Definition: alias_check.c:125
@ with_points_to
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void set_pointer_info_kind(pointer_info_val)
methods.c
bool expression_with_side_effect_p(expression)
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void free(void *)
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
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
#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_comments_p(const char *)
Definition: statement.c:107
void statement_remove_extensions(statement)
That's all folks.
Definition: statement.c:4263
#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_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
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
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_ASSIGN_P(e)
#define call_intrinsic_p(C)
#define empty_comments
Empty comments (i.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 expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
#define call_function(x)
Definition: ri.h:709
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define instruction_call_p(x)
Definition: ri.h:1527
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_call(x)
Definition: ri.h:1529
#define call_arguments(x)
Definition: ri.h:711
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
bool identity_elimination_with_points_to(const char *)
bool identity_elimination(const char *)
identity_elimination.c