PIPS
atomizer.c
Go to the documentation of this file.
1 /*
2 
3  $Id: atomizer.c 23495 2018-10-24 09:19:47Z 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 /* -- atomizer.c
28  *
29  * package atomizer : Alexis Platonoff, juin 91
30  * --
31  *
32  * These functions produce atomic instructions.
33  *
34  * An atomic instruction is an instruction that whether, loads a variable
35  * into a temporary variable, stores a variable from a temporary variable
36  * or computes numericals operations upon temporary variables.
37  *
38  * The scalar variables have a special treatment. Indeed, these variables
39  * are loaded in temporaries and kept in them while they are used or defined.
40  * It is only when they are no more used that they are stored back.
41  * This treatment is done with the dependence graph.
42  *
43  * Note : in the following, we'll distinguish two kinds of variables: the
44  * memory variables and the temporary variables. The firsts will be
45  * called variables, the latter temporaries. The temporaries should
46  * not appear in the dependence graph; ie. that there can not be any
47  * dependences upon the temporaries. The temporaries can also be
48  * called registers.
49  *
50  * This phase produces variables and temporaries. The variables produced are
51  * prefixed : "AUX". The temporaries produced are prefixed : "TMP".
52  * Another kind of entities can be encounter, the NLCs. They have the same
53  * status as the temporaries, ie. they should not appear in the dependence
54  * graph. More, they have another property : an expression that contains only
55  * NLCs and is integer linear, is not decomposed by the atomizer, ie. it is
56  * considered as a constant.
57  */
58 
59 #include "local.h"
60 #include "prettyprint.h"
61 #include "expressions.h"
62 
63 /* Gives the size of the hash table named "MemToTmp". */
64 #define MEM_TO_TMP_SIZE 100
65 
66 /* Useful for atomizer_of_expression(). It tells if the function can return
67  * a variable (MEM_VAR) or if it must return a temporary.
68  */
69 #define MEM_VAR 1
70 #define NO_MEM_VAR 0
71 
72 /* FI: the following global variables are not declared STATIC because
73  * they also are used in codegen.c
74  */
75 
76 /* This global variable is used for the modification of the control graph,
77  * see commentaries of atomizer_of_unstructured() in this file.
78  */
80 
81 /* These lists memorize all the new created entities of each type. They
82  * are used for the declarations of the temporaries and the auxiliaries.
83  */
84 // moved to ri-util/variable.c
85 // list integer_entities = list_undefined;
86 // list real_entities = list_undefined;
87 // list complex_entities = list_undefined;
88 // list logical_entities = list_undefined;
89 // list double_entities = list_undefined;
90 // list char_entities = list_undefined;
91 
92 /* A hash table to map temporary variables (entities)
93  * to memory variables (entities).
94  */
96 
97 /* Dependence graph of the current module. */
99 
100 /*============================================================================*/
101 /* static void initialize_global_variables(char *mod_name) : Initializes the
102  * global variables used through out all the computation of atomizer.
103  *
104  */
105 static void initialize_global_variables(mod_name)
106 char *mod_name;
107 {
108  /* set_current_module_entity(local_name_to_top_level_entity(mod_name)); */
109 
110  /* The last argument says if the resource is to be modified or not :
111  * - false : it is not modified
112  * - true : it is modified
113  */
115  db_get_memory_resource(DBR_CUMULATED_EFFECTS, mod_name, false));
116 
117  mod_dg = (graph) db_get_memory_resource(DBR_DG, mod_name, true);
118 
120 
122 
124  real_entities = NIL;
128  char_entities = NIL;
129 }
130 
132 {
133  /* reset_current_module_entity(); */
134 
136 
138 
145 }
146 
148 {
149  pips_assert("true", b==b);
152  return ent;
153 }
154 
156 {
157  pips_assert("true", ref==ref);
159 }
160 
162 {
164  atomize_as_required(stat,
165  indirection_test, /* reference test */
166  (bool (*)(call,expression)) gen_false2, /* function call test */
167  (bool (*)(test,expression)) gen_false2, /* test condition test */
168  (bool (*)(range,expression)) gen_false2, /* range arguments test */
169  (bool (*)(whileloop,expression)) gen_false2, /* whileloop condition test */
170  build_new_variable); /* new variable */
171 }
172 
173 static void rm_db_block(statement stat)
174 {
175  instruction inst1 = statement_instruction(stat);
176  if ( instruction_block_p(inst1)) {
177  list lt = instruction_block(inst1);
178  list newl = NIL;
179  MAPL (lt2, {
181  {
182  MAPL(lt3, {
183  newl=gen_nconc(newl,CONS(STATEMENT,STATEMENT(CAR(lt3)),NIL));
184  },
186  }
187  else newl = gen_nconc(newl,CONS(STATEMENT,STATEMENT(CAR(lt2)),NIL));
188  },
189  lt);
190  instruction_block(inst1) = newl;
191  ifdebug(8) {
192  //entity module = get_current_module_entity();
193  fprintf(stderr,"statement without db blocks \n");
194  print_statement(stat);
195  }
196  }
197 }
198 
200 {
202 
203  return(stat);
204 }
205 
206 
207 
208 /*============================================================================*/
209 /* void atomizer(const char* module_name): computes the translation of Fortran
210  * instructions into Three Adresses Code instructions.
211  *
212  * This translation is done after two pre-computations :
213  * _ The first one puts all the integer linear expressions into a
214  * normal pattern (see norm_exp.c).
215  * _ The second one removes all the defs with no def-use dependence.
216  *
217  * Also, after the atomization, the module statement is reordered, and
218  * declarations are made for the new variables and temporaries.
219  *
220  * The atomization uses the CODE, CUMULATED_EFFECTS and DG (dependence graph)
221  * resources.
222  *
223  * Called functions:
224  * _ module_body_reorder() : control/control.c
225  */
226 bool atomizer(const string mod_name)
227 {
229  entity module;
230  pips_user_warning("this transformation is being obsoleted by SIMD_ATOMIZER\nIt is no longer maintained and is likely to crash soon\n");
231 
232  debug_on("ATOMIZER_DEBUG_LEVEL");
233 
234  if(get_debug_level() > 0)
235  user_log("\n\n *** ATOMIZER for %s\n", mod_name);
236 
237  mod_stat = (statement) db_get_memory_resource(DBR_CODE, mod_name, true);
238 
239 
240 
242  set_cumulated_rw_effects((statement_effects)db_get_memory_resource(DBR_CUMULATED_EFFECTS,mod_name,true));
243 
246 
247  if (get_bool_property("ATOMIZE_INDIRECT_REF_ONLY"))
248  {
252  }
253  else {
254 
255 
256  initialize_global_variables(mod_name);
257 
258  /* COMPUTATION */
259 
260  /* All the expressions are put into a normal pattern : the NLCs in the
261  * innermost parenthesis.
262  */
264 
265  /* All the defs with no def-use dependence are removed. */
267 
268  /* Module is atomized. */
270 
271  /* We reorder the module. It is necessary because new statements have been
272  * generated. The reordering will permit to reuse the generated code for
273  * further analysis.
274  */
276 
277  /* We declare the new variables and the new temporaries. */
278  /* insert_new_declarations(mod_name); */
280 
282 
283  }
284  /* We save the new CODE. */
285  DB_PUT_MEMORY_RESOURCE(DBR_CODE, strdup(mod_name), mod_stat);
286 
290 
291  if(get_debug_level() > 0)
292  user_log("\n\n *** ATOMIZER done\n");
293 
294  debug_off();
295 
296  return(true);
297 }
298 
299 
300 
301 /*============================================================================*/
302 /* void atomizer_of_unstructured(unstructured u): Computes the transformation
303  * of the unstructured "u".
304  *
305  * This unstructured contains the control graph.
306  * In the control graph, some nodes (of Newgen type "control") have
307  * a statement that is not a "block" of statements. As we need, almost
308  * always, to add new instructions before the IFs and DOs, we have to change
309  * the control graph by adding nodes :
310  * For each node V with a "control_statement" that is not a "block",
311  * we generate a node Vnew that contain a "block" with no instruction.
312  * This node Vnew has the same predecessors as V, and has V as
313  * successor; the node V keeps the same successors, but his
314  * predecessor became Vnew.
315  *
316  * So, for each such node V, when the translation produces instructions,
317  * we need to know the corresponding Vnew, in which we put the
318  * new instructions.
319  *
320  * That is why we use a global variable "l_inst" and a code of CONTROL_MAP
321  * with some modifications (see below).
322  * The list "l_inst" contains the instructions for which we create Vnew.
323  * The modified code of CONTROL_MAP uses a function atom_get_blocs() that
324  * creates new nodes when needed, and updates the list "l_inst".
325  */
327 unstructured u ;
328 {
329  extern list l_inst;
330 
331  list blocs = NIL ;
332  l_inst = NIL;
333 
334  debug(1, "atomizer_of_unstructured", "begin UNSTRUCTURED\n");
335 
336  /* The following code is a modification of CONTROL_MAP,
337  * from control/control.h. This code uses atom_get_blocs() which is
338  * a modification of get_blocs() (in control/control.h).
339  */
340 {
341  cons *_cm_list = blocs ;
342  if( _cm_list == NIL )
343  {
344  atom_get_blocs(unstructured_control(u), &_cm_list ) ;
345  _cm_list = gen_nreverse( _cm_list ) ;
346  }
347  MAPL( _cm_ctls, {control ctl = CONTROL( CAR( _cm_ctls )) ;
348  (void) find_control_block(ctl);
351  (Block *) NULL) ;},
352  _cm_list ) ;
353  if( blocs == NIL )
354  blocs = _cm_list ;
355 }
356 
357  gen_free_list( blocs ) ;
358 
359  debug(1, "atomizer_of_unstructured", "end UNSTRUCTURED\n");
360 }
361 
362 
363 
364 /*============================================================================*/
365 /* void atomizer_of_statement(statement stmt, Block *cb): computes the
366  * translation from Fortran to Three Addresses Code (ATOMIZER) of a statement
367  * ("stmt").
368  *
369  * This function can be called in two different cases:
370  * _ If "cb" is NULL, then "stmt" is taken from a control C of the control
371  * graph. In such case, we have to find out where is the block in which
372  * we'll put the statements created by the translation of "stmt".
373  * . if "stmt" is a block, then this is it.
374  * . else, it is the predecessor of C. This control is obtained by
375  * the function find_control_block().
376  * _ Else, "stmt" is one of the statements of a block, its creations are
377  * put in this block.
378  *
379  * The "cb" variable refers to the current block of statements where "stmt" is.
380  */
383 Block *cb;
384 {
385  instruction inst;
386  bool stmt_with_remote_control_block = false;
388 
389  debug(2, "atomizer_of_statement", "begin STATEMENT\n");
390 
391  inst = statement_instruction(stmt);
392 
393  /* Initialisation of "cb", if it is a NULL pointer. */
394  if(cb == (Block *) NULL)
396  {
397  /* The control in which the created statements are put is not the same
398  * as the control of "stmt".
399  */
400  stmt_with_remote_control_block = true;
401 
402  /* We get the control in which we'll put our new statements. */
404 
405  /* We create the structure that will keep the created statements
406  * during the computation, before putting them in the control "c".
407  */
408  cb = (Block *) malloc(sizeof(Block));
409  if (cb == (Block *) NULL)
410  user_error("atomizer_of_statement", "Block malloc: no memory left");
411  cb->first = NIL;
412  cb->last = CONS(STATEMENT, stmt, NIL);
413  cb->stmt_generated = false;
414  }
415 
416  /* Computation of "stmt". */
417  switch(instruction_tag(inst))
418  {
419  case is_instruction_block : { atomizer_of_block(inst); break; }
421  break; }
423  break; }
425  break; }
426  case is_instruction_goto : break;
429  break; }
430  default : pips_internal_error("Bad instruction tag");
431  }
432 
433  /* Updates of the control graph, if the generated statements are not put in
434  * the same control as "stmt".
435  */
436  if(stmt_with_remote_control_block)
437  {
438  /* The created statements are put in the control just before the control
439  * of the statement that created them.
440  */
442 
443  /* Memory deallocation */
444  if (cb != (Block *) NULL)
445  {
446  cb->first = NIL;
447  cb->last = NIL;
448  free((char *) cb);
449  }
450  }
451  debug(2, "atomizer_of_statement", "end STATEMENT\n");
452 }
453 
454 
455 
456 /*============================================================================*/
457 /* void atomizer_of_block(instruction inst): Applies the translation on all
458  * the statements of the block of the instruction given in argument.
459  *
460  * Note: the "instruction_tag" of "inst" must be a block, otherwise, it's a
461  * user error.
462  *
463  * We enter a new block of statements, so we generate a new variable of
464  * type "Block".
465  * "last" representes the list of statements not translated yet.
466  * "first" representes the list of statements that are translated, plus the
467  * statements that were generated by them.
468  * The statement being translated (current statement) is the first of the
469  * "last" list.
470  * When the translation of a statement is done, it is put at the end of the
471  * "first" list.
472  */
474 instruction i;
475 {
476  Block *cb;
477 
478  debug(2, "atomizer_of_block", "begin BLOCK\n");
479 
481  user_error("atomizer_of_block", "Instruction is not a block");
482 
483  /* Nothing to do!! */
484  if(instruction_block(i) == NIL)
485  return;
486 
487  /* Initialization of the new "Block". */
488  cb = (Block *) malloc(sizeof(Block));
489  if (cb == (Block *) NULL)
490  user_error("atomizer_of_block", "Block malloc: no memory left");
491  cb->last = instruction_block(i);
492  cb->first = NIL;
493 
494  /* "cb->last" is the list of the statements not yet visited */
495  for(; cb->last != NIL; cb->last = CDR(cb->last) )
496  {
497  /* Gets the current statement. */
498  statement s = STATEMENT(CAR(cb->last));
499 
500  /* This current statement has not yet generated another statement. */
501  cb->stmt_generated = false;
502 
503  /* Translation of the current statement. */
504  atomizer_of_statement(s, cb);
505 
506  /* The current statement is put at the end of the "first" list. */
507  cb->first = gen_nconc(cb->first, CONS(STATEMENT, s, NIL));
508  }
509 
510  /* Since there could have been creations of statements in the list "cb->first"
511  * we have to update the block of the instruction.
512  */
513  instruction_block(i) = cb->first;
514 
515  /* Memory deallocation */
516  cb->first = NIL;
517  free( (char *) cb);
518 
519  debug(2, "atomizer_of_block", "end BLOCK\n");
520 }
521 
522 
523 
524 /*============================================================================*/
525 /* void atomizer_of_test(test t, Block *cb): Applies the translation on an
526  * instruction test.
527  *
528  * It consists in translating the three arguments of the test instruction :
529  * the condition expression and the two conditional statements (true, false).
530  *
531  * The condition argument is an expression which may contain a logical
532  * intrinsic operator : "x op y" or "op x", with "op" in (<, =, >=, etc).
533  * In such case, the tranlation does not assign a temporary for the call
534  * expression associated with the operator, it only translates the arguments
535  * of the logical operator.
536  *
537  * The variable "cb" memorises the information about the block of statements
538  * that contains the test statement.
539  *
540  * Called functions :
541  * _ make_block_with_stmt() : loop_normalize/utils.c
542  */
543 void atomizer_of_test(t, cb)
544 test t;
545 Block *cb;
546 {
547  expression cond = test_condition(t);
548 
549  debug(2, "atomizer_of_test", "begin TEST\n");
550 
552  /* If the expression is a call to a intrinsic operation,
553  * only its arguments
554  * are translated.
555  * Note : it is not tested that the intrinsic is a logical
556  * operator. In fact,
557  * Fortran requires it.
558  */
559  {
562 
563  debug(3, "atomizer_of_test", "CONDITION: %s\n",
565  }
566  else
567  /* Else, the conditional expression is translated,
568  * and the returned expression
569  * must be a temporary (NO_MEM_VAR).
570  */
572 
573  /* Afterwards, the two conditional statements are translated. If one of these
574  * statements is not a block of statements, then it is put inside one (the
575  * resulting block contains only one statement !!).
576  */
577  debug(2, "atomizer_of_test", "begin TEST IF\n");
580 
581  debug(2, "atomizer_of_test", "begin TEST ELSE\n");
584 
585  debug(2, "atomizer_of_test", "end TEST\n");
586 }
587 
588 
589 
590 /*============================================================================*/
591 /* void atomizer_of_loop(loop l, Block *cb): Applies the translation on an
592  * instruction loop.
593  *
594  * All written variables of the loop are removed from MemToTmp.
595  *
596  * The variable "cb" memorizes the information about the block of statements
597  * that contains the loop statement.
598  *
599  * Called functions:
600  * _ entity_scalar_p() : ri-util/entity.c
601  * _ make_block_with_stmt() : loop_normalize/utils.c
602  */
603 void atomizer_of_loop(l, cb)
604 loop l;
605 Block *cb;
606 {
607 
608  list cumu_effs, lce;
609  statement stmt;
610  range r;
611 
612  debug(2, "atomizer_of_loop", "begin LOOP: %s\n",
614 
615  /* We have to remove from MemToTmp all the (scalars) variables that are
616  * written in this loop.
617  */
618  stmt = STATEMENT(CAR(cb->last));
619  cumu_effs = load_rw_effects_list(stmt);
620  for(lce = cumu_effs; lce != NIL; lce = CDR(lce))
621  {
622  effect eff = EFFECT(CAR(lce));
624  if( entity_scalar_p(eff_e) &&
626  {
627  (void) hash_del(MemToTmp, (char *) eff_e);
628  }
629  }
630 
631  /* Translation of the three expressions of the loop range. */
632  r = loop_range(l);
636 
637  /* Afterwards, the body statement of the loop is translated. If this
638  * statement is not a block of statements, then it is put inside one (the
639  * resulting block contains only one statement !!).
640  */
643 
644  debug(2, "atomizer_of_loop", "end LOOP\n");
645 }
646 
647 
648 
649 /*============================================================================*/
650 /* void atomizer_of_call(call c, Block *cb): Applies the translation on an
651  * instruction call.
652  *
653  * The two main kinds of call are:
654  * _ external call, ie user_defined function or subroutine.
655  * _ intrinsic call.
656  *
657  * The variable "cb" memorises the information about the block of statements
658  * that contains the call statement.
659  */
660 void atomizer_of_call(c, cb)
661 call c;
662 Block *cb;
663 {
664  entity e = call_function(c);
665  tag t = value_tag(entity_initial(e));
666  string n = entity_name(e);
667 
668  switch (t)
669  {
670  case is_value_code: { atomizer_of_external(c, cb); break; }
671  case is_value_intrinsic: {
672  if (call_arguments(c) == NIL)
673  /* Evite d'atomiser un parame`tre inexistant ( :-) )
674  d'un intrinsic sans argument, du style * dans :
675  write ... FMT=*...
676  RK, 24/02/1994. */
677  break;
678  atomizer_of_intrinsic(c, cb);
679  break;
680  }
681  case is_value_symbolic: break;
682  case is_value_constant: break;
683  case is_value_unknown:
684  pips_internal_error("unknown function %s", n);
685  break;
686  default: pips_internal_error("unknown tag %d", t);
687  }
688 }
689 
690 
691 
692 /*============================================================================*/
693 /* void atomizer_of_intrinsic(call c, block *cb): translates the arguments of
694  * the intrinsic function. It treats two cases: assign call, and others.
695  *
696  * Assign calls are treated differently because the first argument is the
697  * left-hand-side, so this argument is translated with the MEM_VAR option.
698  */
700 call c;
701 Block *cb;
702 {
704  {
705  entity lhs_entity;
706  expression lhs, rhs;
707 
708  /* Assign expressions. */
709  lhs = EXPRESSION(CAR(call_arguments(c)));
710  rhs = EXPRESSION(CAR(CDR(call_arguments(c))));
711 
712  pips_debug(4, "ASSIGN CALL: %s = %s\n",
714  expression_to_string(rhs));
715 
716  /* If the rhs expression is integer linear and exclusively composed of NLC
717  * variables, it is considered like a constant, ie not translated.
718  * Otherwise, it is translated normaly.
719  */
720  if(! nlc_linear_expression_p(rhs))
721  rhs = atomizer_of_expression(rhs, cb, NO_MEM_VAR);
722 
723  /* Translation of the lhs expression. We keep the memory variable. */
724  lhs = atomizer_of_expression(lhs, cb, MEM_VAR);
725 
726  /* The lhs variable is stored, so it is delete from MemToTmp. */
728  (void) hash_del(MemToTmp, (char *) lhs_entity);
729 
730  call_arguments(c) = CONS(EXPRESSION, lhs, CONS(EXPRESSION, rhs, NIL));
731  }
732  else
733  /* The call is not an assignment, then each arguments is translated. */
735 }
736 
737 
738 
739 /*============================================================================*/
740 /* void atomizer_of_external(call c, block *cb): Translates the arguments
741  * of the call to an external function.
742  *
743  * In fact, these arguments are kept as memory variable. When, the argument
744  * is an expression containing a "call" (a real call to a function and not a
745  * call to a constant), this expression is assigned to a new auxiliary
746  * variable which takes its place in the list of arguments. It is a variable,
747  * not a temporary (see the introduction at the beginning of this file).
748  *
749  * Called functions :
750  * _ make_entity_expression() : ri-util/util.c
751  * _ make_assign_statement() : ri-util/statement.c
752  */
754 call c;
755 Block *cb;
756 {
757  list args, new_args;
758 
759  args = call_arguments(c);
760  new_args = NIL;
761 
762  /* All the argument expressions are scanned. If an expression is not a
763  * reference (then, it is a call), we create an auxiliary variable.
764  * The expression is assigned to this new variable which is given in
765  * argument to the function, instead of the expression.
766  * If it is a reference, the corresponfding key (if it exists) in the
767  * hash table MemToTmp is deleted.
768  */
769  for(; args != NIL; args = CDR(args))
770  {
771  expression ae = EXPRESSION(CAR(args));
773  {
775  (void) hash_del(MemToTmp, (char *) reference_variable(ar));
776  reference_indices(ar) =
778  new_args = gen_nconc(new_args, CONS(EXPRESSION, ae, NIL));
779  }
780  else
781  {
782  call arg_call = syntax_call(expression_syntax(ae));
783  if(call_constant_p(arg_call))
784  new_args = gen_nconc(new_args, CONS(EXPRESSION, ae, NIL));
785  else
786  {
788  basic aux_basic = basic_of_expression(tmp);
789  entity aux_ent = make_new_entity(aux_basic, AUX_ENT);
792  new_args = gen_nconc(new_args, CONS(EXPRESSION, aux, NIL));
793  }
794  }
795  }
796 
797  call_arguments(c) = new_args;
798 }
799 
800 
801 
802 /*============================================================================*/
803 /* list atomizer_of_expressions(list expl, Block *cb): Applies the
804  * translation on a list of expressions.
805  *
806  * The variable "cb" memorises the information about the block of statements
807  * that contains the expressions.
808  *
809  * Returns a list of expressions containing the translated expressions.
810  */
812 list expl;
813 Block *cb;
814 {
815  list newl;
816  expression exp, trad_exp;
817  for (newl = NIL; expl != NIL; expl = CDR(expl))
818  {
819  exp = EXPRESSION(CAR(expl));
820  trad_exp = atomizer_of_expression(exp, cb, NO_MEM_VAR);
821  newl = gen_nconc(newl, CONS(EXPRESSION, trad_exp, NIL));
822  }
823  return newl;
824 }
825 
826 
827 
828 /*============================================================================*/
829 /* expression atomizer_of_expression(expression exp, Block *cb, int mem_var):
830  * Applies the translation on an expression.
831  *
832  * It consists in assigning a new temporary variable to the expression, while
833  * the sub-expressions that it may contain are recursively translated.
834  *
835  * If "exp" is only composed of NLCs variables (eventually a constant term),
836  * then the expression is treated like a constant, ie unchanged.
837  * NLC means Normalized Loop Counter.
838  *
839  * The translation of expressions that reference a variable is not done only
840  * if the flag "mem_var" has the value "MEM_VAR". Otherwise, the variable is
841  * assigned to a temporary variable.
842  * The function "atomizer_of_array_indices()" translates the list of indices
843  * (when not empty) of the variable given in argument.
844  * Note: a scalar variable is an array with an empty list of indices.
845  *
846  * The variable "cb" memorises the information about the block of statements
847  * that contains the expression.
848  */
851 Block *cb;
852 int mem_var;
853 {
856  bool IS_NLC_LINEAR = false;
857 
858  pips_debug(5, "begin : %s\n",
860 
861  /* An expression that is integer linear and is exclusively composed of NLCs
862  * is considered like a constant, ie not translated.
863  */
865  IS_NLC_LINEAR = true;
866 
867  switch(syntax_tag(sy))
868  {
869  case is_syntax_reference:
870  {
872 
873  if ( (mem_var == MEM_VAR) || IS_NLC_LINEAR )
874  ret_exp = exp;
875  else
876  ret_exp = assign_tmp_to_exp(exp, cb);
877  break;
878  }
879  case is_syntax_call:
880  {
881  call c = syntax_call(sy);
882 
883  /* Two cases : _ a "real" call, ie an intrinsic or external function
884  * _ a constant
885  */
886  if( ! call_constant_p(c) )
887  {
888  if ((call_arguments(c) == NIL)
890  /* Evite d'atomiser un parame`tre inexistant ( :-) )
891  d'un intrinsic sans argument, du style * dans :
892  write ... FMT=*...
893  RK, 24/02/1994. */
894  ret_exp = exp;
895  break;
896  }
897  else {
898  /* Translates the arguments of the call. */
899  if( ! IS_NLC_LINEAR )
900  atomizer_of_call(c, cb);
901 
902  /* Generates the assign statement, and put it into the current block. */
903  ret_exp = assign_tmp_to_exp(exp, cb);
904  }}
905  else /* Constant value. */
906  ret_exp = exp;
907  break;
908  }
909  case is_syntax_range:
910  {
911  debug(6, "atomizer_of_expression", " Expression RANGE\n");
912  ret_exp = exp;;
913  break;
914  }
915  default : pips_internal_error("Bad syntax tag");
916  }
917  pips_debug(5, "end : %s\n",
918  expression_to_string(ret_exp));
919 
920  return(ret_exp);
921 }
922 
923 
924 
925 /*============================================================================*/
926 /* void atomizer_of_array_indices(expression exp, Block *cb): Applies the
927  * translation on an array expression.
928  *
929  * Only the indices of the array are translated, in order to have a list
930  * of temporary variables.
931  */
934 Block *cb;
935 {
937  list inds = reference_indices(array_ref);
938 
939  pips_debug(6, "begin : %s\n", expression_to_string(exp));
940 
941  /* We translate all the indices expressions. */
942  reference_indices(array_ref) = atomizer_of_expressions(inds, cb);
943 
944  pips_debug(6, "end : %s\n", expression_to_string(exp));
945 }
void user_log(const char *format,...)
Definition: message.c:234
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
#define AUX_ENT
#define MEM_TO_TMP_SIZE
– atomizer.c
Definition: atomizer.c:64
void atomizer_of_block(instruction i)
===========================================================================
Definition: atomizer.c:473
void atomizer_of_external(call c, Block *cb)
===========================================================================
Definition: atomizer.c:753
void atomizer_of_call(call c, Block *cb)
===========================================================================
Definition: atomizer.c:660
void atomizer_of_test(test t, Block *cb)
===========================================================================
Definition: atomizer.c:543
static void reset_global_variables()
Definition: atomizer.c:131
#define NO_MEM_VAR
Definition: atomizer.c:70
void normalize_wp65_code(statement stat)
Definition: atomizer.c:161
static void initialize_global_variables(char *mod_name)
===========================================================================
Definition: atomizer.c:105
list l_inst
FI: the following global variables are not declared STATIC because they also are used in codegen....
Definition: atomizer.c:79
list atomizer_of_expressions(list expl, Block *cb)
===========================================================================
Definition: atomizer.c:811
static bool indirection_test(reference ref, expression expr)
Definition: atomizer.c:155
hash_table MemToTmp
These lists memorize all the new created entities of each type.
Definition: atomizer.c:95
void atomizer_of_loop(loop l, Block *cb)
===========================================================================
Definition: atomizer.c:603
void atomizer_of_statement(statement stmt, Block *cb)
===========================================================================
Definition: atomizer.c:381
void atomizer_of_array_indices(expression exp, Block *cb)
===========================================================================
Definition: atomizer.c:932
void atomizer_of_unstructured(u)
===========================================================================
Definition: atomizer.c:326
#define MEM_VAR
Useful for atomizer_of_expression().
Definition: atomizer.c:69
static entity build_new_variable(entity module, basic b)
Definition: atomizer.c:147
void atomizer_of_intrinsic(call c, Block *cb)
===========================================================================
Definition: atomizer.c:699
static graph mod_dg
Dependence graph of the current module.
Definition: atomizer.c:98
static void rm_db_block(statement stat)
Definition: atomizer.c:173
static statement rm_block_block_statement(statement stat)
Definition: atomizer.c:199
bool atomizer(const string mod_name)
===========================================================================
Definition: atomizer.c:226
expression atomizer_of_expression(expression exp, Block *cb, int mem_var)
===========================================================================
Definition: atomizer.c:849
expression assign_tmp_to_exp(expression, Block *)
===========================================================================
Definition: codegen.c:155
bool defs_elim_of_statement(statement, graph)
===========================================================================
Definition: defs_elim.c:211
void put_stmt_in_Block(statement, Block *)
codegen.c
Definition: codegen.c:89
void atom_get_blocs(control, cons **)
void normal_expression_of_statement(statement)
===========================================================================
Definition: norm_exp.c:123
control find_control_block(control)
===========================================================================
Definition: control.c:115
bool nlc_linear_expression_p(expression)
===========================================================================
Definition: utils.c:78
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
void set_rw_effects(statement_effects)
void set_cumulated_rw_effects(statement_effects)
list load_rw_effects_list(statement)
void reset_cumulated_rw_effects(void)
void reset_rw_effects(void)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_action(x)
Definition: effects.h:642
#define action_tag(x)
Definition: effects.h:310
@ is_action_write
Definition: effects.h:293
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
void atomize_as_required(statement, bool(*)(reference, expression), bool(*)(call, expression), bool(*)(test, expression), bool(*)(range, expression), bool(*)(whileloop, expression), entity(*)(entity, basic))
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define call_constant_p(C)
Definition: flint_check.c:51
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void * malloc(YYSIZE_T)
void free(void *)
struct _newgen_struct_graph_ * graph
Definition: graph.h:31
#define graph_undefined
Definition: graph.h:60
statement make_block_with_stmt_if_not_already(statement)
Build a statement block from a statement if not already a statement block.
Definition: statement.c:768
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
bool gen_false2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2801
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#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 MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
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
statement make_assign_statement(expression, expression)
Definition: statement.c:583
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_del(hash_table htp, const void *key)
this function removes from the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:439
void hash_table_clear(hash_table htp)
Clears all entries of a hash table HTP.
Definition: hash.c:305
static statement mod_stat
We want to keep track of the current statement inside the recurse.
Definition: impact_check.c:41
#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 pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define user_error(fn,...)
Definition: misc-local.h:265
int get_debug_level(void)
GET_DEBUG_LEVEL returns the current debugging level.
Definition: debug.c:67
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
@ hash_pointer
Definition: newgen_hash.h:32
#define hash_table_undefined
Value of an undefined hash_table.
Definition: newgen_hash.h:49
int tag
TAG.
Definition: newgen_types.h:92
struct cons * list
Definition: newgen_types.h:106
void normalize_all_expressions_of(void *obj)
Definition: normalize.c:668
static char * module
Definition: pips.c:74
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
list double_entities
#define instruction_block_p(i)
list real_entities
#define ENTITY_ASSIGN_P(e)
list complex_entities
#define NORMALIZE_EXPRESSION(e)
list logical_entities
list char_entities
#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
list integer_entities
Make a new variable entity which name is one letter prefix + one incrementing number.
Definition: ri-util.h:2787
#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
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
expression make_entity_expression(entity e, cons *inds)
Definition: expression.c:176
bool expression_intrinsic_operation_p(expression exp)
bool expression_intrinsic_operation_p(expression exp): Returns true if "exp" is an expression with a ...
Definition: expression.c:1949
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
entity make_new_entity(basic, int)
Definition: variable.c:898
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
entity make_new_module_variable(entity, int)
Make a new module integer variable of name X<d>.
Definition: variable.c:830
void AddEntityToDeclarations(entity, entity)
END_EOLE.
Definition: variable.c:108
void discard_module_declaration_text(entity)
Discard the decls_text string of the module code to make the prettyprinter ignoring the textual decla...
Definition: variable.c:1696
#define value_tag(x)
Definition: ri.h:3064
#define loop_body(x)
Definition: ri.h:1644
#define control_undefined
Definition: ri.h:916
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define normalized_linear_p(x)
Definition: ri.h:1779
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define range_upper(x)
Definition: ri.h:2290
#define value_intrinsic_p(x)
Definition: ri.h:3074
#define instruction_loop(x)
Definition: ri.h:1520
#define test_false(x)
Definition: ri.h:2837
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
@ is_value_intrinsic
Definition: ri.h:3034
@ is_value_unknown
Definition: ri.h:3035
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
@ is_value_symbolic
Definition: ri.h:3032
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ 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 entity_name(x)
Definition: ri.h:2790
#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 expression_syntax(x)
Definition: ri.h:1247
#define instruction_unstructured(x)
Definition: ri.h:1532
#define loop_index(x)
Definition: ri.h:1640
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
int aux
Definition: solpip.c:104
During the computation, the program has to deal with blocks of statements.
bool stmt_generated
list first
list last
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207