PIPS
norm_exp.c
Go to the documentation of this file.
1 /*
2 
3  $Id: norm_exp.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 /* -- norm_exp.c
28  *
29  * package atomizer : Alexis Platonoff, aout 91
30  * --
31  *
32  * Functions for the normalization of expressions.
33  *
34  * Before the atomization, all the expression of the Code are put
35  * in a normal form. This normal form gathers the NLCs
36  * variables in the innermost parenthesis with the constant term.
37  * The NLCs are sorted in order to have the innerloop counter in the
38  * inner parenthesis.
39  *
40  * Thus, the following expression:
41  * (4*S + ( NLC1 + ((T + 7) + 3*NLC2))) + C) + 8*NLC3
42  * is normalized in:
43  * 4*S + (T + (C + (8*NLC1 + (3*NLC2 + (NLC3 + 7)))))
44  *
45  * For more information about NLCs, see loop_normalize package.
46  */
47 /* #include "loop_normalize.h" */
48 #define NLC_PREFIX "NLC"
49 #define ENTITY_NLC_P(e) (strncmp(entity_local_name(e), NLC_PREFIX, 3) == 0)
50 
51 #include "local.h"
52 #include "prettyprint.h"
53 
54 /*============================================================================*/
55 /* void normal_expression_of_expression(expression exp): normalizes "exp".
56  *
57  * There are three cases:
58  * 1. "exp" is a call to an intrinsic or external function.
59  * 2. "exp" is a reference.
60  * 3. "exp" is a range
61  *
62  * In the case (1), if "exp" is linear (ie normalized), we call
63  * reconfig_expression(); it computes the normalization of "exp" with its
64  * Pvecteur. If "exp" is not integer linear, this function is called
65  * recursively upon the arguments of the call.
66  *
67  * In case (2), we call this function upon each of the indices of "exp".
68  *
69  * In case (3), we do nothing. Such a case may occur with a range argument in
70  * a call to a write or read procedure.
71  */
74 {
76 if(syntax_tag(sy) == is_syntax_call)
77  {
78  call c = syntax_call(sy);
79  if(! call_constant_p(c))
80  {
83  {
84  pips_debug(5, "Expression Linear : %s\n", expression_to_string(exp));
85 
87  }
88  else
89  {
90  list args = call_arguments(c);
91 
92  pips_debug(5, "Expression Complex : %s\n",
94 
95  for(; args != NIL; args = CDR(args))
97  }
99  }
100  }
101 else if(syntax_tag(sy) == is_syntax_reference)
102  {
104  list inds = reference_indices(ref);
105  for(; inds != NIL; inds = CDR(inds))
107  }
108 else if(syntax_tag(sy) == is_syntax_range)
109  {
110  pips_debug(6, "Expression Range : %s\n",
112  }
113 else
114  pips_internal_error("Bad expression tag");
115 }
116 
117 
118 
119 /*============================================================================*/
120 /* void normal_expression_of_statement(statement s): normalizes the
121  * expressions contained in "s".
122  */
124 statement s;
125 {
127 
128 debug(4, "normal_expression_of_statement", "begin STATEMENT\n");
129 
130 switch(instruction_tag(inst))
131  {
132  case is_instruction_block :
133  { list block = instruction_block(inst);
134  for(; block != NIL ; block = CDR(block))
136  break; }
137  case is_instruction_test :
138  { test t = instruction_test(inst);
142  break; }
143  case is_instruction_loop :
144  { loop l = instruction_loop(inst);
145  range lr = loop_range(l);
150  break; }
151  case is_instruction_call :
152  { call c = instruction_call(inst);
153  list args = call_arguments(c);
154 
155  debug(4, "normal_expression_of_statement", "Stmt CALL: %s\n",
157 
158  for(; args != NIL; args = CDR(args))
160  break; }
161  case is_instruction_goto : break;
164  break; }
165  default : pips_internal_error("Bad instruction tag");
166  }
167 debug(4, "normal_expression_of_statement", "end STATEMENT\n");
168 }
169 
170 
171 
172 /*============================================================================*/
173 /* void normal_expression_of_unstructured(unstructured u): normalizes the
174  * expressions of an unstructured instruction "u".
175  */
177 unstructured u;
178 {
179 list blocs = NIL;
180 
181 debug(3, "normal_expression_of_unstructured", "begin UNSTRUCTURED\n");
182 
184  unstructured_control( u ), blocs);
185 
186 gen_free_list(blocs);
187 
188 debug(3, "normal_expression_of_unstructured", "end UNSTRUCTURED\n");
189 }
190 
191 
192 
193 /*============================================================================*/
194 /* int get_nlc_number(entity nlc_ent): returns the number ending "nlc_ent"
195  * name.
196  * The local name is "NLC#", so we have to get the "#".
197  */
198 int get_nlc_number(nlc_ent)
199 entity nlc_ent;
200 {
201 const char* nlc_name = entity_local_name(nlc_ent);
202 const char* num = nlc_name+3;
203 
204 return(atoi(num));
205 }
206 
207 
208 
209 /*============================================================================*/
210 /* static Pvecteur config_vecteur(Pvecteur Vvar): returns a Pvecteur resulting
211  * of the configuration of the Pvecteur "Vvar".
212  *
213  * Firstly, we put into three different Pvecteurs the constant term, the NLCs
214  * variables and the others variables (not NLCs).
215  * The NLCs variables are ordered from the greater to the smaller number.
216  *
217  * Secondly, we concatenate these three Pvecteurs in the order:
218  * constant_term, nlc, not_nlc.
219  *
220  * For example, with Pvecteur:
221  * 2*I 3*NLC2 1*NLC1 4*T 7
222  * we could obtain:
223  * 7 3*NLC2 1*NLC1 4*T 2*I
224  */
226 Pvecteur Vvar;
227 {
228 Pvecteur Vnot_nlc, Vnlc, Vterm_cst, newV, Vc, Vaux;
229 
230 Vterm_cst = VECTEUR_NUL;
231 Vnlc = VECTEUR_NUL;
232 Vnot_nlc = VECTEUR_NUL;
233 for(Vc = Vvar; !VECTEUR_NUL_P(Vc); Vc = Vc->succ)
234  {
235  /* "Vc" is the constant term. */
236  if(term_cst(Vc))
237  Vterm_cst = vect_new(Vc->var, Vc->val);
238  else
239  {
240  entity var = (entity) Vc->var;
241  Pvecteur new_vect = vect_new(Vc->var, Vc->val);
242 
243  /* "Vc" is a NLC. */
244  if(ENTITY_NLC_P(var))
245  {
246  int num, crt_num = 0;
247 
248  if(VECTEUR_NUL_P(Vnlc))
249  Vnlc = new_vect;
250  else
251  {
252  num = get_nlc_number(var);
253 
254  crt_num = get_nlc_number((entity) Vnlc->var);
255  if(num > crt_num)
256  {
257  new_vect->succ = Vnlc;
258  Vnlc = new_vect;
259  }
260  else
261  {
262  bool not_fin = true;
263  Pvecteur Vs = Vnlc, Vp;
264  while(not_fin)
265  {
266  Vp = Vs;
267  Vs = Vs->succ;
268  if(!VECTEUR_NUL_P(Vs))
269  {
270  crt_num = get_nlc_number((entity) Vs->var);
271  if(num > crt_num)
272  {
273  new_vect->succ = Vs;
274  Vp->succ = new_vect;
275  not_fin = false;
276  }
277  }
278  else
279  {
280  Vp->succ = new_vect;
281  not_fin = false;
282  }
283  }
284  }
285  }
286  }
287 
288  /* "Vc" is not a NLC. */
289  else
290  {
291  new_vect->succ = Vnot_nlc;
292  Vnot_nlc = new_vect;
293  }
294  }
295  }
296 
297 newV = Vnot_nlc;
298 
299 if(!VECTEUR_NUL_P(Vnlc))
300  {
301  Vc = Vnlc;
302  while(!VECTEUR_NUL_P(Vc))
303  {
304  Vaux = Vc;
305  Vc = Vc->succ;
306  }
307  Vaux->succ = newV;
308  newV = Vnlc;
309  }
310 
311 if(!VECTEUR_NUL_P(Vterm_cst))
312  {
313  Vterm_cst->succ = newV;
314  newV = Vterm_cst;
315  }
316 
317 return(newV);
318 }
319 
320 
321 
322 /*============================================================================*/
323 /* void reconfig_expression(expression exp): "exp" is reordered so as to gather
324  * all the NLCs in the innermost parenthesis. More, the NLC of the inner loop
325  * is in the innermost parenthesis with the TCST (constant term).
326  * For example, if we have:
327  * (4*S + ( NLC1 + ((T + 7) + 3*NLC2))) + C) + 8*NLC3
328  * it is reordered in:
329  * 4*S + (T + (C + (8*NLC1 + (3*NLC2 + (NLC3 + 7)))))
330  *
331  * Called functions:
332  * _ Pvecteur_to_expression() : loop_normalize/utils.c
333  */
336 {
337 Pvecteur vect, new_vect;
340 expression new_exp;
341 
343  return;
345  return;
347  return;
348 
349 vect = (Pvecteur) normalized_linear(nor);
350 
351 /* We configurate the Pvecteur of "exp". */
352 new_vect = config_vecteur(vect);
353 
354 /* We build a new expression with the configurated Pvecteur. */
355 new_exp = Pvecteur_to_expression(new_vect);
356 
357 /* We change the syntax of "exp". */
358 if(new_exp != expression_undefined)
360 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static int num
Definition: bourdoncle.c:137
#define call_constant_p(C)
Definition: flint_check.c:51
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
#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
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#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_internal_error
Definition: misc-local.h:149
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
void normal_expression_of_statement(statement s)
===========================================================================
Definition: norm_exp.c:123
int get_nlc_number(entity nlc_ent)
===========================================================================
Definition: norm_exp.c:198
void normal_expression_of_expression(expression exp)
===========================================================================
Definition: norm_exp.c:72
static Pvecteur config_vecteur(Pvecteur Vvar)
===========================================================================
Definition: norm_exp.c:225
void normal_expression_of_unstructured(unstructured u)
===========================================================================
Definition: norm_exp.c:176
void reconfig_expression(expression exp)
===========================================================================
Definition: norm_exp.c:334
#define ENTITY_NLC_P(e)
Definition: norm_exp.c:49
string expression_to_string(expression e)
Definition: expression.c:77
#define NORMALIZE_EXPRESSION(e)
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define is_instruction_block
soft block->sequence transition
#define instruction_block(i)
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
expression Pvecteur_to_expression(Pvecteur vect)
AP, sep 25th 95 : some usefull functions moved from static_controlize/utils.c.
Definition: expression.c:1825
#define loop_body(x)
Definition: ri.h:1644
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define call_function(x)
Definition: ri.h:709
#define range_upper(x)
Definition: ri.h:2290
#define instruction_loop(x)
Definition: ri.h:1520
#define test_false(x)
Definition: ri.h:2837
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
#define range_increment(x)
Definition: ri.h:2292
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define normalized_tag(x)
Definition: ri.h:1778
#define expression_normalized(x)
Definition: ri.h:1249
#define test_true(x)
Definition: ri.h:2835
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define test_condition(x)
Definition: ri.h:2833
#define range_lower(x)
Definition: ri.h:2288
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define loop_range(x)
Definition: ri.h:1642
#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 normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define instruction_unstructured(x)
Definition: ri.h:1532
@ is_normalized_linear
Definition: ri.h:1760
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
Value val
Definition: vecteur-local.h:91
Variable var
Definition: vecteur-local.h:90
struct Svecteur * succ
Definition: vecteur-local.h:92
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
struct Svecteur * Pvecteur
#define VECTEUR_NUL_P(v)
#define term_cst(varval)
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110