PIPS
single_assign.c
Go to the documentation of this file.
1 /*
2 
3  $Id: single_assign.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 /* Name : single_assign.c
29  * Package : reindexing
30  * Author : Alexis Platonoff
31  * Date : febuary 1994
32  * Historic :
33  * - 14 nov 94 : move this file into reindexing package. Del single_assign
34  * package.
35  *
36  * Documents:
37  * Comments : This file contains the functions for the transformation of a
38  * program to a single assignment form.
39  */
40 
41 /* Ansi includes */
42 #include <stdio.h>
43 #include <string.h>
44 
45 /* Newgen includes */
46 #include "genC.h"
47 
48 /* C3 includes */
49 #include "boolean.h"
50 #include "arithmetique.h"
51 #include "vecteur.h"
52 #include "contrainte.h"
53 #include "ray_dte.h"
54 #include "sommet.h"
55 #include "sg.h"
56 #include "sc.h"
57 #include "polyedre.h"
58 #include "union.h"
59 #include "matrice.h"
60 #include "matrix.h"
61 
62 /* Pips includes */
63 #include "boolean.h"
64 #include "ri.h"
65 #include "constants.h"
66 #include "ri-util.h"
67 #include "misc.h"
68 #include "complexity_ri.h"
69 #include "database.h"
70 #include "graph.h"
71 #include "dg.h"
72 #include "paf_ri.h"
73 #include "parser_private.h"
74 #include "property.h"
75 #include "reduction.h"
76 #include "text.h"
77 #include "text-util.h"
78 #include "tiling.h"
79 #include "text-util.h"
80 #include "pipsdbm.h"
81 #include "resources.h"
82 #include "static_controlize.h"
83 #include "paf-util.h"
84 #include "pip.h"
85 #include "array_dfg.h"
86 #include "reindexing.h"
87 
88 /* Macro functions */
89 
90 #define FIRST 1
91 #define SECOND 2
92 #define THIRD 3
93 
94 /* Internal variables */
95 
96 /* Global variables */
97 static int tc;
98 
99 /* Local defines */
102 
103 /* ========================================================================= */
104 /* * void rhs_subs_in_ins(instruction ins, reference r1, reference r2)
105  *
106  * Changes, in the right hand side of "ins", the occurrences of "r1" by
107  * "r2".
108  *
109  */
110 void rhs_subs_in_ins(ins, r1, r2)
111 instruction ins;
112 reference r1, r2;
113 {
114  switch(instruction_tag(ins)) {
115  case is_instruction_call : {
116  call c = instruction_call(ins);
118  expression rhs_exp = EXPRESSION(CAR(CDR(call_arguments(c))));
119 
120  ref_subs_in_exp(rhs_exp, r1, r2);
121 
122  }
123  else pips_internal_error("Instruction is not an assign call");
124 
125  break;
126  }
127  case is_instruction_block :
128  case is_instruction_test :
129  case is_instruction_loop :
130  case is_instruction_goto :
132  default : pips_internal_error("Instruction is not an assign call");
133  }
134 }
135 
136 /*==================================================================*/
137 /* vertex my_dfg_in_vertex_list( (list) l, (vertex) v )
138  * Input : A list l of vertices.
139  * A vertex v of a dataflow graph.
140  * Returns vertex_undefined if v is not in list l.
141  * Returns v' that has the same statement_ordering than v.
142  *
143  * AC 93/10/19
144  */
145 
147 
148  list l;
149  vertex v;
150 {
151  vertex ver;
152  int in;
153 
155  for (;!ENDP(l); POP(l))
156  {
157  int prov_i;
158 
159  ver = VERTEX(CAR( l ));
161  if ( prov_i == in ) return( ver );
162  }
163  return (vertex_undefined);
164 }
165 
166 
167 /*=======================================================================*/
168 /* graph my_dfg_reverse_graph( (graph) g )
169  * This function is used to reverse Pips's graph in order to have
170  * all possible sources directly (Feautrier's dependance graph).
171  *
172  * AC 93/10/19
173  */
174 
175 
177 
178  graph g;
179 {
180  graph rev_graph = graph_undefined;
181  list verlist = NIL;
182  successor succ;
183 
184  MAPL(ver_ptr,{
185  vertex ver;
186  vertex ver2;
187  vertex ver5;
188 
189  ver = VERTEX(CAR( ver_ptr ));
190  ver5 = my_dfg_in_vertex_list( verlist, ver );
191  if ( ver5 == vertex_undefined )
192  {
193 /*
194  ver2 = make_vertex(copy_dfg_vertex_label((dfg_vertex_label)\
195  vertex_vertex_label( ver)),(list) NIL );
196 */
197  ver2 = make_vertex(vertex_vertex_label(ver), NIL);
199  }
200  else ver2 = ver5;
201 
202  MAPL(succ_ptr, {
203  list li = NIL;
204  successor succ2;
205  vertex ver3;
206  vertex ver4;
207 
208  succ = SUCCESSOR(CAR( succ_ptr ));
209  ver3 = successor_vertex( succ );
210  ver5 = my_dfg_in_vertex_list( verlist, ver3);
211 /*
212  succ2 = make_successor(copy_dfg_arc_label((dfg_arc_label)\
213  successor_arc_label(succ)),ver2 );
214 */
215  succ2 = make_successor(successor_arc_label(succ), ver2);
216  if ( ver5 == vertex_undefined )
217  {
218  ADD_ELEMENT_TO_LIST( li, SUCCESSOR,succ2);
219 /*
220  ver4 = make_vertex(copy_dfg_vertex_label((dfg_vertex_label)\
221  vertex_vertex_label(ver3)),(list) li );
222 */
223  ver4 = make_vertex(vertex_vertex_label(ver3), li);
225  }
226  else
228  }, vertex_successors( ver ) );
229 
230 
231  }, graph_vertices( g ) );
232 
233  rev_graph = make_graph( verlist );
234  return( rev_graph );
235 }
236 
237 /* ========================================================================= */
238 /*
239  * entity create_entity(string name, variable v)
240  *
241  * Creates an entity with the name "name" and of variable "v" (i.e. it is
242  * its type).
243  */
245 string name;
246 variable v;
247 {
248  return(make_entity(name,
252 }
253 
254 
255 /* ========================================================================= */
256 /*
257  * list dims_of_nest(int n)
258  *
259  * returns a list containing the dimensions (NewGen dimension) of the
260  * englobing loops of statement number "n".
261  */
263 int n;
264 {
266  list dims = NIL, l_loops;
267 
268  l_loops = static_control_loops(stco);
269  for(; !ENDP(l_loops); POP(l_loops)) {
270  loop lo = LOOP(CAR(l_loops));
271  range ra = loop_range(lo);
272  dims = gen_nconc(dims, CONS(DIMENSION,
274  range_upper(ra),
275  NIL),
276  NIL));
277  }
278  return(dims);
279 }
280 
281 
282 /* ========================================================================= */
283 /*
284  * reference build_new_ref(int kind, int n, list subscripts, reference old_r)
285  *
286  * builds a new array reference. Its entity name depends on "kind":
287  * kind == IS_TEMP => name is : SATn
288  * kind == IS_NEW_ARRAY => name is : SAIn
289  * We first test if this entity does not exist yet. If not, we have create it
290  * with a type_variable with the same basic as the one of the entity of
291  * "old_ref" and a dimension depending again on kind:
292  * kind == IS_TEMP => dimension is: empty
293  * kind == IS_NEW_ARRAY => dimension is: dimension of the loop nest of
294  * statement number n
295  *
296  * Its indices of the new reference are "subscripts".
297  *
298  * "subscripts" is a list of affine expressions.
299  * If "subscripts" is empty, then this is a scalar.
300  */
301 reference build_new_ref(kind, n, subscripts, old_r)
302 int kind;
303 int n;
304 list subscripts;
305 reference old_r;
306 {
307  list sl;
308  entity ent;
309  string num, name = (string) NULL;
310 
311  /* we duplicate this list */
312  sl = subscripts;
313 
314  num = (string) malloc(32);
315  (void) sprintf(num, "%d", n);
316  if(kind == IS_TEMP)
318  SAT, num, (string) NULL));
319  else if(kind == IS_NEW_ARRAY)
321  SAI, num, (string) NULL));
322  else
323  pips_internal_error("Bad value for kind");
324 
325  ent = gen_find_tabulated(name, entity_domain);
326  if(ent == entity_undefined) {
327  list dims = NIL;
328 
329  if(kind == IS_NEW_ARRAY)
330  dims = dims_of_nest(n);
331  else
332  pips_internal_error("Bad value for kind");
333 
334  ent = create_entity(name, make_variable(basic_of_reference(old_r), dims));
335  }
336 
337 if(get_debug_level() > 6) {
338 fprintf(stdout, "\t\t\t\t\t\t[build_new_ref] Nouvelle ref %s[", entity_local_name(ent));
339 fprint_list_of_exp(stdout, sl);
340 fprintf(stdout, "]\n");
341 }
342 
343  return(make_reference(ent, sl));
344 }
345 
346 /* ========================================================================= */
347 /*
348  * void lhs_subs_in_ins(instruction ins, string SA, int n, list subscripts)
349  *
350  * Substitutes to the lhs (left Hand Side) reference of "ins" the array
351  * reference SAn[subscripts], cf. build_new_ref().
352  *
353  * "subscripts" is a list of entity, so we have transform it into a list of
354  * expression.
355  *
356  * Note: "ins" must be an assign call
357  */
358 void lhs_subs_in_ins(ins, SA, n, subscripts)
359 instruction ins;
360 string SA;
361 int n;
362 list subscripts;
363 {
364  switch(instruction_tag(ins)) {
365  case is_instruction_call : {
366  call c = instruction_call(ins);
368  expression lhs_exp = EXPRESSION(CAR(call_arguments(c)));
369  syntax sy = expression_syntax(lhs_exp);
370  if(syntax_reference_p(sy)) {
371  reference lhs = syntax_reference(sy);
372  list exp_subs = entities_to_expressions(subscripts);
373  syntax_reference(sy) = build_new_ref(IS_NEW_ARRAY, n, exp_subs, lhs);
374 
375 if(get_debug_level() > 3) {
376 fprintf(stdout, "\t\t\t[lhs_subs_in_ins] New ref %s instead of %s\n",
378  reference_to_string(lhs));
379 }
380 
381  }
382  else pips_internal_error("Lhs is not a reference");
383  }
384  else pips_internal_error("Instruction is not an assign call");
385  break;
386  }
387  case is_instruction_block :
388  case is_instruction_test :
389  case is_instruction_loop :
390  case is_instruction_goto :
392  default : pips_internal_error("Instruction is not an assign call");
393  }
394 }
395 
396 /* ========================================================================= */
397 /*
398  * list references_of_expression(expression exp)
399  *
400  * Conversion of an expression into a list of references.
401  * Only the array and scalar references used in the operations are added,
402  * not the references in index expressions.
403  */
406 {
407  list refl = NIL;
409  switch(syntax_tag(sy)) {
410  case is_syntax_reference: {
411  refl = gen_nconc(refl, CONS(REFERENCE, syntax_reference(sy), NIL));
412  break;
413  }
414  case is_syntax_call: {
415  list ael = call_arguments(syntax_call(sy));
416  for(; !ENDP(ael); POP(ael)) {
417  expression ae = EXPRESSION(CAR(ael));
418  refl = gen_nconc(refl, references_of_expression(ae));
419  }
420  break;
421  }
422  case is_syntax_range: pips_internal_error("Syntax Range");
423  default : pips_internal_error("Bad syntax tag");
424  }
425  return(refl);
426 }
427 
428 
429 /* ========================================================================= */
430 /*
431  * list get_rhs_of_instruction(instruction ins)
432  *
433  * Constructs a list of references that are all the rhs (Right Hand Side) of
434  * instruction "ins".
435  */
437 instruction ins;
438 {
439  list rhsl = NIL;
440  switch(instruction_tag(ins)) {
441  case is_instruction_call : {
442  call c = instruction_call(ins);
444  expression rhs_exp;
445  list args = call_arguments(c);
446 
447  if(gen_length(args) != 2)
448  pips_internal_error("Assign call without 2 args");
449 
450  /* There are two args: lhs = rhs, we want the references of the rhs */
451  rhs_exp = EXPRESSION(CAR(CDR(args)));
452  rhsl = gen_nconc(rhsl, references_of_expression(rhs_exp));
453  }
454  break;
455  }
456  case is_instruction_block :
457  case is_instruction_test :
458  case is_instruction_loop :
459  case is_instruction_goto :
461  default : pips_internal_error("Instruction is not an assign call");
462  }
463  return(rhsl);
464 }
465 
466 
467 /* ========================================================================= */
468 /*
469  * list build_associate_temp(list lr)
470  *
471  * builds a list of reference to temporary variables. These temporaries are
472  * associated to each reference of "lr" (in the same order). These temporaries
473  * are scalars.
474  * They are numbered with a global counter "tc".
475  *
476  */
478 list lr;
479 {
480  extern int tc;
481 
482  list l, atl = NIL;
483 
484  for(l = lr; !ENDP(l); POP(l)) {
485  reference r = REFERENCE(CAR(l));
486  atl = gen_nconc(atl, CONS(REFERENCE,
487  build_new_ref(IS_TEMP, tc++, NIL, r),
488  NIL));
489  }
490  return(atl);
491 }
492 
493 
494 /* ========================================================================= */
495 /*
496  * list build_successors_with_rhs(list ls, reference r)
497  *
498  * builds a sublist of list "ls". "ls" is a list of successors, each successor
499  * containing a list of dataflows. Each datalow represents the dependence
500  * upon a reference. So a successor of "ls" is put in our sublist if and only
501  * if it contains a dataflow that depends on the reference "r".
502  *
503  */
505 list ls;
506 reference r;
507 {
508  list sls = NIL, l, ll;
509 
510  for(l = ls; !ENDP(l); POP(l)) {
511  successor suc = SUCCESSOR(CAR(l));
513  for(ll = dfl; !ENDP(ll); POP(ll)) {
514  dataflow df = DATAFLOW(CAR(ll));
515  reference dfr = dataflow_reference(df);
516 
517  /* true equality, not on pointers */
518  if(reference_equal_p(dfr, r))
519  sls = gen_nconc(sls, CONS(SUCCESSOR, suc, NIL));
520  }
521  }
522  return(sls);
523 }
524 
525 
526 /* ========================================================================= */
527 /*
528  * int count_dataflows_on_ref(list ls, reference r, dataflow *df, int *m)
529  *
530  * "ls" is a list of successors. This function scans this list and looks for
531  * dataflows on reference "r". If it does not find any, it returns 0, else
532  * if there is one such dataflow, then it returns 1 (and also, save this
533  * dataflow and the statement number of the pointed vertex in, respectively,
534  * df and m). Else, it returns 2.
535  *
536  */
537 int count_dataflows_on_ref(ls, r, df, m)
538 list ls;
539 reference r;
540 dataflow *df;
541 int *m;
542 {
543  list l;
544  int count = 0;
545 
546 if(get_debug_level() > 3) {
547 fprintf(stdout, "\t\t\t[count_dataflows_on_ref] %s\n",
549 }
550 
551  *df = dataflow_undefined;
552  *m = -1;
553 
554  for(l = ls; !ENDP(l) && (count < 2); POP(l)) {
555  successor suc = SUCCESSOR(CAR(l));
557  for(; !ENDP(dfl) && (count < 2); POP(dfl)) {
558  dataflow d = DATAFLOW(CAR(dfl));
559 
561  count++;
562  if(count == 2)
563  *df = dataflow_undefined;
564  else {
565  *df = d;
567 
568  }
569  if(get_debug_level() > 3) {
570  fprintf(stdout, "\t\t\t[count_dataflows_on_ref] One more\n");
571  fprint_dataflow(stdout,
573  d);
574 }
575  }
576  }
577  }
578  return(count);
579 }
580 
581 
582 /* ========================================================================= */
583 /*
584  * list dataflows_on_ref(successor suc, reference r)
585  *
586  * This function scans the list of dataflows of "suc" and looks for
587  * dataflows on reference "r". It returns the list these dataflows.
588  */
590 successor suc;
591 reference r;
592 {
593  list dfl, rdfl = NIL;
594 
596  for(; !ENDP(dfl); POP(dfl)) {
597  dataflow d = DATAFLOW(CAR(dfl));
599  rdfl = gen_nconc(rdfl, CONS(DATAFLOW, d, NIL));
600  }
601  return(rdfl);
602 }
603 
604 
605 /* ========================================================================= */
606 /*
607  * void ref_subs_in_exp(expression exp, reference r1, reference r2)
608  *
609  * changes, in expression "exp", the occurrences of "r1" by "r2".
610  *
611  */
612 void ref_subs_in_exp(exp, r1, r2)
614 reference r1, r2;
615 {
617  switch(syntax_tag(sy)) {
618  case is_syntax_reference: {
620  syntax_reference(sy) = r2;
621  break;
622  }
623  case is_syntax_call: {
624  list ael = call_arguments(syntax_call(sy));
625  for(; !ENDP(ael); POP(ael)) {
626  expression ae = EXPRESSION(CAR(ael));
627  ref_subs_in_exp(ae, r1, r2);
628  }
629  break;
630  }
631  case is_syntax_range: pips_internal_error("Syntax Range");
632  default : pips_internal_error("Bad syntax tag");
633  }
634 }
635 
636 /* ========================================================================= */
637 /*
638  * expression predicate_to_expression(predicate pred)
639  */
641 predicate pred;
642 {
643  entity and_ent, leq_ent, equ_ent;
644  expression exp1 = expression_undefined, exp2;
645  Psysteme ps = (Psysteme) predicate_system(pred);
646  Pcontrainte pc;
647 
648 if(get_debug_level() > 5) {
649 fprintf(stdout, "\t\t\t\t\t[predicate_to_expression] Init\n");
650 fprint_pred(stdout, pred);
651 }
652 
655  entity_domain);
658  entity_domain);
661  entity_domain);
662 
663  if( (and_ent == entity_undefined) || (leq_ent == entity_undefined) ||
664  (equ_ent == entity_undefined) ) {
665  pips_internal_error("There is no entity for operators");
666  }
667 
668  for(pc = ps->inegalites; pc!=NULL; pc = pc->succ) {
669  Pvecteur pv = pc->vecteur;
671  exp2 = MakeBinaryCall(leq_ent, exp, int_to_expression(0));
672 
673  ifdebug(7) {
674  pu_vect_fprint(stdout, pv);
675  fprintf(stdout, "\t\t\t\t\t\tvec_to_exp : %s\n",
677 
678  fprintf(stdout, "\t\t\t\t\t\tINEG: exp2 = %s\n",
679  expression_to_string(exp2));
680  }
681 
682  if(exp1 == expression_undefined)
683  exp1 = exp2;
684  else
685  exp1 = MakeBinaryCall(and_ent, exp1, exp2);
686 
687 if(get_debug_level() > 6) {
688 fprintf(stdout, "\t\t\t\t\t\tINEG: exp1 = %s\n",
689  expression_to_string(exp1));
690 }
691 
692  }
693  for(pc = ps->egalites; pc!=NULL; pc = pc->succ) {
694  Pvecteur pv = pc->vecteur;
695  exp2 = MakeBinaryCall(equ_ent, make_vecteur_expression(pv),
696  int_to_expression(0));
697  if(exp1 == expression_undefined)
698  exp1 = exp2;
699  else
700  exp1 = MakeBinaryCall(and_ent, exp1, exp2);
701 
702  ifdebug(7) {
703  fprintf(stdout, "\t\t\t\t\t\tEG: exp1 = %s, exp2 = %s\n",
704  expression_to_string(exp1),
705  expression_to_string(exp2));
706  }
707  }
708 
709  ifdebug(6) {
710  fprintf(stdout, "\t\t\t\t\t[predicate_to_expression] Result: %s\n",
711  expression_to_string(exp1));
712  }
713 
714  return(exp1);
715 }
716 
717 
718 /* ========================================================================= */
719 /*
720  * void add_test(statement s, predicate cond, reference lhs rhs, int how)
721  *
722  * "s" is a statement that contains a block instruction, i.e. a list of
723  * instruction. This function adds a new assignment statement to this list
724  * conditionned by "cond". This assignment is "lhs = rhs". The kind of test
725  * instruction is determined by "how".
726  *
727  * "how" can have three different values:
728  * _ FIRST: adds a test instruction in the before last position of this
729  * list
730  * _ SECOND: this case implies that the before last instruction of this
731  * list is a test, it adds a "else if" instruction
732  * _THIRD: this case implies that the before last instruction of this
733  * list is a test, it adds a "else" instruction
734  *
735  */
736 void add_test(s, cond, lhs, rhs, how)
737 statement s;
738 predicate cond;
739 reference lhs, rhs;
740 int how;
741 {
742  list bl, l, ll = NIL, lll = NIL;
743  entity assign_ent;
744  expression lhs_exp, rhs_exp, pred_exp;
745  statement assign_s, new_s;
747 
749  pips_internal_error("Instruction MUST be a block");
750 
751  /* We construct the statement "lhs = rhs" */
754  entity_domain);
760  make_call(assign_ent,
761  CONS(EXPRESSION, lhs_exp,
763  rhs_exp, NIL)))));
764 
765  /* Then, we find where to put it... */
766  bl = instruction_block(ins);
767  for(l = bl; !ENDP(l); POP(l)) {lll = ll; ll = l;}
768  if(ll == NIL) /* This means that "bl" is empty */
769  pips_internal_error("Block is empty");
770 
771  /* ... and how. */
772  if(how == FIRST) {
773  pred_exp = predicate_to_expression(cond);
778  make_test(pred_exp,
779  assign_s,
781 
782  if(lll == NIL) /* This means that "bl" has only one instruction */
783  instruction_block(ins) = CONS(STATEMENT, new_s, bl);
784  else
785  CDR(lll) = CONS(STATEMENT, new_s, ll);
786  }
787  else if(how == SECOND) {
788  pred_exp = predicate_to_expression(cond);
789  if(lll == NIL)
790  pips_internal_error("Block has only one instruction");
791  else {
792  instruction ai;
793  test te;
794 
795  new_s = STATEMENT(CAR(lll));
796  ai = statement_instruction(new_s);
798  pips_internal_error("Instruction must be a test");
799 
800  te = instruction_test(ai);
801  while(test_false(te) != statement_undefined) {
804  pips_internal_error("Instruction must be a test");
805  te = instruction_test(aai);
806  }
811  make_test(pred_exp,
812  assign_s,
814  }
815  }
816  else if(how == THIRD) {
817  if(lll == NIL)
818  pips_internal_error("Block has only one instruction");
819  else {
820  instruction ai;
821  test te;
822 
823  new_s = STATEMENT(CAR(lll));
824  ai = statement_instruction(new_s);
826  pips_internal_error("Instruction must be a test");
827 
828  te = instruction_test(ai);
829  while(test_false(te) != statement_undefined) {
832  pips_internal_error("Instruction must be a test");
833  te = instruction_test(aai);
834  }
835  test_false(te) = assign_s;
836  }
837  }
838  else /* bad value */
839  pips_internal_error("Bad value in how");
840 }
841 
842 
843 /* ========================================================================= */
844 /*
845  * void sa_print_ins(FILE *fp, instruction i)
846  *
847  */
848 void sa_print_ins(fp, i)
849 FILE *fp;
850 instruction i;
851 {
852  switch(instruction_tag(i)) {
853  case is_instruction_block: {
854  list l = instruction_block(i);
855  fprintf(fp, "Block {\n");
856  for(; !ENDP(l); POP(l)) {
858  }
859  fprintf(fp, "} End Block\n");
860  break;
861  }
862  case is_instruction_test: {
863  test te = instruction_test(i);
864  fprintf(fp, "If (%s) {\n",
867  fprintf(fp, "}\n");
868  if(test_false(te) != statement_undefined) {
869  fprintf(fp, "Else {\n");
871  fprintf(fp, "}\n");
872  }
873  break;
874  }
875  case is_instruction_loop: {
876  loop lo = instruction_loop(i);
877  fprintf(fp, "For %s = %s, %s, %s {\n",
883  fprintf(fp, "}\n");
884  break;
885  }
886  case is_instruction_goto: {
887  fprintf(fp, "GOTO %d\n", statement_ordering(instruction_goto(i)));
888  break;
889  }
890  case is_instruction_call: {
891  call ca = instruction_call(i);
892  list l = call_arguments(ca);;
893  fprintf(fp, "Call %s with:", entity_local_name(call_function(ca)));
894  for(; !ENDP(l); POP(l)) {
895  fprintf(fp, "%s, ",
897  }
898  fprintf(fp, "\n");
899  break;
900  }
902  default: pips_internal_error("Bad instruction tag");
903  }
904 }
905 
906 
907 /* ========================================================================= */
908 /*
909  * bool full_predicate_p(predicate p)
910  */
912 predicate p;
913 {
914  Psysteme ps;
915 
916  if(p == predicate_undefined) return(true);
917 
918  ps = (Psysteme) predicate_system(p);
919 
920  if(ps == NULL) return(true);
921 
922  if((ps->egalites == NULL) && (ps->inegalites == NULL)) return(true);
923 
924  return(false);
925 }
926 
927 
928 /* ========================================================================= */
929 /*
930  * void sa_do_it(graph the_dfg)
931  *
932  */
934 graph the_dfg;
935 {
936  list l;
937 
938  /* let's have a reverse DFG, i.e. the "successors" of an instruction i are
939  * the instructions that may write the values used by i;
940  */
942 
943 if(get_debug_level() > 0) {
944 fprint_dfg(stdout, the_dfg);
945 }
946 
947  /* loop over the vertices of the DFG */
948  for(l = graph_vertices(the_dfg); !ENDP(l); POP(l)) {
949 
950  /* cv is the current vertex, cn is its number, cs is the associate
951  * statement
952  */
953  vertex cv = VERTEX(CAR(l));
958  list ciel = static_control_to_indices(stco);
959 
960  reference new_ref;
961  list clrhs, clt;
962 
963  /* cls is the list of successors of cv */
964  list cls = vertex_successors(cv);
965 
966 if(get_debug_level() > 0) {
967 fprintf(stdout, "Noeuds %d :\n", cn);
968 sa_print_ins(stdout, ci);
969 fprintf(stdout, "\n");
970 }
971 
972  if(! assignment_statement_p(cs))
973  continue;
974 
975  /* change the lhs of cs to a new array indexed by the englobing loop
976  * indices: SAIn(i1,...ip)
977  * (i1,...,ip) are the indices of the englobing loops of cs
978  */
979  lhs_subs_in_ins(ci, SAI, cn, ciel);
980 
981 if(get_debug_level() > 1) {
982 fprintf(stdout, "\tApres Subs LHS : \n");
984 }
985 
986  if(cls == NIL)
987  continue;
988 
989  /* construct the list of rhs */
990  clrhs = get_rhs_of_instruction(ci);
991 
992  /* construct the associated list of temporaries */
993  clt = build_associate_temp(clrhs);
994 
995  /* in the code, replace ci by a block new_i containing ci */
997  /* We create a new instruction with an empty block of instructions */
999  /* Then, we put the instruction "ci" in the block. */
1000  instruction_block(new_i) = CONS(STATEMENT,
1002  statement_number(cs),
1003  statement_ordering(cs),
1004  statement_comments(cs),
1005  ci),
1006  NIL);
1011  statement_instruction(cs) = new_i;
1012 
1013 if(get_debug_level() > 3) {
1014 fprintf(stdout, "\t\t\tDevient BLOCK : \n");
1015 sa_print_ins(stdout, statement_instruction(cs));
1016 }
1017  }
1018 
1019  /* loop over the list of rhs */
1020  for(; !ENDP(clrhs); POP(clrhs), POP(clt)) {
1021 
1022  /* crhs is the current ref and ct is the associate temp */
1023  reference crhs = REFERENCE(CAR(clrhs));
1024  reference ct = REFERENCE(CAR(clt));
1025  dataflow df;
1026  int m, nb_df;
1027 
1028  if(get_debug_level() > 2) {
1029  fprintf(stdout, "\t\tReference %s :\n",
1030  reference_to_string(crhs));
1031  }
1032 
1033  /* We count the number of dataflows in "cls" that contains "crhs", and
1034  * we then consider three cases: 0 dataflow, 1 dataflow, 2 or more
1035  * dataflows.
1036  */
1037  nb_df = count_dataflows_on_ref(cls, crhs, &df, &m);
1038 
1039  if(nb_df == 0) {
1040  /* Nothing is changed concerning this rhs */
1041 
1042 if(get_debug_level() > 2) {
1043 fprintf(stdout, "\t\tZero dataflow :\n");
1044 sa_print_ins(stdout, statement_instruction(cs));
1045 }
1046 
1047  }
1048  else if(nb_df == 1) {
1049  /* pred is the cond of df, L is the transformation of df */
1052 
1053 if(get_debug_level() > 2) {
1054 fprintf(stdout, "\t\tUn seul dataflow :\n");
1055 sa_print_ins(stdout, statement_instruction(cs));
1056 }
1057 
1058  new_ref = build_new_ref(IS_NEW_ARRAY, m, L, crhs);
1059 
1060  if(full_predicate_p(pred)) {
1061  /* change in ci the occurrences of crhs by SAIm[L] */
1062  rhs_subs_in_ins(ci, crhs, new_ref);
1063 
1064 if(get_debug_level() > 3) {
1065 fprintf(stdout, "\t\t\tFull predicate :\n");
1066 sa_print_ins(stdout, statement_instruction(cs));
1067 }
1068  }
1069  else {
1070  rhs_subs_in_ins(ci, crhs, ct);
1071  add_test(cs, pred, ct, new_ref, FIRST);
1072  add_test(cs, predicate_undefined, ct, crhs, THIRD);
1073 
1074 if(get_debug_level() > 2) {
1075 fprintf(stdout, "\t\t\tNot full predicate :\n");
1076 sa_print_ins(stdout, statement_instruction(cs));
1077 }
1078  }
1079  }
1080  else {
1081  int nt = 0; /* number of tests currently added */
1082  list lls = cls;
1083 
1084 if(get_debug_level() > 2) {
1085 fprintf(stdout, "\t\tAu moins deux dataflows :\n");
1086 }
1087  for(; !ENDP(lls); POP(lls)) {
1088  successor suc = SUCCESSOR(CAR(lls));
1089 
1090  list ldf = dataflows_on_ref(suc, crhs);
1092 
1093 if(get_debug_level() > 2) {
1094 fprintf(stdout, "\t\tArc pointe' vers %d :\n", m);
1095 }
1096 
1097  for(; !ENDP(ldf); POP(ldf)) {
1098  dataflow df = DATAFLOW(CAR(ldf));
1099 
1100  /* pred is the cond of df, L is the transformation of df */
1103 
1104  /* change in ci the occurrences of crhs by ct; */
1105  rhs_subs_in_ins(ci, crhs, ct);
1106 
1107 if(get_debug_level() > 3) {
1108 fprintf(stdout, "\t\t\tApres substitution dans RHS :\n");
1109 sa_print_ins(stdout, statement_instruction(cs));
1110 }
1111 
1112  new_ref = build_new_ref(IS_NEW_ARRAY, m, L, crhs);
1113 
1114  /* First test */
1115  if(nt == 0) {
1116  /* "if(pred) ct = SAIm[L(i1,...,ip)]", just before ci in cs */
1117  add_test(cs, pred, ct, new_ref, FIRST);
1118  nt++;
1119 
1120 if(get_debug_level() > 3) {
1121 fprintf(stdout, "\t\t\tPremier test :\n");
1122 sa_print_ins(stdout, statement_instruction(cs));
1123 }
1124  }
1125  else {
1126  /* "else if(pred) ct = SAIm[L(i1,...,ip)]", just before ci in cs */
1127  add_test(cs, pred, ct, new_ref, SECOND);
1128 
1129 if(get_debug_level() > 3) {
1130 fprintf(stdout, "\t\t\tDeuxieme test :\n");
1131 sa_print_ins(stdout, statement_instruction(cs));
1132 }
1133  }
1134  }
1135  }
1136  /* "else ct = crhs", just before ci in cs */
1137  add_test(cs, predicate_undefined, ct, crhs, THIRD);
1138 
1139 if(get_debug_level() > 3) {
1140 fprintf(stdout, "\t\t\tDernier test :\n");
1141 sa_print_ins(stdout, statement_instruction(cs));
1142 }
1143  }
1144  }
1145  }
1146 }
1147 
1148 
1149 /* ========================================================================= */
1150 /*
1151  * void single_assign((char*) mod_name):
1152  *
1153  */
1154 void single_assign(mod_name)
1155 char* mod_name;
1156 {
1157  extern int tc;
1158 
1159  graph the_dfg;
1160  entity ent;
1161  static_control stco;
1164 
1165  /* Initialize debugging functions */
1166  debug_on("SINGLE_ASSIGN_DEBUG_LEVEL");
1167  if(get_debug_level() > 0)
1168  user_log("\n\n *** COMPUTE SINGLE_ASSIGN for %s\n", mod_name);
1169 
1170  /* We get the required data: module entity, code, static_control, dataflow
1171  * graph.
1172  */
1173  ent = local_name_to_top_level_entity( mod_name );
1174 
1175  if(ent != get_current_module_entity()) {
1178  }
1179 
1180  mod_stat = (statement) db_get_memory_resource(DBR_CODE, mod_name, true);
1181  STS = (statement_mapping) db_get_memory_resource(DBR_STATIC_CONTROL,
1182  mod_name, true);
1185 
1186  if ( stco == static_control_undefined) {
1187  pips_internal_error("This is an undefined static control !");
1188  }
1189  if ( !static_control_yes( stco )) {
1190  pips_internal_error("This is not a static control program !");
1191  }
1192 
1193  /* The DFG */
1194  the_dfg = adg_pure_dfg((graph) db_get_memory_resource(DBR_ADFG, mod_name, true));
1195 
1196  if(get_debug_level() > 0) {
1197  fprint_dfg(stdout, the_dfg);
1198  }
1199 
1200  /* The temporaries counter */
1201  tc = 0;
1202 
1203  sa_do_it(the_dfg);
1204 
1205  DB_PUT_MEMORY_RESOURCE(DBR_CODE, strdup(mod_name), (char*) mod_stat);
1206 
1207  if(get_debug_level() > 0) {
1208  user_log("\n\n *** SINGLE_ASSIGN done\n");
1209  }
1210 
1212 
1213  debug_off();
1214 }
1215 
void user_log(const char *format,...)
Definition: message.c:234
graph make_graph(list a)
Definition: graph.c:56
successor make_successor(arc_label a1, vertex a2)
Definition: graph.c:98
vertex make_vertex(vertex_label a1, list a2)
Definition: graph.c:140
call make_call(entity a1, list a2)
Definition: ri.c:269
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
storage make_storage(enum storage_utype tag, void *val)
Definition: ri.c:2273
value make_value(enum value_utype tag, void *val)
Definition: ri.c:2832
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
dimension make_dimension(expression a1, expression a2, list a3)
Definition: ri.c:565
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
syntax make_syntax(enum syntax_utype tag, void *val)
Definition: ri.c:2491
type make_type(enum type_utype tag, void *val)
Definition: ri.c:2706
static int count
Definition: SDG.c:519
graph adg_pure_dfg(graph in_gr)
======================================================================
Definition: adg_graph.c:56
void fprint_dfg(FILE *fp, graph obj)
===========================================================================
static hash_table STS
The "STS" global variable is the hash table that maps the static_control on the statements.
Definition: adg_read_paf.c:155
statement adg_number_to_statement(int in_nb)
======================================================================
Definition: adg_utils.c:461
static int num
Definition: bourdoncle.c:137
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
string make_entity_fullname(const char *module_name, const char *local_name)
END_EOLE.
Definition: entity_names.c:230
void * malloc(YYSIZE_T)
#define successor_vertex(x)
Definition: graph.h:118
#define vertex_undefined
Definition: graph.h:128
#define successor_arc_label(x)
Definition: graph.h:116
#define vertex_vertex_label(x)
Definition: graph.h:152
#define vertex_successors(x)
Definition: graph.h:154
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
#define graph_vertices(x)
Definition: graph.h:82
#define graph_undefined
Definition: graph.h:60
#define VERTEX(x)
VERTEX.
Definition: graph.h:122
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#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
#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
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 assignment_statement_p(statement)
Test if a statement is an assignment.
Definition: statement.c:135
#define ADD_ELEMENT_TO_LIST(_list, _type, _element)
Definition: icfg-local.h:50
static list verlist
of vertex
Definition: icfg_scan.c:107
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_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
int get_debug_level(void)
GET_DEBUG_LEVEL returns the current debugging level.
Definition: debug.c:67
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define MODULE_SEP_STRING
Definition: naming-local.h:30
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
hash_table statement_mapping
these macros are obsolete! newgen functions (->) should be used instead
Definition: newgen-local.h:42
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
#define string_undefined
Definition: newgen_types.h:40
char * string
STRING.
Definition: newgen_types.h:39
#define UU
Definition: newgen_types.h:98
void pu_vect_fprint(FILE *, Pvecteur)
===========================================================================
Definition: print.c:446
list static_control_to_indices(static_control)
package mapping : Alexis Platonoff, july 1993
Definition: utils.c:1037
void reset_current_stco_map(void)
========================================================================
Definition: utils.c:2423
static_control get_stco_from_current_map(statement)
========================================================================
Definition: utils.c:2429
void fprint_pred(FILE *, predicate)
===========================================================================
Definition: print.c:287
void set_current_stco_map(statement_mapping)
========================================================================
Definition: utils.c:2408
void fprint_dataflow(FILE *, int, dataflow)
===========================================================================
Definition: print.c:229
#define static_control_loops(x)
Definition: paf_ri.h:757
#define DATAFLOW(x)
DATAFLOW.
Definition: paf_ri.h:308
#define dataflow_transformation(x)
Definition: paf_ri.h:342
#define dfg_arc_label_dataflows(x)
Definition: paf_ri.h:378
#define static_control_yes(x)
Definition: paf_ri.h:753
#define static_control_undefined
Definition: paf_ri.h:727
#define dataflow_governing_pred(x)
Definition: paf_ri.h:344
#define dfg_vertex_label_statement(x)
Definition: paf_ri.h:413
#define dataflow_reference(x)
Definition: paf_ri.h:340
#define dataflow_undefined
Definition: paf_ri.h:314
void fprint_list_of_exp(FILE *fp, list exp_l)
void fprint_list_of_exp(FILE *fp, list exp_l): prints in the file "fp" the list of expression "exp_l"...
Definition: expression.c:229
string reference_to_string(reference r)
Definition: expression.c:87
string expression_to_string(expression e)
Definition: expression.c:77
graph the_dfg
The placement function.
Definition: prgm_mapping.c:99
#define SA_MODULE_NAME
#define SAT
#define IS_NEW_ARRAY
#define SAI
#define IS_TEMP
#define ENTITY_ASSIGN_P(e)
#define EQUAL_OPERATOR_NAME
#define make_entity(n, t, s, i)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define AND_OPERATOR_NAME
FI: intrinsics are defined at a third place after bootstrap and effects! I guess the name should be d...
#define is_instruction_block
soft block->sequence transition
#define instruction_block(i)
#define LESS_OR_EQUAL_OPERATOR_NAME
#define ASSIGN_OPERATOR_NAME
Definition: ri-util-local.h:95
#define make_empty_statement
An alias for make_empty_block_statement.
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
list entities_to_expressions(list l_ent)
build a list of expressions from a list of entities
Definition: entity.c:2703
entity entity_empty_label(void)
Definition: entity.c:1105
expression make_vecteur_expression(Pvecteur pv)
make expression for vector (Pvecteur)
Definition: expression.c:1650
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
basic basic_of_reference(reference)
Retrieves the basic of a reference in a newly allocated basic object.
Definition: type.c:1459
#define loop_body(x)
Definition: ri.h:1644
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
#define LOOP(x)
LOOP.
Definition: ri.h:1606
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#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 statement_ordering(x)
Definition: ri.h:2454
#define instruction_goto(x)
Definition: ri.h:1526
#define test_false(x)
Definition: ri.h:2837
@ is_value_unknown
Definition: ri.h:3035
@ 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 statement_label(x)
Definition: ri.h:2450
@ is_storage_rom
Definition: ri.h:2494
#define entity_undefined
Definition: ri.h:2761
#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 predicate_undefined
Definition: ri.h:2046
#define test_true(x)
Definition: ri.h:2835
#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 statement_comments(x)
Definition: ri.h:2456
#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 instruction_test(x)
Definition: ri.h:1517
@ is_type_variable
Definition: ri.h:2900
#define statement_number(x)
Definition: ri.h:2452
#define expression_syntax(x)
Definition: ri.h:1247
#define predicate_system(x)
Definition: ri.h:2069
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
#define loop_index(x)
Definition: ri.h:1640
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
struct Ssysteme * Psysteme
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
static int tc
Internal variables
Definition: single_assign.c:97
void single_assign(char *mod_name)
=========================================================================
void sa_print_ins(FILE *fp, instruction i)
=========================================================================
vertex my_dfg_in_vertex_list(list l, vertex v)
=================================================================
dfg_arc_label arc_label
list get_rhs_of_instruction(instruction ins)
=========================================================================
expression predicate_to_expression(predicate pred)
=========================================================================
void rhs_subs_in_ins(instruction ins, reference r1, reference r2)
=========================================================================
#define FIRST
Name : single_assign.c Package : reindexing Author : Alexis Platonoff Date : febuary 1994 Historic :
Definition: single_assign.c:90
void ref_subs_in_exp(expression exp, reference r1, reference r2)
=========================================================================
list references_of_expression(expression exp)
=========================================================================
graph my_dfg_reverse_graph(graph g)
======================================================================
void lhs_subs_in_ins(instruction ins, string SA, int n, list subscripts)
=========================================================================
dfg_vertex_label vertex_label
Local defines.
list dims_of_nest(int n)
=========================================================================
#define SECOND
Definition: single_assign.c:91
void add_test(statement s, predicate cond, reference lhs, reference rhs, int how)
=========================================================================
#define THIRD
Definition: single_assign.c:92
int count_dataflows_on_ref(list ls, reference r, dataflow *df, int *m)
=========================================================================
bool full_predicate_p(predicate p)
=========================================================================
list build_successors_with_rhs(list ls, reference r)
=========================================================================
list build_associate_temp(list lr)
=========================================================================
reference build_new_ref(int kind, int n, list subscripts, reference old_r)
=========================================================================
entity create_entity(string name, variable v)
=========================================================================
void sa_do_it(graph the_dfg)
=========================================================================
list dataflows_on_ref(successor suc, reference r)
=========================================================================
Definition: pip__tab.h:30
Pvecteur vecteur
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
Pcontrainte egalites
Definition: sc-local.h:70
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
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